This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM2432: DLR Sign_On Overflow test (CT22) - Handling of Unicast Continuous Sign_On frame

Part Number: AM2432

Question

We are currently working on DLR conformance (ODVA CT22), and we have a question regarding the correct handling of the Sign_On Overflow scenario, specifically for Unicast Continuous Sign_On frames.


Background

During execution of:

  • CT22 DLR Emulated Test 2.3:
    Sign_On Frame – Overflow

our DUT fails at:

  • Analyze Sign_on Unicast Results

According to the test result:

"Observed 1 Sign_on frames for Sequence ID 0x15; Expected at least 2 Sign_on frames" 


Observed Behavior

From packet capture:

  1. The CT tool first sends a multicast Sign_On frame exceeding maximum size (~1512 bytes).
  2. Then, it sends a unicast Sign_On frame (Continuous Sign_On) to the DUT (~60 bytes).
  3. However, the DUT does not transmit any response frame.

Current Implementation Issue

From our analysis of the TI SDK (EIP_processProtocolFrames), it appears that DLR frame detection is performed based on:

Destination MAC == 01:21:6C:00:00:02 (DLR multicast)

As a result:

  • Unicast Sign_On (Continuous Sign_On) frames are not recognized as DLR frames
  • These frames are discarded in EIP_processProtocolFrames()

CIP Specification Reference

According to CIP Specification, Volume 2, Section 9-5.5.4 (Sign_On Process):

  • When the Sign_On frame exceeds maximum size:

    • A node does not append its address
    • Instead, it sends the Sign_On frame directly to the active supervisor (unicast)
  • Upon receiving this unicast Sign_On:

    • The supervisor restarts the Sign_On process
    • It sends a new Sign_On frame directly (unicast) to the node
    • The node shall:
      • Add its address
      • Forward the Sign_On frame again (multicast)

This implies that unicast Sign_On frames must be handled as valid DLR frames, not discarded.


Questions

We tried the following modifications, and the test passed, but we are not confident that these are correct implementations.

(1) DLR frame detection

We modified the code so that:

  • Unicast Sign_On frames are also processed by EIP_DLR_processDLRFrame()

Question: What is the correct way to identify DLR frames in this case?
Is there any recommended method (e.g., EtherType, DLR Frame Type)?


(2) Destination MAC handling

To avoid CT failure:

  • We modified the destination MAC address to the DLR multicast address before forwarding

Question: Is rewriting the destination MAC address to multicast the correct behavior?
Or should the original unicast destination be preserved?


(3) signOnRcvdFlag handling

In the SDK implementation:

  • EIP_DLR_processDLRFrame() returns without processing if signOnRcvdFlag == FALSE

We observed that:

  • Even after accepting unicast Sign_On frames, signOnRcvdFlag remains FALSE
  • As a workaround, we temporarily removed this check to pass the test

Question:

What is the correct condition and timing to set signOnRcvdFlag to TRUE?

  • Should it be set upon receiving:
    • multicast Sign_On?
    • unicast Sign_On (continuous)?
    • both?

Environment

  • SDK: Industrial Communications SDK for AM243x 11.00.00.08

Summary

Our main concern is:

  • Proper handling of Unicast Continuous Sign_On frames
  • Compliance with CIP Sign_On overflow behavior
  • Alignment with TI SDK intended implementation

