SoAd - Socket Adaptor Overview

Micael Coutinho,autosarbswsoad

As you probably know, TCP / IP is the most established technology for telecommunication with ethernet. Its extensive suite of protocols covers addressing for applications, logical addressing of endpoints and physical addressing, having dynamic configuration and routing at its core. In contrast, we are used in Autosar to have static configuration of communication between source and sink, and intransigent / predictable run-time behaviour. Both are not compatible.

Therefore, Socket Adaptor was created, to act as a middle layer in between both communication paradigms. It defines a static communication configuration, with the information required by the Autosar stack and leaves open points that can be updated during runtime, while also abstracting the callback architecture of socket-based communication typically found in TCP / IP. This is achieved by providing an interface between the Autosar communication services, governed by I-PDUs (you can learn about I-PDUs in our posts COM - Demystifying I-PDU Transmission Modes (opens in a new tab) and other ones we have on our website), and the socket communication of TCP / IP, mapping I-PDU IDs to socket connections and vice-versa.

SoAd implements the following features:

Socket Adaptor - Dependencies With Other Modules

As you can see in the figure below (where I-PDU communication exchanges are in blue), the upper layers that interact with SoAd all communicate via I-PDUs with it. These are the PduR (which you can learn more about in this post Demystifying Autosar PDU Router. A Comprehensive Guide to Routing, Handling, and Buffering (opens in a new tab)), DoIP, Sd, UDP NM and Xcp (learn about it in our post What is XCP (opens in a new tab)). These are then connected via SoAd with the Autosar TCP / IP stack (TcpIp), which implements the main TCP / IP protocols. Lastly, the EthSM is used to control the state of SoAd, and the IdsM is used to report security events to the SoAd:

Dependencies between the Socket Adaptor (SoAd) and other BSW modules

Dependencies between the Socket Adaptor (SoAd) and other BSW modules

Socket Adaptor Limitations

Of course, there are some limitations that SoAd has addressed, or it just cannot fulfil. The most obvious is the overhead: TCP / IP data adds around 60 bytes of overhead. If you are transmitting small amounts of data, it is just unacceptable, unless you group multiple I-PDUs and send them all in one go. This is made possible through the addition of a PDU header, comprised of an ID and length. This way, multiple PDUs are sent via a single socket connection.

Moreover, assignment of TCP and UDP port numbers is the responsibility of the implementation, just as the management of IP addresses. These are static or handled dynamically through DHCP or a similar protocol. It also does not specify a physical layer or data rate.

Laslty, SOME / IP protocol and interface versions are not checked by SoAd, even though they should be, as described in the SOME / IP specification. Although, the service and method IDs are checked, and if they are not valid the error SOAD_E_INV_PDUHEADER_ID will be set.

Opening and Closing Socket Connections

One important feature of the Socket Adapter is socket handling, as sockets are the backbone of the communication via TCP / IP. Depending on the usage of UDP or TCP, these provide connectionless or connection-oriented communication, respectively. Two stations can establish one or more socket connections, where on each side a socket will be comprised of an address and a port, and their combination will be a connection.

SoAd adds to each socket connection some parameters, such as the transport protocol and its own parameters, the presence or absence of a PDU header, buffer needs, connection setup, among other things. Each socket connection within SoAd has a unique identifier, named SoConId. It is also possible to group multiple socket connections with similar parameters into socket connection groups.

The upper layers can request SoAd to open a socket through the API SoAd_OpenSoCon, and request to close it via SoAd_CloseSoCon. These APIs will set a flag to signal the request, and it will be handled within the cyclic SoAd_MainFunction.

The remote address of a socket connection can be modified via the API SoAd_SetRemoteAddr, but only if none of the conditions apply:

A socket connection is eligible to be opened in the main function if all the following points are met:

Regarding socket connection closing, it will also occur within the SoAd_MainFunction, when a request to close the socket is issued via the API SoAd_CloseSoCon and no upper layer requested to keep the socket open, through SoAd_OpenSoCon, or if the parameter within SoAd_CloseSoCon is set to true.

If the socket closed through the SoAd_CloseSoCon API call, the state of the socket connection will be set to SOAD_SOCON_OFFLINE. If it is closed for some other reason, the socket will transition to the state SOAD_SOCON_RECONNECT. Lastly, while the socket is being closed, all active TP sessions are terminated and a notification is issued to the upper layers involved, via an API call to <Upper_layer>_[SoAd][Tp]RxIndication (delivering E_OK if all the received data has been delivered to the upper layer), further transmissions and receptions are discarded and the related TcpIp sockets are closed.

