Details
Description
There are CIP attributes that are notified to the user and there are attributes that are remanently stored.
Per default the two sets have been identical, but this has changed due to EtherNet/IP Scanner requirements.
For instance, the bitmasks of the CC object are notified for the Master Status Block now, although they are not stored remanently.
Also, the user can enable notification for a lot (most) of attributes, but he cannot enable remanent storing.
Also, there is the "bypass NV" flag.
Thus, it makes sense to split that logic into distinct building blocks.
The attribute flags may be extended, so that, next to EIP_OBJECT_TREAT_NOTIFY, we also will have EIP_OBJECT_TREAT_REMANENT.
The stack then should call distinct callbacks of the AP task to achieve remanent storing and notification as independent functions.
In fact, both calls should then always be blocking the current operation, so that any further action in the protocol stack is blocked until the remanent storing is completed or the host has replied to the indication packet. This ensures that we do not run into an out-of-packets scenario in case the host application is not processing the indications fast enough.
This would limit the number of packets that are used in parallel to the sum of requests the stack can handle in parallel that are notified. These two numbers should be well-dimensioned, so that no overflow can occur and the stack blocks (or error-replies) towards the network whenever the host application is busy (which still is an overload scenario that can be handled by the host order timeout mechanism).
Currently, we have a lot of points where we asynchronously generate indications due to events in the stack, so that the AP task can run quite easily out of resources and indications are temporarily not generated, which is potentially a bad thing. We do a logbook entry for GCI in such cases, but the AP task just silently fails here.
Generally speaking we should determine the number of CIP_OBJ_ASYNC_REQUEST_T in the system, since this is the number of parallel requests in the stack. Each of these CIP_OBJ_ASYNC_REQUEST_T 's should use at maximum one packet in parallel and block until that packet has been processed. Synchronous operations in the stack should not use packets at all.
So:
* Split-up the notification callback into a notification callback and a remanent storing callback.
* Have a new attribute flag EIP_OBJECT_TREAT_REMANENT
* The remanent storing shall be synchronous always (continue in control flow not before it has been finished)
* When we say control flow, we mean the context of one asynchronous request in the stack CIP_OBJ_ASYNC_REQUEST_T. Determine and limit the number of these requests. The callbacks for notification and/or remanent storing should be stored in this object. Synchronous operations shall not store remanently and shall not notify the host application.
* The notifications should be synchronous so that the maximum number of indication packets is limited to a hard upper valu (e.g. the number of asynchronous requests).
* Another meaningful split would be EIP_OBJECT_TREAT_NOTIFY_AP_TASK and EIP_OBJECT_TREAT_NOTIFY_HOST, where EIP_OBJECT_TREAT_NOTIFY_APTASK is a simple callback and EIP_OBJECT_TREAT_NOTIFY_HOST is an asynchronous, blocking call which calls back on completion.
We have never been well dimensioned with reagrds to these resource limits. With the recent increase on the number of connections for both the adapter and scanner, we are way bout of bounds. There are at least 80 parallel requests in the stack where each can generate multiple remanent storing orders and change notifications in parallel. We run out of packets very very easily.