Any guidance on correct design or reference implementation would be greatly appreciated.

 

  • Hi  

    Before proceeding with the issue analysis - one thing that I wanted to confirm - what is the ENIP Protocol stack that is being used here? 

    Is it the ENIP Stack from TI?

    In the meantime , I will do the required analysis from the Driver/Firmware POV.

    Regards
    Archit

  • Hi  

    Thank you for your response.

    We are not using the ENIP stack provided by TI.
    Instead, we are using a third-party EtherNet/IP stack integrated on top of the TI SDK.

    Best regards,

    Akihiro Tamura

  • Hi ,

    from PRU Firmware and ICSS DLR driver point of view, the issue should be resolved in the Upcoming release.
    For your reference, I have attached the test result (using TI's EIP Stack).

    https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/908/DLR_5F00_EmulatedTest.7z

    Best regards,
    Pourya

  • Hi Pourya,

    So, it looks next release is capable to pass the DLR conformance test.

    1. Could you help answer his question as below?
    2. If patch is available, is it possible to share it?

    [Questions]

    Questions

    We tried the following modifications, and the test passed, but we are not confident that these are correct implementations.

    (1) DLR frame detection

    We modified the code so that:

    • Unicast Sign_On frames are also processed by EIP_DLR_processDLRFrame()

    Question: What is the correct way to identify DLR frames in this case?
    Is there any recommended method (e.g., EtherType, DLR Frame Type)?


    (2) Destination MAC handling

    To avoid CT failure:

    • We modified the destination MAC address to the DLR multicast address before forwarding

    Question: Is rewriting the destination MAC address to multicast the correct behavior?
    Or should the original unicast destination be preserved?


    (3) signOnRcvdFlag handling

    In the SDK implementation:

    • EIP_DLR_processDLRFrame() returns without processing if signOnRcvdFlag == FALSE

    We observed that:

    • Even after accepting unicast Sign_On frames, signOnRcvdFlag remains FALSE
    • As a workaround, we temporarily removed this check to pass the test

    Thank you.

    Best Regards,

    Kasai

  • (1) DLR frame detection

    We modified the code so that:

    • Unicast Sign_On frames are also processed by EIP_DLR_processDLRFrame()

    Question: What is the correct way to identify DLR frames in this case?
    Is there any recommended method (e.g., EtherType, DLR Frame Type)?

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    On our side we are identifying in several steps:

    1. EtherType (0x80E1) - in first step compare any frame for DLR EtherType

    2. Compare multicast MAC - in second step compare whether MAC address is DLR Multicast address.

    • Check for exact multicast MAC address (01:21:6C:00:00:02) other multicast addresses are not handled for Sign_On frames
    • If  MAC == 01:21:6C:00:00:02 then check DLR Frame Type for Sign_On Type (7) and handle with EIP_DLR_processDLRFrame call
          

    3. Compare for unicast MAC - in third step compare whether the MAC address is address of your device, other unicast MAC's are not handled for Sign_On frames

    • If MAC == "MAC of your device", then check DLR Frame Type for Sign_On Type (7) and handle with EIP_DLR_processDLRFrame call

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    (2) Destination MAC handling

    To avoid CT failure:

    • We modified the destination MAC address to the DLR multicast address before forwarding

    Question: Is rewriting the destination MAC address to multicast the correct behavior?
    Or should the original unicast destination be preserved?

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    No modifications are needed, but you should handle only unicast MAC which is equal to MAC of your device as is written in 1st answer.

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    (3) signOnRcvdFlag handling

    In the SDK implementation:

    • EIP_DLR_processDLRFrame() returns without processing if signOnRcvdFlag == FALSE

    We observed that:

    • Even after accepting unicast Sign_On frames, signOnRcvdFlag remains FALSE
    • As a workaround, we temporarily removed this check to pass the test

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Not sure with this one because in actual implementation there is no if condition for signOnRcvdFlag. But I will suggest first to remove workaround and handle just unicast MAC address of the device. If problem persists just please ask again and I will forward it to responsible colleague.

    With best regards
    Jiri Biel

  • Hi, 

    Just to add a couple of more points here: 

    • In the Industrial Comms SDK 11.00 , the PRU firmware does not send the DLR Unicast Signon frames in the highest priority queue. This is fixed in the latest firmware which will be included in the upcoming Industrial Comms SDK 2026 release.
      • Regarding sharing the files ahead of the release - I am checking this internally with the team.
      • However, as an immediate workaround - a check can be added in the Reception callback for the Sign-On frame and calling the ICSS DLR Driver function.

    (2) Destination MAC handling

    To avoid CT failure:

    • We modified the destination MAC address to the DLR multicast address before forwarding

    Question: Is rewriting the destination MAC address to multicast the correct behavior?
    Or should the original unicast destination be preserved?

    According to the Spec:

    It is possible that the number of nodes in the ring large enough that all nodes’ addresses do not fit in the Sign_On frame. When a node receives the Sign_On frame, if adding the node’s address would exceed the maximum frame size, the node does not add its address, but saves the port through which the frame was received and sends the Sign_On frame directly to the active ring supervisor.


    When the ring supervisor receives the Sign_On frame sent to its unicast MAC address, it assumes this is due to the Sign_On frame size reaching its maximum. The supervisor restarts the Sign On process by sending a new Sign_On frame directly (unicast) to the node from which it received the unicast Sign_On frame.


    Upon receiving the new Sign_On frame from the ring supervisor, the ring node adds its address to the Sign_On frame. The node then sends the Sign_On frame (multicast) through its other port than the saved port.

    Translating this logic into code, the reference code for the Node side processing could look like:

    uint32_t gSignOnOverflowDetectedPort;
    
    void EIP_DLR_processSignOnFrameAsNode(EIP_DLRHandle dlrHandle, uint8_t *pktBuffer,
                                          uint8_t portNum, uint16_t size)
    {
        ICSS_EMAC_Handle dlricssEmacHandle = dlrHandle->emacHandle;
        PRUICSS_HwAttrs const *pruicssHwAttrs = (PRUICSS_HwAttrs const *)(dlrHandle->pruicssHandle->hwAttrs);
        activeSuperAddr *actSupAddrPtr = &(dlrHandle->dlrObj->addr);
        uint8_t *ifMacID = (uint8_t *)(&(dlrHandle->macId[0]));
        uint16_t numNodes, offset;
        uint8_t txPort;
        uint8_t dstMac[6];
        uint8_t isUnicast;
        ICSS_EMAC_TxArgument txArg;
        /* Create a local array of MAX_MTU size - aligned to 4 bytes */
        uint8_t newSignOnFrame[ICSS_EMAC_MAXMTU] __attribute__((aligned(4))) = {0};
    
        /* Check if this is a unicast frame (destination MAC = own MAC) */
        EIP_DLR_getMACId(pktBuffer + DLR_DST_MAC_OFFSET, dstMac);
        if(DLR_FALSE == memcmp(dstMac, ifMacID, ETHERNET_MAC_ADDR_LEN))
        {
            isUnicast = DLR_TRUE;
        }
        else
        {
            isUnicast = DLR_FALSE;
        }
    
        /* Calculate next port for forwarding */
        if(portNum == ICSS_EMAC_PORT_1)
        {
        	txPort = ICSS_EMAC_PORT_2;
        }
        else
        {
        	txPort = ICSS_EMAC_PORT_1;
        }
    
        /* Get current number of nodes */
        numNodes = EIP_DLR_convBigEndianToLittleEndianHalfWord(pktBuffer + DLR_SIGNON_NUM_NODES_OFFSET);
    
        /* Calculate offset where new address would be added */
        offset = (DLR_SIGNON_SUP_MAC_ADD_OFFSET + (numNodes * 10));
    
        /* Check if adding own address (4 bytes for IP Address and 6 bytes for MAC Address = 10 bytes) would exceed max frame size */
        if ((offset + ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN) > ICSS_EMAC_MAXMTU)
        {
            /* Frame is too large - save receiving port to shared RAM and send unicast to supervisor */
            gSignOnOverflowDetectedPort = portNum;
    
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(pktBuffer + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* Set destination to supervisor MAC (unicast) */
            EIP_DLR_addMACID(pktBuffer + DLR_DST_MAC_OFFSET, actSupAddrPtr->supMACAddress);
    
            /* Send unicast to supervisor on the other port */
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.lengthOfPacket = size;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = pktBuffer;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
        else if (isUnicast == DLR_TRUE)
        {
            /* This is a unicast Sign_On from supervisor (after overflow detection) */
            /* Copy old data from the frame */
            memcpy(newSignOnFrame, pktBuffer, size);
            /* Add own address to the frame */
            EIP_DLR_addMACID(newSignOnFrame + offset, ifMacID);
            EIP_DLR_addWord(newSignOnFrame + offset + ETHERNET_MAC_ADDR_LEN, dlrHandle->deviceIP);
            offset += (ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN);
            numNodes++;
    
            /* Update number of nodes in frame */
            EIP_DLR_addSignOnNumNodes(newSignOnFrame, numNodes);
    
            /* Restore multicast destination MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_DST_MAC_OFFSET, EIP_DLR_signOnMacID);
    
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* send on OTHER port */
            if((ICSS_EMAC_PORT_1 == gSignOnOverflowDetectedPort)
            {
                txPort = ICSS_EMAC_PORT_2;
            }
            else
            {
                txPort = ICSS_EMAC_PORT_1;
            }
    
            if(offset < DEFAULT_DLR_PACKET_SIZE)
            {
                txArg.lengthOfPacket = DEFAULT_DLR_PACKET_SIZE;
            }
            else
            {
                txArg.lengthOfPacket = offset;
            }
    
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = newSignOnFrame;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
        else
        {
            /* Normal processing: add own address and forward multicast */
            /* Copy old data from the frame */
            memcpy(newSignOnFrame, pktBuffer, size);
            /* Modify source MAC to own MAC */
            EIP_DLR_addMACID(newSignOnFrame + DLR_SRC_MAC_OFFSET, ifMacID);
    
            /* Add own address */
            EIP_DLR_addMACID(newSignOnFrame + offset, ifMacID);
            EIP_DLR_addWord(newSignOnFrame + offset + ETHERNET_MAC_ADDR_LEN, dlrHandle->deviceIP);
            offset += (ETHERNET_IP_ADDR_LEN + ETHERNET_MAC_ADDR_LEN);
            numNodes++;
    
            /* Update number of nodes */
            EIP_DLR_addSignOnNumNodes(newSignOnFrame, numNodes);
    
            if(offset < DEFAULT_DLR_PACKET_SIZE)
            {
                txArg.lengthOfPacket = DEFAULT_DLR_PACKET_SIZE;
            }
            else
            {
                txArg.lengthOfPacket = offset;
            }
            /* Send multicast on other port */
            txArg.icssEmacHandle = dlricssEmacHandle;
            txArg.portNumber = txPort;
            txArg.queuePriority = ICSS_EMAC_QUEUE1;
            txArg.srcAddress = newSignOnFrame;
    
            ICSS_EMAC_txPacket(&txArg, NULL);
        }
    }
    

    Let us know if there are any doubts/questions here.

    Regards
    Archit

  • Hi 

    I'd highly recommend to use the latest ICSS DLR driver and the EIP firmware from the Industrial Comms SDK AM243x: https://www.ti.com/tool/download/INDUSTRIAL-COMMUNICATIONS-SDK-AM243X/2026.00.00.06 

    This has the CT22 DLR Emulated Tests passing for both a DLR Node and Supervisor test cases.

    Feel free to reach out to us in case you have any concerns.

    Regards
    Archit