There is a bit more to this. As for socket connection opening, closing and the SoAd state machine, we will cover them more extensively in a future post, so stay tuned for that.

Message Transmission and Confirmation via IF and TP API

For transmission of PDUs via TCP or UDP sockets, the Socket Adaptor defines a PDU route, which links a PDU to a socket connection. It defines, through either of the parameters SoAdPduRoute or SoAdPduRouteDest the route of a PDU from an upper layer to the socket on the TcpIp stack depicted in the socket connection, SoAdSocketConnection, or socket connection group SoAdSocketConnectionGroup. The upper layer can use the IF-API or the TP-API for the transmission request and to provide the necessary data for it to take place.

When using the IF API, after the upper layers signals its request to transmit data, via an API call to SoAd_IfTransmit, the Socket Adaptor verifies the respective socket connection through the parameter TxPduId and calls the necessary TcpIp API to transmit the PDU if the PDU provided is not empty or the configuration parameter SoAdPduHeaderEnable is set to true, otherwise, it will stop the process and return E_NOT_OK.

Moreover, for UDP sockets, SoAd will use the TcpIp_UdpTransmit API to transmit the PDU, specifying the SocketId and the remote address (it will be needed as there are no preliminary connection steps like in TCP) contained in the SocketConnection, and the length of the PDU.

For TCP, the underlying TcpIp API is TcpIp_TcpTransmit, including the parameters SocketId, PDU length and ForceRetrieve (set to true). Inside both APIs, the TcpIp module will use the API SoAd_CopyTxData to retrieve the data for the PDU transmission. If the PDU buffer pointer from the upper layer (or SDU), PduInfoPtr->SduDataPtr, came into the Socket Adaptor set to NULL_PTR, it will retrieve the PDU data from the upper layer through an API call to <Upper_layer>[SoAd][If]TriggerTransmit.

For the confirmation of messages, the Socket Adaptor will call the API <Upper_layer>[SoAd][If]TxConfirmation, in case of a UDP socket connection, within the next SoAd_MainFunction call after the TcpIp_UdpTransmit has returned successfully. As for TCP, the same API will be called when all transmit requests have been confirmed by the receiver. Even when multiple requests are issued in succession, TCP will only confirm when the last request is completed.

Another option for the transmission of messages is through SoAd_IfRoutingGroupTransmit. This API will store a transmission request for each SoAdPduRouteDest referenced by a routing group through the id parameter, to be processed within the SoAd_MainFunction. Another variant of this API is SoAd_IfSpecificRoutingGroupTransmit, that specifies a socket connection SoConId, from which the PDUs shall be transmitted.

Within the SoAd_MainFunction call, the data to be transmitted will be gathered from the upper layers via the API <Upper_layer>[SoAd][If]TriggerTransmit into the PduInfoType.SduDataPtr and PduInfoType.SduDataLength and transmitted via the respective socket connection.

The last option for transmission is the TP-API. When an upper layer requests a transmission through it, the SoAd checks the length of the message (and discards it if the length is set to zero), checks the parameter TxPduId provided via the API call to SoAd_TpTransmit, to select the correct SoAdPduRoute (which contains one or more SoAdPduRouteDest values that will provide the SoAdSocketConnection to where the PDU should be transmitted) and stores the TP transmission request to be processed within the SoAd_MainFunction.

The API <Upper_layer>[SoAd][Tp]CopyTxData will be called repeatedly to retrieve the data and its length to be transmitted (where the value of the argument AvailableDataPtr gets incremented in each call to the length value retrieved in the former API call, starting with zero, and the data is stored into the buffer provided in BufPtr), to then, depending on the connection get data itself and forward it to the TcpIp module with the correct transmission API.

When a UDP socket is in use, the TcpIp_UdpTransmit will be called when all the data has been retrieved through one or more main function calls. If the <Upper_layer>[SoAd][Tp]CopyTxData API fails with the return value BUFREQ_E_NOT_OK, then the process is aborted, and the upper layer is notified via the API <Upper_layer>_[SoAd][Tp]TxConfirmation with the status E_NOT_OK. The failure will not affect the socket connection state.

For a TCP socket, the same will be used to retrieve the data and its length, with the argument ForceRetrieve set to false. The particularity with a TCP socket is that in case the API call to <Upper_layer>[SoAd][Tp]CopyTxData fails with BUFREQ_E_NOT_OK, the TCP socket connection will be closed within the next SoAd_MainFunction, and the new transmission requests and receptions will be discarded.

Moreover, when the multiple respective TcpIp_UdpTransmit or TcpIp_TcpTransmit return, the Socket Adaptor will forward this status via the <Upper_layer>_[SoAd][Tp]TxConfirmation callback.

Additionally, the TCP will forward the confirmation only once, when all the TP PDU data has been transmitted, if the parameter SoAdSocketTcpImmediateTpTxConfirmation is set to false, or one for each transmission via the aforementioned APIs if the parameter value is set to true, which is the behaviour for UDP socket connections.

Lastly, a new SoAd_TpTransmit call can be performed within the confirmation API for the same PDU, creating a new TP session.

There are some more variations, depending upon the parameters and the nPdu feature. Today we will not go over them, for the sake of keeping this article short and sweet, but these topics will be covered in future posts.

Message Reception

Regarding the message reception from TCP and UDP sockets, the Socket Adaptor specified a socket route that is related to a socket connection. This route, specified by either of the parameters SoAdSocketRoute or SoAdSocketRouteDest, defines the route from a socket of the TcpIp module to the upper layer. The upper layer can then use the IF-API or TP-API to receive the PDU.

The reception process for both socket types starts with checking the socket connection and routes to be involved, through the SocketId parameter received in the SoAd_RxIndication. Then, the messages are filtered according to the message acceptance policy and converted into a PDU.

After this conversion, if the PDU length is zero and PDU header mode is not enabled and the upper layer is not TP, the PDU is discarded. Otherwise, the corresponding reception functions for the upper layer specified in the parameter SoAdRxUpperLayerType within the socket destination route SocketRouteDest get called.

Looking specifically at UDP sockets, these can contain more than one socket connection belonging to a socket connection group, which in this case all of the socket connections in the group share the same socket, and the socket connection is to be chosen according to the best match algorithm.

Concerning message reception on TCP sockets, the Socket Adaptor has to confirm all data forwarded to the upper layers or discarded internally, via an API call to SoAd_RxIndication, taking place within SoAd_RxIndication or SoAd_MainFunction.

When it comes to the behaviour of both the IF and TP-PDUs, these have to be processed independently and according to their type and time of arrival, per socket connection. When using a reception buffer, the order of the data is also to be preserved, and if the size of the received data is larger than the available space in the reception buffer, the error SOAD_E_BUFS is raised. Moreover, when a PDU is discarded, the optional configuration parameter SoAdGetAndResetMeasurementDataApi can be selected, enabling SoAd to increment the measurement data upon each discard occurrence.

Upon SoAd_RxIndication, the reception of a PDU and its forwarding to an upper layer via the IF-API is resumed in the following steps:

As for the reception of PDUs with the TP-API without PDU header mode, it will also take place within SoAd_RxIndication. There are two different possibilities for it.

In the first one, if a TP reception is already taking place on the relevant socket connection and SoAd reception buffer can store all the received data from TcpIp, all the data will be copied into the buffer, for later processing within the SoAd_MainFunction.

For the second case, the SoAd reception buffer is empty. In regard to the TP data for this socket connection:

As a side note, you can cancel transmission and reception of TP sessions via the APIs SoAd_TpCancelReceive and SoAd_TpCancelTransmit. Doing so will make the SoAd_MainFunction close the socket connection.

The PDU header configuration has implications on the overall reception behavior. We did not forget about this, let us cover it in another article, where we will take a deeper dive.

Closing Thoughts

As you could verify, we have barely scratched the surface and there is already a gigantic flow of information in this post. Truth is, the very basics are covered. But there is more, such as nPDU feature, configuration parameters, best match algorithm, acceptance policy, header mode, routing groups and security event reporting to cover. These will come in soon in future posts, so stay tuned!

If you like this sort of longer content, get in line for the waiting list on the upcoming eBook about Classic Autosar!

Author: Micael Coutinho (opens in a new tab)

References:

© AutosarToday —@LinkedIn