4.2. HSR_PRP¶
4.2.1. Protocol Overview¶
HSR stands for High Availability Seamless Redundancy. This is a protocol used to support redundant networks needed for industrial applications such as factory automation, substation automation etc. The standard is defined in IEC 62439-3 clause 5. HSR Ethernet frames are not compatible with standard Ethernet frames. HSR frames are identified uniquely by the HSR tag. So only HSR frames are possible in the network which is not identifiable by a standard Ethernet device. Factory or field devices are connected to a Double Attached Node HSR (DANH). Typically these nodes are connected in a Ring topology and only DANH compliant nodes can be connected to the HSR network. Other standard Ethernet devices (Singly Attached Nodes, SANs) needs to be connected through a Redundancy Box (RedBox) to work with HSR networks. HSR tag is used to manage redundancy in HSR network.
A DANH node has two ports operated in parallel. A source DANH prefixes a frame passed from its upper layers with an HSR tag to identify frame duplicates and sends the frame over each port.
A destination DANH receives, in the fault-free state, two identical frames (one from each port) within a certain interval. It removes the HSR tag of the first frame before passing it to its upper layers and discards any duplicate. The nodes support the IEEE 802.1D bridge functionality and forward frames from one port to the other, except if they already sent the same frame in that same direction. In particular, the node will not forward a frame that it injected into the ring.
4.2.2. ICSS Firmware¶
A common firmware is used across TI RTOS and Linux implementations of HSR/PRP. This section describes the firmware details.
4.2.2.1. Firmware Features Supported¶
- HSR/PRP
- The implementation is as per IEC 62439-3 Ed 2.0
- Operates as a DAN (Dual Attached Node)
- HSR
- Operates as a DANH
- As per clause 5 of the standard
- Support for modes – H, T, U and N as per standard
- Modes can be changed at run time
- PRP
- Operates as a DANP
- As per clause 6 of the standard
- Two ports as per standard, Port A and Port B
- Support for Node Table
- Total 128 entries on AMICx, AM335x, AM437x
- Total 256 entries on AM57xx & K2G
- Hash Table for faster lookup
- O(1) complexity
- Node Table statistics
- Support for Multicast Filtering
- Supported on all SoCs
- Hash Table for faster lookup
- O(1) complexity
- Duplicate Discard Table
- Duplicate discard on Port to Host path (HSR and PRP)
- Duplicate discard table on Port to Port path (HSR)
- Data integrity (CRC) check during port to port forwarding, except cut through (HSR)
- QoS scheme : 3-bit VLAN PCP
- No of levels supported : 8
- Number of host queues : 2 | 4 QoS levels per host queue
- Number of port queues : 4 | 2 QoS levels per port queue
- Number of host queues are configurable
- Statistics
- Supports all MIB statistics as per standard
- Node Table statistics for debugging
- PTP/1588
- PTP Slave and Master mode
- Supports P2P clock.
- PTP over 802.3 (Annex F)
- Transparent Clock supported
- Ordinary Clock supported
- Single and Two step clock supported
- Peer delay Response is always sent as two-step
- Storm Prevention : Yes. Configurable per port
4.2.2.2. Duplicate algorithm and table¶
Handling duplicate frames is one of the main tasks in HSR and PRP. The LRE must not provide the duplicate of a frame to its upper layer in order to offload the processor. The algorithm for discarding duplicates is not specified in IEC 62439-3. However, the standard mandates that the algorithm must be designed such that it never rejects a legitimate frame, while occasional acceptance of a duplicate can be tolerated.
In HSR, additionally to discarding duplicates destined to the host, a discard operation should also be used to prevent frames from looping in the network. A looping frame is a frame that is never discarded in any node of the network and therefore it keeps looping indefinitely. Normally, such a frame should be dropped by its source node. The function handles the case when a defective HSR device does not filter correctly according to source/destination address. This operation is less critical than the host duplicate discard. It is also specified that any duplicate discard method shall be able to forget an entry identified by the source MAC address and the sequence number after a time EntryForgetTime (default 400ms).
A table holds entries representing frames that have been registered in the LRE, each entry is represented bya frame signature. The signature consists of the source MAC address and the 16 bit sequence number. The sequence number value is incremented by 1 when a frame and its duplicate are sent by a source in an HSR network. This signature allows identifying a frame uniquely. When a frame is received, the list is searched by comparing the frame signature with all entries in the table. If such an entry is found, the frame is a duplicate and shall be discarded. If no entry exists, the frame is the first one received and needs to be forwarded to the application and/or – in case of HSR - to the other port. With a successful forwarding process (frame received with no error), a new entry with the signature of that frame is created in the table.
A linear lookup process is too time consuming; thus Hash algorithms are used to decrease the search time.
4.2.2.3. Port to Host Duplicate Table¶
It is used to prevent sending duplicate frames to the upper layers. This table is common for both PRUs. Resource sharing implies that collision (two PRUs accessing the same data) must be handled. Since the table is common to both PRUs, the host duplicate rejection must be done after the EOF is detected in order to avoid rejecting legitimate frames.
4.2.2.4. Port to Port Duplicate Table¶
A PRU forwards the frames received from one HSR port to the other HSR port, unless the frame was sent already. Each PRU has its own port duplicate table. A search operation can start before the EOF is detected since the table is not shared between the PRU and is not subject to any modification during the reception of a frame. In order to minimize the load of the PRU after EOF reception, the search operation in the port duplicate table is executed during frame reception. Moreover, this allows to quickly detecting if the frame should be discarded early in the reception process. An insertion in the table is still made only after the EOF is detected, but the operation is much faster since the result of the search operation can used.
4.2.2.5. Node Table¶
The node table is a central element of the HSR/PRP mechanism although the standard declares node tables optional. This firmware implements node tables for HSR and PRP. Node table handling is implemented in the PRU and comprises of registering incoming supervision and non-supervision-frames as well as ageing and deleting of old entries. The standard requires updating the node table when a supervision frame is received. Accessing the node table is thus not critical since supervision frames are sent only every 2 seconds. For HSR, to maintain statistics for each source node of the network and to facilitate debugging, the implementation updates the node table for each frame received by the host from a source that has previously sent a supervision frame. A further advantage of this approach is having a similar implementation for HSR and PRP. Indeed, the PRP Standard requires updating the node table, if implemented, for all the incoming frames in order to keep track of the traffic contented to each redundant LAN. The node table is accessible by the host for management purposes. Update- and register operations in the table should be done when the frame is completely received in order to avoid registering erroneous frames.
The node table search/update operation is very critical since it is resource/time consuming (maximum NODE_TABLE_SIZE is 256 entries). In the worst case scenario (node table full), a linear lookup operation in the receiving task could load the PRU too much and in consequence could cause Rx overflow or TX underflow. Moreover the node table is common to both PRUs and since it is accessed often, the resource-sharing management has additional impact on the latency. Optimized linear tables were considered, but the timing remained too critical in the worst case scenario. Hash tables are not considered because it is not allowed to lose entries due to collisions. The implemented solution is a sorted table with a two layer table structure. This allows to significantly optimize the lookup time especially when the table has lots of valid entries.
It is important to notice that in a normal HSR case scenario there are - in average - significantly more successful lookup operations (MAC address found in the table) than insertion and deletion operations. Indeed, insertion operations are only made with a supervision frame. This assumption cannot be made for PRP since all frames can create an entry in the node table. The design is therefore optimized according to this assumption.
4.2.2.6. Frame duplication from the host¶
Frames sent by the host must be duplicated and should be sent to both ports nearly at the same time for HSR and PRP. In a simple approach, the host stores the frame in the queue of one PRU, the PRU then waits until both ports are available and finally sends the frame at the same time via both ports. However, this solution is not resource efficient and it increases the latency of one PRU when waiting for the PORT to be ready. Therefore, a solution that off-loads the PRU from the duplication task is implemented: the host driver duplicates the frames and puts a copy to each PRU queue.
The implementation is however not straightforward:
Since the frames are not “linked” to each other, there is no guarantee that the frames are sent by both PRUs within a short interval. The host could control the queue status and only push the frames in the highest priority queue of both PRU when the queues are free. This would force each PRU to send the frame and its duplicate next. Nevertheless, for HSR this solution removes the prioritization of the frame circulating in the HSR ring as a PRU could buffer a high priority frame from the ring due to a lower priority frame sent by the host. Frames circulating in the ring are to be treated with higher priority than frames sent by the host. There is a compromise to be found.
The solution is the following: The host driver duplicates the frame and puts the duplicates in the queues of each PRU. The queue is selected based on the priority of the frame. Each PRU handles the frame independently and we only have the assurance that each frame will be sent out within an unknown interval. The drawback of this solution is the lack of control on when each frame will be sent out. The interval can be bigger than one maximum sized Ethernet frame in this case.
4.2.2.7. Supervision Frame¶
Incoming supervision frames are received and processed by the PRU. On reception of a frame, the PRU updates the node table and the statistic counters. For HSR, if the received supervision frame originates from the receiver (i.e. it traversed the whole ring) it is discarded. Otherwise it is sent to the next node in store and forward mode. The reason for using store and forward mode is the following: A supervision frame might trigger the creation of an entry in the node table and this task is time consuming. By sending the frame in store and forward mode, more time is available for this operation while receiving the frame. Each device in an HSR/PRP network sends supervision frames at a constant time interval. Outgoing supervision frames are composed and sent by the host CPU.
4.2.2.8. Cut-Through for HSR¶
Cut through happens when switch firmware bypasses the transmit queues and directly copies data from Rx FIFO to Tx FIFO. The concept is explained here
The concept of forwarding frames from HSR port to HSR port when operating in cut-through mode deserves more explanation since the following boundary conditions require a carefully balanced implementation: •Cut-through of a frame shall start as early as possible in order to minimize the propagation delay in each node. The ICSS switch supports starting the cut-through operation after a configurable amount of bytes received. Theoretically, for HSR the minimum number of bytes required is 22 (12 bytes Source-/Destination MAC, 4 bytes VLAN Tag, 6 bytes HSR Tag) in order to have all the necessary data to take the routing decision. The receiving process is optimized to allow cut through as soon as possible depending on the type of the frame ( see start receiving process in 3.2.2 Micro Scheduler). •Duplicates shall not be cut through (i.e. the detection of a duplicate shall be finished before the next node in the ring starts processing the frame) •Detection of duplicates (computing the hash index and scanning a bin in the hash table) is time consuming
Waiting for the duplicate detection before taking the cut through decision would delay the frame too much. Starting to cut-through a frame without port duplicate rejection minimizes the delay and allows starting the receiving process after 14 bytes. Once the cut through of a frame has started, the port duplication rejection process starts. If the frame is identified as duplicate or corrupted, the transmission of the frame is aborted by asserting the TX_RESET which will reset the transmit FIFO and clear all its contents and therefore corrupt the frame being cut-though.
4.2.2.9. HSR/PRP Memory Map¶
Name of Offset | Description Refer to hsr_prp_firmwar e.h | Offset in Shared RAM | Size (in bytes) |
---|---|---|---|
INDEX_ARRAY | Index entry for Node Table | 0x1E0 | 144 |
NODE_TABLE | Node Table for the DANH/DANP | 0x1FCO | 4132 |
Table: Shared RAM Memory Map
Name of Offset | Description Refer to hsr_prp_firmware.h | Offset in Shared RAM (base : 0x140) |
---|---|---|
LRE_CNT_TX_A | Number of frames successfully sent over port A that are HSR/PRP tagged | 4 |
LRE_CNT_TX_B | Same for Port B | 8 |
LRE_CNT_TX_C | Number of frames successfully sent to Host that are HSR/PRP tagged | 12 |
LRE_CNT_ERRWRONGLAN_A | number of frames with the wrong LAN identifier received on LRE port A | 16 |
LRE_CNT_ERRWRONGLAN_B | Same for Port B | 20 |
LRE_CNT_ERRWRONGLAN_C | Same for Host | 24 |
LRE_CNT_RX_A | number of frames received successfully with HSR or PRP TAG on a LRE port A | 28 |
LRE_CNT_RX_B | Same for Port B | 32 |
LRE_CNT_RX_C | Same for Host | 36 |
LRE_CNT_ERRORS_A | number of frames with errors received on this LRE port A | 40 |
LRE_CNT_ERRORS_B | Same for Port B | 44 |
LRE_CNT_ERRORS_C | Same for Host | 48 |
LRE_CNT_NODES | Number of active nodes in the node table | 52 |
LRE_CNT_PROXY_NODES | Number of active proxy nodes in the node table | 56 |
LRE_CNT_UNIQUE_RX_A | Number of entries in the duplicate detection mechanism on port A for which no duplicate was received | 60 |
LRE_CNT_UNIQUE_RX_B | Same for Port B | 64 |
LRE_CNT_UNIQUE_RX_C | Same for Host | 68 |
LRE_CNT_DUPLICATE_RX_A | Number of entries in the duplicate detection mechanism on port A for which one single duplicate was received | 72 |
LRE_CNT_DUPLICATE_RX_B | Same for Port B | 76 |
LRE_CNT_DUPLICATE_RX_C | Same for Host | 80 |
LRE_CNT_MULTIPLE_RX_ A | Number of entries in the duplicate detection mechanism on port A for which more than one duplicate was received | 84 |
LRE_CNT_MULTIPLE_RX_ B | Same for Port B | 88 |
LRE_CNT_MULTIPLE_RX_ C | Same for Port C | 92 |
LRE_CNT_OWN_RX_A | Number of entries on port A received from device itself | 96 |
LRE_CNT_OWN_RX_B | Same for Port B | 100 |
LRE_DUPLICATE_DISCARD | Number of frame retreive by the host | 104 |
LRE_TRANSPARENT_RECEPT ION | Number of frame received without PRP RCT | 108 |
LRE_NODE_TABLE_LOOKUP _ERROR_A | Number of instances where node table look up failed for Port A | 112 |
LRE_NODE_TABLE_LOOKUP _ERROR_B | Same for Port B | 116 |
LRE_NODE_TABLE_FULL | If Node Table is full, this value is incremented | 120 |
LRE_MULTICAST_DROPPED | If the Multicast frame is dropped because of no hash value configured in the filter table, this value is incremented | 124 |
LRE_VLAN_DROPPED | If the frame is dropped because of no entry for the VID of the frame in the VLAN filter table, this value is incremented | 128 |
Table: LRE Interface Stats
Name of Offset | Description Refer to hsr_prp_firmwar e.h | Offset in PRU0 DRAM | Size (in bytes) |
---|---|---|---|
DUPLICATE_HOST_T ABLE | Duplicate detection table for Host | 0x200 | 6136 |
NEXT_FREE_ADDRES S_NT_QUEUE | Offset of the queue of the free address for the node table | 0x1B00 | 132 |
POINTERS_FREE_AD DR_NODETABLE | Offset of the read and write pointer of the free address of the node table(read.w0,writ e.w2) | 0x1B84 | 4 |
Table: PRU0 RAM Memory Map
Name of Offset | Description Refer to hsr_prp_firmwar e.h | Offset in PRU1 DRAM | Size (in bytes) |
---|---|---|---|
DUPLICATE_PORT_T ABLE_PRU0 | Offset of port duplicate table for PRU0 (HSR Only) | 0x200 | 3064 |
DUPLICATE_PORT_T ABLE_PRU1 | Offset of port duplicate table for PRU1 (HSR Only) | 0xE00 | 3064 |
NODE_TABLE_SIZE | Size of the node table [0..128] | 0x1C00 | 4 |
NODE_TABLE_ARBIT RATION | Busy slave flag and busy master flag for 3 lock used to protect the node table | 0x1C04 | 4 |
DUPLICATE_HOST_T ABLE_SIZE | Size and setup (N and M) of duplicate host table | 0x1C08 | 4 |
DUPLICATE_PORT_T ABLE_SIZE | Size and setup (N and M) of duplicate port table | 0x1C1C | 4 |
NODE_FORGET_TIME | Time after which a node entry is cleared (10ms resolution) | 0x1C20 | 4 |
DUPLI_FORGET_TIM E | Time after which an entry is removed from the duplicate table (10ms resolution) | 0x1C24 | 4 |
PATH_BROKEN_NB_ FRAM_DIFF | Supervision frame Counter minimum difference to detect a broken path | 0x1C28 | 4 |
DUPLI_PORT_CHECK _RESO | Time interval to check the port duplicate table | 0x1C2C | 4 |
DUPLI_HOST_CHECK _RESO | Time interval to check the host duplicate table | 0x1C30 | 4 |
NODETABLE_CHECK_ RESO | Time interval to check the node duplicate table | 0x1C34 | 4 |
HOST_TIMER_CHECK _FLAGS | Host | Port | 0x1C38 | 4 |
HOST_DUPLICATE_A RBITRATION | Arbitration flag for the host duplicate task | 0x1C3C | 4 |
ICSS_FIRMWARE_RE LEASE | Time counter to trigger the host duplicate table check task | 0x1C40 | 4 |
RED_FIRMWARE_REL EASE | Time counter to trigger the Node Table check task in firmware | 0x1C44 | 4 |
SUP_ADDR | Supervision address in HSR | 0x1C48 | 4 |
Table: PRU1 RAM Memory Map
4.2.3. Linux Software¶
4.2.3.1. Overview¶
In both HSR and PRP protocols, the DAN (Dual Attached Node) sends an identical frame to both the interfaces and uses a sequence number in the tag to allow drop duplicates at the Rx node to achieve redundancy. This section describes the different software components of a Linux based HSR/PRP solution to support redundancy.
4.2.3.2. Features supported¶
- HSR/PRP
- 100 Mbits/s Full Duplex Ethernet Interface
- The implementation is as per IEC 62439-3 Ed 2.0
- Operates as a DAN (Dual Attached Node)
- HSR
- Operates as a DANH
- As per clause 5 of the standard
- Support for modes – H, T, U and N as per standard
- Modes can be changed at run time
- Cut-through switching
- PRP
- Operates as a DANP
- As per clause 6 of the standard
- Two ports as per standard, Port A and Port B
- Support for Node Table
- Total 128 entries on AMICx, AM335x, AM437x
- Total 256 entries on AM57xx & K2G
- Hash Table for faster lookup
- Node Table statistics
- Support for Multicast Filtering
- Supported on all SoCs
- Hash Table of 256 entries for faster lookup
- O(1) complexity
- User configurable mask to select bits for hashing
- Support for VLAN over HSR/PRP interface
- Support for VLAN Filtering
- VLAN filter table of 4096 entries for perfect match
- O(1) complexity
- Duplicate Discard Table
- Duplicate discard on Port to Host path (HSR and PRP)
- Duplicate discard table on Port to Port path (HSR)
- Data integrity (CRC) check during port to port forwarding, except cut through (HSR)
- QoS scheme : 3-bit VLAN PCP
- No of levels supported : 2
- Number of host queues : 2 | 2 QoS levels per host queue
- Number of port queues : 2 | 2 QoS levels per port queue
- Statistics
- Supports all MIB statistics as per standard
- Node Table statistics for debugging
- Storm Prevention : Yes. Configurable per port
- Dual instance of HSR/PRP using two PRU-ICSS on AM571x
- VLAN tag support in Supervision frames
- Run time change of Protocol at PRU-ICSS without reboot
4.2.3.3. Software Architecture¶
The diagram below highlights the software components that are modified or developed specifically for HSR/PRP. These along with other standard Linux OS components are used to implement the Linux HSR/PRP DAN (Dual Attached Node).
- Linux Kernel drivers
- HSR/PRP driver
- Ethernet driver
- User space
- Net-SNMP
- iproute2
4.2.3.3.1. HSR/PRP Driver source code and Kconfig option¶
The driver source code is located under net/hsr-prp folder of the Linux source tree. To build kernel with this driver, set Kconfig option CONFIG_HSR_PRP=y in the dotconfig or enable it from the menu.
4.2.3.3.2. Linux HSR/PRP Driver¶
The Linux networking subsystem in upstream kernel has added support for HSR driver starting in v3.12 (HSRv0 - IEC 62439-3:2010) and enhanced the same to support HSRv1 (IEC 62439-3:2012) in v4.6. This driver allows user to create an HSR network device with a pair of slave network interfaces (A and B) that are standard Ethernet interfaces. For example on TI’s AM572x IDK EVM, there are two Ethernet interfaces (10/100) per each PRU ICSS. The PRU Emac driver available for ICSS PRU Ethernet h/w supports two Ethernet ports. Using ip link command, user will be able to setup a HSR interface on this EVM that pair the two PRU Ethernet interfaces to create a HSR node or DAN-H.
TI has enhanced the Linux HSR driver and ip link command in iproute2 package to support PRP defined in IEC 62439-3 clause 4. With this change, user will be able to create a Doubly Attached Node with PRP (DAN-P) using standard Ethernet interfaces. As in the case of HSR, using ip link command, user will be able to setup a prp interface using two Ethernet interfaces such as the one provided by PRU EMAC driver.
Linux HSR/PRP driver provides a standard Ethernet interface to application layer and hide the details of the redundancy protocol under the driver layer. Linux HSR/PRP driver implements the Link Redundancy Entity (LRE) that is central to implementing redundancy using respective protocol.
HSR LRE functions and L2 routing can be offloaded to the firmware running on the PRU cores of ICSS. The diagram below shows the architecture of an Offloaded HSR/PRP driver. The upper layer driver is existing Linux HSR/PRP driver described in the previous section. The PRU Ethernet driver exports HSR/PRP capabilities in the NetDev feature flags. The green blocks in the Redundancy layer shows the software blocks that gets offloaded to PRUs in ICSS which is shown green as well. The upper layer HSR/PRP driver uses the feature flags exported by the PRU Ethernet driver to disable corresponding functions in its layer. The firmware is a re-use from the TI RTOS implementation that is discussed above. Re-use means the data structures and API should be re-used across both TI RTOS and Linux driver implementations. A common PRU Ethernet driver is developed to support existing EMAC device as well HSR/PRP
4.2.3.3.3. PRU-ICSS Subsystem Driver¶
PRU-ICSS Subsystem Driver provide a set of functions to client driver such as PRU Ethernet (described in next section) to load and run firmware on a specific core, such as PRU on a PRU-ICSS. On a SoC, there can be 1 or 2 instance of the PRU-ICSS and client driver might want to know which instance it is referring to. For example, PRU Ethernet driver calls pruss_get() to get the instance ID. Also PRU-ICSS and PRU Ethernet driver support sysfs and debugfs files specific to an instance and user might have to know what instance the file refers to. Following mapping is used for the ID based on the SoC and the PRU-ICSS instance.
SoC | ID | if number | ICSS TRM reference |
---|---|---|---|
AM3 | 0 | eth0/1 | PRU-ICSS |
AM4 | 0 | eth1/2 | PRU-ICSS0 |
AM5 | 1 | eth4/5 | PRU-ICSS1 |
AM5 | 2 | eth2/3 | PRU-ICSS2 |
K2G | 0 | eth1/2 | PRU-ICSS0 |
K2G | 1 | eth3/4 | PRU-ICSS1 |
In the following section, the PRU-ICSS ID is used in the debugfs or sysfs file path and the same can be obtained from the table above to know which PRU-ICSS the file refers to.
4.2.3.3.4. PRU Ethernet Driver (EMAC/HSR/PRP)¶
Starting from Processor SDK 04.00.00 release, the PRU Ethernet driver supports HSR/PRP firmware offload. More specifically, based on a module parameter configured at boot time, the PRU Ethernet driver loads either a PRU EMAC firmware, PRU HSR firmware or PRU PRP firmware. The first case (EMAC) is the non-offload case, while the latter 2 cases are the firmware offload cases. When a HSR/PRP firmware is loaded, the PRU Ethernet driver will do proper firmware configurations and notify the Linux HSR/PRP driver stack that offload has been enabled. From then on, LRE functionality is carried out in firmware.
Notice that, from the user point of view, other than providing a module parameter to specify which firmware to load, all of the above mentioned driver behavior is transparent to the user.
Note
For all discussion and examples shown, AM57xx device is used as example, but different devices will use different ports. Please see PRU-ICSS Subsystem Driver for interface number and PRU-ICSS ID information for different SoCs.
As of Processor SDK 5.1.x, the driver supports 2 instances of HSR/PRP one on each of PRU-ICSS on AM5xxx as per table below.
PRU-ICSS1 PRU-ICSS2 HSR HSR HSR PRP PRP PRP PRP HSR
4.2.3.3.4.1. Queue Usage and VLAN PCP to Queue Map¶
At the Ingress, there are two queues available for queueing the frames coming from each port or PRU to Host and two queues available for packets from Host to each PRU. At the Egress, there are additionally two more queues used for forward traffic from PRU1 to PRU0 and vice-versa. PRUETH driver configures the PCP to Queue MAP in Shared RAM which is used by firmware to decide which queue to pick to enqueue frames towards Host or other PRU. Priority queues are assigned based on the PCP value in VLAN tag of an Ethernet frame. Untagged frame is treated like PCP 0. Here is the mapping value configured by driver in 4 bytes starting at offset QUEUE_2_PCP_MAP_OFFSET (defined in hsr_prp_firmware.h). Same mapping is used for Ingress and Egress traffic.
The convention is that higher queue value corresponds to lower priority
For HSR/PRP Ethernet types
- At ingress to Host
byte 0 - To host from PRU 1, PCP 0-3 => Q3
byte 1 - To host from PRU 1, PCP 4-7 => Q2
byte 2 - To host from PRU 0, PCP 0-3 => Q1
byte 3 - To host from PRU 0, PCP 4-7 => Q0
At the ingress, firmware inspect the PCP value in the incoming Ethernet frame’s VLAN tag and choose a priority queue to enqueue the frame based on the above mapping.
- At egress from host to wire/network
PRU0/PRU1
---------
byte 0 - from Host to PRU, PCP 0-3 => Q3
byte 1 - from Host to PRU, PCP 4-7 => Q2
PRU0
-----
byte 2 - from PRU1 to PRU0, PCP 0-3 => Q1
byte 3 - from PRU1 to PRU0, PCP 4-7 => Q0
PRU1
-----
byte 2 - from PRU0 to PRU1, PCP 0-3 => Q1
byte 3 - from PRU0 to PRU1, PCP 4-7 => Q0
Driver choose the priority queue for egress transmission based on the PCP value of the Ethernet frame received from the upper layer. Firmware sends the frames first from Q0 and Q2 in a round robin fashion. Once these queues are drained, it then sends from the next higher queues Q1 and Q3 again in a round robin fashion. At the egress, Q0/Q1 are port queues and Q2/Q3 are host queues.
For Dual EMAC Ethernet type
In Dual EMAC case, mapping is hard coded in firmware.
- At ingress to Host
From PRU0 to Host, PCP 0-3 => Q1
From PRU0 to Host, PCP 4-7 => Q0
From PRU1 to Host, PCP 0-3 => Q3
From PRU1 to Host, PCP 4-7 => Q2
- At egress from host to wire/network
PRU0/PRU1
-- ---------
From Host to PRU0/PRU1, PCP 0-1 => Q3
From Host to PRU0/PRU1, PCP 2-3 => Q2
From Host to PRU0/PRU1, PCP 4-5 => Q1
From Host to PRU0/PRU1, PCP 6-7 => Q0
Firmware sends the frames first from Q1, and then from the next higher queue (Q2) and so forth.
For all ethernet types, at the Ingress, two separate irq handlers are assigned to each port to process the packets. Driver handler first process packets from the high priority queue followed by packets from the lower priority queue.
4.2.3.3.4.2. Changing protocol at PRU Ethernet¶
PRU Ethernet driver supports multiple protocols based on the firmware loaded on ICSS PRU. In Processor SDK 04.00.00, a capability was added to change the protocol running on the PRU at boot time through bootargs. This is described at Testing HSR/PRP Firmware Offload. Starting Processor SDK 04.01.00, The driver can be configured to switch the protocol while the board is powered up and running Linux kernel. By default, the PRU Ethernet driver is probed to be in the EMAC mode and EMAC firmware is loaded on to the PRU unless user set the pruss2_ethtype to run HSR (1) or PRP (2). Two feature names are added to help offload HSR or PRP in the PRU Ethernet driver :- hsr-rx-offload and prp-rx-offload. PRU Firmware essentially offload the rx side processing of LRE, such as duplicate detection and drop, node table update, stats update etc. To reflect the same, the features are named with a rx-offload suffx to the protocol name. Ethtool command has an option -K to set or clear the feature in a network device. So this flag can be set or reset rx offload feature in the PRU Ethernet device. As the device may be hooked up to a upper HSR/PRP network device, user is expected to delete the hsr or prp interface before changing the flag at the PRU Ethernet device. General procedure to change protocol at PRU Ethernet device is as follows:-
Below assumes that hsr or prp interface using the PRU Ethernet devices is currently deleted. Here are the steps at a high level:-
1. Bring down the two PRU Ethernet interfaces using ifconfig and unassign the ip address using ifconfig. For example
ifconfig eth2 down 0.0.0.0
ifconfig eth3 down 0.0.0.0
2. If the PRU Ethernet device is currently running HSR or PRP offload feature, the same has to be disabled before switching to EMAC or another protocol using ethtool -K option. For example if HSR is currently running, do
ethtool -K eth2 hsr-rx-offload off
ethtool -K eth3 hsr-rx-offload off
Similarly if PRP is currently running, do
ethtool -K eth2 prp-rx-offload off
ethtool -K eth3 prp-rx-offload off
3. If user would like to offload HSR, enable the feature hsr-rx-offload on both devices.
ethtool -K eth2 hsr-rx-offload on
ethtool -K eth3 hsr-rx-offload on
4. Now the PRU Ethernet devices can be paired to create an HSR interface using ip link command. To offload PRP user does following command in step 3
ethtool -K eth2 prp-rx-offload on
ethtool -K eth3 prp-rx-offload on
To display the offload feature currently active at the PRU Ethernet, user may type following command for example for eth2
ethtool -k eth2
Sample commands
Before using these commands, save the MAC address of both interfaces. These sample commands assumes a MAC address of 70:FF:76:1C:0E:8C for both PRU Ethernet interfaces and an IP address of 192.168.2.20 for the hsr/prp interface. Eth3 MAC address is assumed to be 70:FF:76:1C:0E:8E. Also assumes user create hsr0 or prp0 interface using eth2 and eth3 interfaces. Please note that for each DAN, user needs to assign unique MAC address and IP address from the same subnet.
- To switch from EMAC to HSR
ifconfig eth2 0.0.0.0 down
ifconfig eth3 0.0.0.0 down
ifconfig eth2 hw ether 70:FF:76:1C:0E:8C
ifconfig eth3 hw ether 70:FF:76:1C:0E:8C
ethtool -K eth2 hsr-rx-offload on
ethtool -K eth3 hsr-rx-offload on
ifconfig eth2 up
ifconfig eth3 up
ip link add name hsr0 type hsr slave1 eth2 slave2 eth3 supervision 45 version 1
ifconfig hsr0 192.168.2.20
- To switch from HSR to PRP
ip link delete hsr0
ifconfig eth2 down
ifconfig eth3 down
ethtool -K eth2 hsr-rx-offload off
ethtool -K eth3 hsr-rx-offload off
ethtool -K eth2 prp-rx-offload on
ethtool -K eth3 prp-rx-offload on
ifconfig eth2 up
ifconfig eth3 up
ip link add name prp0 type prp slave1 eth2 slave2 eth3 supervision 45
ifconfig prp0 192.168.2.20
- To switch from PRP to HSR
ip link delete prp0
ifconfig eth2 down
ifconfig eth3 down
ethtool -K eth2 prp-rx-offload off
ethtool -K eth3 prp-rx-offload off
ethtool -K eth2 hsr-rx-offload on
ethtool -K eth3 hsr-rx-offload on
ifconfig eth2 up
ifconfig eth3 up
ip link add name hsr0 type hsr slave1 eth2 slave2 eth3 supervision 45 version 1
ifconfig hsr0 192.168.2.20
- To switch from HSR to EMAC
ip link delete hsr0
ifconfig eth2 down
ifconfig eth3 down
#Restore eth3 MAC address
ifconfig eth3 hw ether 70:FF:76:1C:0E:8E
ethtool -K eth2 hsr-rx-offload off
ethtool -K eth3 hsr-rx-offload off
ifconfig eth2 192.168.2.20
ifconfig eth3 192.168.3.20
- To switch from PRP to EMAC
ip link delete prp0
ifconfig eth2 down
ifconfig eth3 down
ethtool -K eth2 prp-rx-offload off
ethtool -K eth3 prp-rx-offload off
#Restore eth3 MAC address
ifconfig eth3 hw ether 70:FF:76:1C:0E:8E
ifconfig eth2 192.168.2.20
ifconfig eth3 192.168.3.20
4.2.3.3.4.3. PRP EMAC mode¶
PRP EMAC mode is a special mode of PRP Ethernet type where the driver configures the PRP firmware to work like EMAC firmware. This is because currently PTP support is available only in PRU PRP firmware. So the current implementation of SAN with PTP requires PRUETH driver to be configured as PRP using bootargs. User needs to configure the PRP Firmware in PRP EMAC mode before bringing up the Ethernet interfaces. It is expected to add the PTP support to EMAC firmware in a future release. Until then this intermediate solution is used. Here are the steps to use PRUETH as SAN with PTP
- Boot the IDK EVM with prussX_ethtype in bootargs set to PRP as described at Testing HSR/PRP Firmware Offload
- Once the EVM boots up and user login, first thing to verify is if PRUETH is configured as PRP Ethernet type. See above section for details
- Configure PRP EMAC mode in the PRP firmware by issuing the following command at the console
echo 1 > /sys/devices/platform/pruss<ID>_eth/net/eth<if number>/prp_emac_mode
where <ID> and <if number> are described in section PRU-ICSS Subsystem Driver
- Now bring up Ethernet interfaces as usual and the device is ready to be used as SAN. PTP support can be enabled at this time. See section on [[1]] for the details.
NOTE: run time protocol switch is not supported for switch to SAN PTP for now and required boot time configuration and above debugfs command once device is boot up in PRP mode
4.2.3.4. Multicast filtering¶
Multicast filtering is an Ethernet frame filtering feature in PRU firmware based on the destination MAC address of the received frame. The PRU provides a Multicast filter table in Data RAM1 of PRU with a size of 256 entries of 1 byte each. Firmware implements an imperfect match for filtering the frames based on a hash calculated using the destination MAC address of the frame and a configurable mask if the destination address is a multicast MAC address.
Hash = (MAC_ADDR[0] AND MASK[0]) XOR
(MAC_ADDR[1] AND MASK[1]) XOR
(MAC_ADDR[2] AND MASK[2]) XOR
(MAC_ADDR[3] AND MASK[3]) XOR
(MAC_ADDR[4] AND MASK[4]) XOR
(MAC_ADDR[5] AND MASK[5])
Where MASK is a user configurable value provided at boot time and MAC_ADDR is the multicast MAC address which is extracted from the destination address of the Ethernet frame and AND is the bitwise AND operation. In other words, a bitwise AND operation is performed between each byte of MAC address and a corresponding MASK byte and the resulting bytes are XOR-ed together to get the hash value. The hash is used to index into the Multicast filter table to check if it is set (1) or reset (0). If set, the frame is forwarded to ARM core (a.k.a Host). If reset, the frame is dropped at the PRU. This is an imperfect match since there can be multiple MAC addresses that produces the same hash value. So these frames will get forwarded to the ARM core.
ti_prueth.pruss<ID>_port<PORT>_mc_mask is the module parameter for MASK where <ID> is described in section PRU-ICSS Subsystem Driver and <PORT> is ‘0’ in HSR/PRP case since both ports share the same MASK (port 1 does not need to be set and has no effect), and ‘0’ or ‘1’ in Dual EMAC case since both ports can be configured independently.
Sample bootargs with MASK configured (HSR/PRP)
setenv pruss1_port0_mc_mask "FF:FF:FF:FF:00:00"
setenv pruss2_port0_mc_mask "FF:FF:FF:FF:00:00"
setenv args_mmc 'run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype} ti_prueth.pruss1_ethtype=${pruss1_ethtype} ti_prueth.pruss2_ethtype=${pruss2_ethtype} ti_prueth.pruss1_port0_mc_mask=${pruss1_port0_mc_mask} ti_prueth.pruss2_port0_mc_mask=${pruss2_port0_mc_mask}'
A comparable sample bootargs with MASK configured for Dual EMAC
setenv pruss1_port0_mc_mask "FF:FF:FF:FF:00:00"
setenv pruss1_port1_mc_mask "FF:FF:FF:FF:00:00"
setenv pruss2_port0_mc_mask "FF:FF:FF:FF:00:00"
setenv pruss2_port1_mc_mask "FF:FF:FF:FF:00:00"
setenv args_mmc 'run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype} ti_prueth.pruss1_ethtype=${pruss1_ethtype} ti_prueth.pruss2_ethtype=${pruss2_ethtype} ti_prueth.pruss1_port0_mc_mask=${pruss1_port0_mc_mask} ti_prueth.pruss1_port1_mc_mask=${pruss1_port1_mc_mask} ti_prueth.pruss2_port0_mc_mask=${pruss2_port0_mc_mask} ti_prueth.pruss2_port1_mc_mask=${pruss2_port1_mc_mask}'
Typically, an application joins the multicast group either using a raw socket of type SOCK_DGRAM and use setsockopt() API to Join or leave the multicast group. An interesting article on this is available at
https://www.tenouk.com/Module41c.html
This causes the Multicast MAC address to be added to the mc_list of the socket and the associated network device in kernel and finally get passed to the Ethernet device driver (in our case, it is PRU Ethernet device driver). The relevant API is ndo_set_rx_mode() of the net_device_ops structure in Linux kernel associated with the network device. The PRU Ethernet device driver calculates the hash as described above and then writes 1 to MC filter table using the hash value as index. The PRU Ethernet device driver also supports allmulti which is used to enable receieve of all multicast frames at an interface. This is an option passed to the ifconfig command.
Example
>ifconfig eth2 192.168.2.20 allmulti
To remove the option
>ifconfig eth2 192.168.2.20 -allmulti
To display the Multicast address list of an interface, say eth2, user types
>ip maddr show dev eth2
sample display
root@am57xx-evm:~# ip maddr show dev eth2
6: eth2
link 33:33:00:00:00:01 users 2
link 01:00:5e:00:00:01 users 2
link 33:33:ff:1c:16:e0 users 2
link 01:00:5e:00:00:fb
link 01:00:5e:00:00:fc
link 33:33:00:01:00:03 users 2
link 33:33:00:00:00:fb users 2
inet 224.0.0.1
inet6 ff02::fb
inet6 ff02::1:3
inet6 ff02::1:ff1c:16e0
inet6 ff02::1
inet6 ff01::1
PRU Ethernet driver also provides a debugfs file mc_filter to display MC filter table in the memory
/sys/kernel/debug/prueth-prp-<ID>/mc_filter
or
/sys/kernel/debug/prueth-hsr-<ID>/mc_filter
or (for Dual EMAC)
/sys/kernel/debug/prueth-eth<if number>/mc_filter
where ID/’if number’ is described in section PRU-ICSS Subsystem Driver
Sample display
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-prp-2/mc_filter
MC Filter : enabled
MC Mask : ff:ff:ff:ff:0:0
MC Filter table below 1 - Allowed, 0 - Dropped
0: 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
20: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
30: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
40: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
50: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
60: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
70: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
80: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
90: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
b0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
c0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
d0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
e0: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
f0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4.2.3.4.1. Dual EMAC¶
If using Dual EMAC, the only interface differences are the debugfs paths and the mask parameters, as mentioned above. Internally, the multicast filter table(s) are stored in each PRU’s Data RAM (PRU0->Data RAM0, PRU1->Data RAM1) instead of one table in Data RAM1 as for HSR/PRP.
4.2.3.5. VLAN over PRU Ethernet¶
Virtual LAN (VLAN) is a standard Linux feature that can be enabled over PRU Ethernet devices. There are many websites that describes how Linux VLAN works. Some of them are at [[2]] or at [[3]] and some configuration details are also discussed at [[4]].
User may use ip link command to setup vlan interface over prueth interfaces. For example, over a hsr interface, if user would like to setup two vlan interfaces say, hsr0.2 and hsr0.3, user execute the following commands assuming the hsr0 interface is already setup:-
Node-1
ifconfig hsr0 0.0.0.0
ip link add link hsr0 name hsr0.2 type vlan id 2
ip link add link hsr0 name hsr0.3 type vlan id 3
ifconfig hsr0.2 192.168.2.40
ifconfig hsr0.3 192.168.3.40
ip link set hsr0.2 type vlan egress 0:0
ip link set hsr0.3 type vlan egress 0:7
Node-2
ifconfig hsr0 0.0.0.0
ip link add link hsr0 name hsr0.2 type vlan id 2
ip link add link hsr0 name hsr0.3 type vlan id 3
ifconfig hsr0.2 192.168.2.50
ifconfig hsr0.3 192.168.3.50
ip link set hsr0.2 type vlan egress 0:0
ip link set hsr0.3 type vlan egress 0:7
The above assume we have a network with two nodes connected back to back. The procedure is same if more than two nodes are present in the network. Using similar commands, user would be able to overlay multiple virtual LANs over the physical LAN created. The egress option of ip link command allow mapping packet priority to VLAN PCP values. In the example the packets on VLAN ID 2 is mapped to PCP value of 0 and VLAN ID 3 is mapped to PCP value of 7. At the Egress PRU Ethernet device looks at the PCP value and places it into one of the 4 queues. PRU scan the high priority queue first for packets and transmits them before transmitting packets from the lower priority queues. At the ingress, the PRU checks the PCP value of the packet in the VLAN header and places the frame into one of the ingress queues. More details on Queue usage is available at Queue Usage and VLAN PCP to Queue Map
In the above example, after passing some UDP traffic over hsr0.2 and hsr0.3, the user may check following statistics to verify if the packets are going over the right VLAN interface
On Node-1
cat /proc/net/vlan/hsr0.3
hsr0.3 VID: 3 REORDER_HDR: 1 dev->priv_flags: 1001
total frames received 68090
total bytes received 52598480
Broadcast/Multicast Rcvd 52
total frames transmitted 68090
total bytes transmitted 52598459
Device: hsr0
INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
EGRESS priority mappings: 0:7
root@am57xx-evm:~# cat /proc/net/vlan/hsr0.2
hsr0.2 VID: 2 REORDER_HDR: 1 dev->priv_flags: 1001
total frames received 68105
total bytes received 52604702
Broadcast/Multicast Rcvd 53
total frames transmitted 68074
total bytes transmitted 52583138
Device: hsr0
INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0
EGRESS priority mappings: 0:0
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-eth2/stats
TxQ-0 TxQ-1 TxQ-2 TxQ-3 RxQ-0 RxQ-1
=====================================================
68041 0 0 68908 67809 68925
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-eth3/stats
TxQ-0 TxQ-1 TxQ-2 TxQ-3 RxQ-2 RxQ-3
=====================================================
68041 0 0 68912 234 695
Similar procedure can be used for setting up VLAN interfaces over PRU EMAC and HSR Ethernet types.
4.2.3.6. VLAN Filtering¶
The PRU has a 4096 entry VLAN filter table that allows filtering out unwanted VLAN traffic to the host. As soon a VLAN interface is created, the 802.1q Linux kernel module sends the VID information down to the lower layer HSR or PRP Linux device which in turn pass it down to the slave Ethernet devices below it (or directly to the Ethernet device in the case of Dual EMAC). The PRU Ethernet driver gets the VID information via net_device_ops:ndo_vlan_rx_add_vid(). On receiving this, PRU Ethernet driver sets the entry at the VID index in VLAN filter table to 1. When the VLAN interface is deleted, the driver receives the same information through ndo_vlan_rx_kill_vid() and reset the entry at the VID index.
PRU firmware on receiving a VLAN frame, extracts the VID and look up the VLAN filter table for an entry at the VID if VLAN filtering is enabled in firmware. If the entry is 1, it forwards the frame to the Host. Otherwise the frame is dropped. There are additional controls to allow priority tagged frames to Host if the corrsponding bit is set in firmware shared memory. PRU Ethernet driver always enables Priority tagged frames to the Host. User may setup a VLAN interface with VID 0 to send or receive priority tagged frames. See section VLAN for details on how to assign egress priority mapping for the priority tagged VLAN interface.
Useful commands
User can use the following command to view the VLAN filter table at PRU. (Similar commands apply for HSR and Dual EMAC)
cat /sys/kernel/debug/prueth-prp-<ID>/vlan_filter
Where ID is described at PRU-ICSS Subsystem Driver
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-prp-2/vlan_filter
VLAN Filter : enabled
VLAN Filter untagged : allowed to Host
VLAN Filter priority tagged: allowed to Host
0: 0011000000000000000000000000000000000000000000000000000000000000
64: 0000000000000000000000000000000000000000000000000000000000000000
128: 0000000000000000000000000000000000000000000000000000000000000000
192: 0000000000000000000000000000000000000000000000000000000000000000
256: 0000000000000000000000000000000000000000000000000000000000000000
320: 0000000000000000000000000000000000000000000000000000000000000000
384: 0000000000000000000000000000000000000000000000000000000000000000
448: 0000000000000000000000000000000000000000000000000000000000000000
512: 0000000000000000000000000000000000000000000000000000000000000000
576: 0000000000000000000000000000000000000000000000000000000000000000
640: 0000000000000000000000000000000000000000000000000000000000000000
704: 0000000000000000000000000000000000000000000000000000000000000000
768: 0000000000000000000000000000000000000000000000000000000000000000
832: 0000000000000000000000000000000000000000000000000000000000000000
896: 0000000000000000000000000000000000000000000000000000000000000000
960: 0000000000000000000000000000000000000000000000000000000000000000
1024: 0000000000000000000000000000000000000000000000000000000000000000
1088: 0000000000000000000000000000000000000000000000000000000000000000
1152: 0000000000000000000000000000000000000000000000000000000000000000
1216: 0000000000000000000000000000000000000000000000000000000000000000
1280: 0000000000000000000000000000000000000000000000000000000000000000
1344: 0000000000000000000000000000000000000000000000000000000000000000
1408: 0000000000000000000000000000000000000000000000000000000000000000
1472: 0000000000000000000000000000000000000000000000000000000000000000
1536: 0000000000000000000000000000000000000000000000000000000000000000
1600: 0000000000000000000000000000000000000000000000000000000000000000
1664: 0000000000000000000000000000000000000000000000000000000000000000
1728: 0000000000000000000000000000000000000000000000000000000000000000
1792: 0000000000000000000000000000000000000000000000000000000000000000
1856: 0000000000000000000000000000000000000000000000000000000000000000
1920: 0000000000000000000000000000000000000000000000000000000000000000
1984: 0000000000000000000000000000000000000000000000000000000000000000
2048: 0000000000000000000000000000000000000000000000000000000000000000
2112: 0000000000000000000000000000000000000000000000000000000000000000
2176: 0000000000000000000000000000000000000000000000000000000000000000
2240: 0000000000000000000000000000000000000000000000000000000000000000
2304: 0000000000000000000000000000000000000000000000000000000000000000
2368: 0000000000000000000000000000000000000000000000000000000000000000
2432: 0000000000000000000000000000000000000000000000000000000000000000
2496: 0000000000000000000000000000000000000000000000000000000000000000
2560: 0000000000000000000000000000000000000000000000000000000000000000
2624: 0000000000000000000000000000000000000000000000000000000000000000
2688: 0000000000000000000000000000000000000000000000000000000000000000
2752: 0000000000000000000000000000000000000000000000000000000000000000
2816: 0000000000000000000000000000000000000000000000000000000000000000
2880: 0000000000000000000000000000000000000000000000000000000000000000
2944: 0000000000000000000000000000000000000000000000000000000000000000
3008: 0000000000000000000000000000000000000000000000000000000000000000
3072: 0000000000000000000000000000000000000000000000000000000000000000
3136: 0000000000000000000000000000000000000000000000000000000000000000
3200: 0000000000000000000000000000000000000000000000000000000000000000
3264: 0000000000000000000000000000000000000000000000000000000000000000
3328: 0000000000000000000000000000000000000000000000000000000000000000
3392: 0000000000000000000000000000000000000000000000000000000000000000
3456: 0000000000000000000000000000000000000000000000000000000000000000
3520: 0000000000000000000000000000000000000000000000000000000000000000
3584: 0000000000000000000000000000000000000000000000000000000000000000
3648: 0000000000000000000000000000000000000000000000000000000000000000
3712: 0000000000000000000000000000000000000000000000000000000000000000
3776: 0000000000000000000000000000000000000000000000000000000000000000
3840: 0000000000000000000000000000000000000000000000000000000000000000
3904: 0000000000000000000000000000000000000000000000000000000000000000
3968: 0000000000000000000000000000000000000000000000000000000000000000
4032: 0000000000000000000000000000000000000000000000000000000000000000
4.2.3.6.1. Dual EMAC¶
If using Dual EMAC, the only interface differences are the debugfs paths.
/sys/kernel/debug/prueth-eth<if number>/vlan_filter
Internally, the VLAN filter table(s) are stored in each PRU’s Data RAM (PRU0->Data RAM0, PRU1->Data RAM1) instead of one table in Shared RAM as for HSR/PRP.
Limitation
Currently, the PRU firmware is configured to receive all of the untagged frames from the network when the VLAN filtering is enabled. However there is no support for port VLAN which allows these frames to be received at a designated VLAN interface.
4.2.3.7. Broadcast Storm Prevention¶
Broadcast storm is defined as an excessive amount of Layer 2 broadcast Ethernet frames at the ingress of a network interface causing resources being wasted in the device for processing these frames and thereby affecting the device performance.
PRUETH driver implements a control mechanism that user can enable to drop these frames if the number of frames received during a window (100 msec) reaches a threshold. PRUETH uses a credit value as the threshold which is user configurable on a per interface basis. There is a sysfs entry
/sys/devices/platform/pruss<ID>_eth/net/eth<if number>/nsp_credit
Where ID and if number are obtained from the table under the section PRU-ICSS Subsystem Driver. The driver writes the credit value in DRAM based on the sysfs entry from user. The PRU firmware uses the credit value as a counter. The driver refreshes the counter every 100 msec. i.e write the credit value to memory every 100 msec. PRU Firmware upon receiving a broadcast frame decrements this counter until it becomes zero. Firmware forwards the broadcast frames to Host or ARM until the counter is non zero. PRU Firmware drops the broadcast frames if the counter is zero. Since driver writes the credit value to DRAM every 100 msec, the number of broadcast frames sent to host or ARM during a 100 msec window is limited to the credit value and anything beyond that is dropped by the firmware. Firmware maintains a statistics counter, stormPrevCounter, for the number of frames dropped due to storm prevention control and can be seen using ethtool -S command.
Note that this feature is disabled by default and user needs to configure it explicitely to enable the feature. A write of non zero value to the sysfs file enables the feature and zero disables the feature. The value to be used may be experimented in a particular network situation and configured by the user. In a typical network, there will be few of these per 100 msec window such as ARP broadcast, DHCP broadcast, router advetisement etc. So user may observe the broadcast traffic in the network using network tools such as wireshark and set the credit value accordingly.
Example
To enable do
>echo 10 > /sys/devices/platform/pruss2_eth/net/eth2/nsp_credit
for setting credit value to 10 for eth2. Similarly for other interfaces.
To disable do
>echo 0 > /sys/devices/platform/pruss2_eth/net/eth2/nsp_credit
4.2.3.8. Receive Interrupt Pacing¶
Currently PRUETH driver receives one interrupt per frame from each port. This results in lesser performance due to interrupt handling overhead in the Linux kernel especially for small size frames such as that used in grid infrastructure networks.
A well-known technique used in rx packet processing of a network driver is to use rx interrupt pacing to accumulate the Ethernet frames at the hardware or underlying network device’s buffer so as to generate less number of interrupts per packet to the host. This reduces the overhead in Linux kernel associated with interrupt handling by distributing the same over muliple packets, thereby reducing CPU usage. In this case PRUETH firmware accumulates the frames in the ingress ring buffer between host and PRU for a configurable period of time and raise an interrupt on timeout expiry (timeout equals to the configured period) there by resulting in lesser number of interrupts per frame. PRUETH firmware implements a Rx Pacing timer and the same gets configured by the PRUETH driver for HSR/PRP Ethernet types when the network device is opened and stopped when the device is closed. This timer is implemented per interface since driver has separate interrupts per PRU or interface.
The user may show the timer value using the ethtool –c option which is a standard Linux command to show different coalesce parameters at the network device. –C option allows user to override the default value at the device. The driver uses a default timeout value of 123 usec (Duration of an MTU frame). User is not expected to change this as there are limited number of buffers in the receive path between Host and PRU and using a bigger value can result in packet loss. However ethtool –c option is implemented in the PRUETH driver to show current setting in the driver and -C to change it if needed. Driver supports rx-usecs and adaptive-rx parameters from the available list of parameters and can be changed using –C option. When adaptive-rx is turned ON, every time a frame is received at the PRU and the buffer is empty, the PRU firmware raises an interrupt. However if the buffer is already occupied with some frames and the timer is already running, it will wait until timer expiry to raise the next interrupt. This would be useful to improve latency when using interrupts pacing. Currently this is disabled by default as enabling the same result in a lower throughput. However user may enable the same through ethtool –C command if needed.
Example
To show the current value of pacing timer, use
>ethtool –c <Ethernet interface>
To change the current value, use
>ethtool –C <Ethernet interface> <param> <value> <param> <value>
For example for eth2, user type
>ethtool –c eth2
Note that this changes the timer at both PRUs (for HSR/PRP). So the command may be issued to one of the pair of Ethernet interfaces used for the HSR or PRP interface. i.e for ICSS2 (assuming eth2 and eth3), user may use either of the below command to set the timer
>ethtool –C eth2 rx-usecs 123
or
>ethtool –C eth3 rx-usecs 123
Similarly to enable adaptive-rx, user types
>ethtool –C eth2 adaptive-rx on
or
>ethtool –C eth3 adaptive-rx on
Both parameters may be updated in one go as
>ethtool –C eth2 rx-usecs 123 adaptive-rx on
More details on the command syntax are available by typing man ethtool on a Linux PC as this is a standard Linux command.
4.2.3.9. VLAN Tag in Supervision frame¶
HSR/PRP protocol standard IEC62439-3 defines that the PRP_Supervision frame as well as HSR_Supervision frames optionally include a VLAN tag header. Starting with Processor SDK 5.1.x, VLAN tag is supprted in Linux HSR/PRP implementation.
In Linux, user use the ip link add command to create an HSR/PRP interface. ip link command is supported by the iproute2 package which is an open source software. hsr or prp type is currently a supported link type by ip link command. To support VLAN tag in SV frames, the command now accepts 3 more parameters from user. They are:-
- VLAN Identifier (VID) - sv_vid
- Priority code point (PCP) - sv_pcp
- Drop eligible indicator (DEI) or formerly known as Canonical Format Indicator (CFI) - sv_dei
User provides following values in the ip link add command for this purpose.
sv_vid <vid value> sv_pcp <pcp value> sv_dei <dei value>
These are all optional parameters. At least one of the value to be provided to use vlan. A default value of zero is used if not supplied by the user.
4.2.3.10. Node Table¶
HSR/PRP offloaded LRE supports a Node Table (NT) of 256 entries on AM5/K2G devices and 128 entries on AM3/4 devices. NT entries are maintained in shared RAM of the PRU ICSS. For HSR, an entry containing the MAC address of the remote node is inserted to the Node table when a supervison(SV) frame is received from that node. For PRP, this gets added for any frame received from the node. Firmware first looks up the address in the NT upon receiving a SV frame. The look up status is indicated in a bit in the buffer descriptor. The same is checked by the driver and if the look up status indicates no success, the MAC entry is inserted to the NT by driver. For subsequent frames received from the node, the firmware updates the NT and the insertion process is skipped in the driver.
The driver also runs an ageing timer to forget the node if there was no frame received from the remote node for a period of time as specified by the standard. During the timeout, if the entry is aged, then the same is deleted from the NT.
In Summary, search/update of an NT entry is done in firmware and insert/ delete of an entry is done by the driver.
The NT entries can be displayed by the user at the console using the proc file /proc/<if_name>/node-table.
Example: If the interface name is prp0, a sample command is shown below to display the NT entries.
root@am57xx-evm:~# cat /proc/prp0/node-table
Remote nodes in network: 1
Node[0]:
MAC ADDR: 70:ff:76:1c:16:ef
DANP
Time Last Seen: RxA=0 RxB=0
4.2.3.11. Net-SNMP¶
The TI SDK release ships tisdk-rootfs-image-am57xx-evm.tar.xz with Net-SNMP 5.7.3 binaries pre-installed and snmpd is started as part of the user space initialization. TI has developed a Net-SNMP module to support IEC-62439-3 related MIB access at the DAN using snmp commands such as snmpwalk, snmpget etc. NOTE: IEC-62439-3 MIB is supported only in the offloaded case. So user is expected to create HSR/PRP interface with offload. For details on how to setup HSR/PRP interface with offload, please refer Testing HSR/PRP Firmware Offload
Command examples
An example snmpwalk command execution is shown below where 192.168.2.20 is the IP address of the remote DAN-P or DAN-H prp/hsr interface.
root@am57xx-evm:/etc/snmp# snmpwalk -v 2c -c public 192.168.2.20 iec62439
IEC-62439-3-MIB::lreManufacturerName.0 = STRING: TI LRE
IEC-62439-3-MIB::lreInterfaceCount.0 = INTEGER: 1
IEC-62439-3-MIB::lreRowStatus.1 = INTEGER: active(1)
IEC-62439-3-MIB::lreNodeType.1 = INTEGER: hsr(2)
IEC-62439-3-MIB::lreNodeName.1 = STRING: hsr0
IEC-62439-3-MIB::lreVersionName.1 = ""
IEC-62439-3-MIB::lreMacAddress.1 = STRING: d2:ef:e6:2a:1f:5b
IEC-62439-3-MIB::lrePortAdminStateA.1 = INTEGER: active(2)
IEC-62439-3-MIB::lrePortAdminStateB.1 = INTEGER: active(2)
IEC-62439-3-MIB::lreLinkStatusA.1 = INTEGER: up(1)
IEC-62439-3-MIB::lreLinkStatusB.1 = INTEGER: up(1)
IEC-62439-3-MIB::lreDuplicateDiscard.1 = INTEGER: discard(2)
IEC-62439-3-MIB::lreTransparentReception.1 = INTEGER: 0
IEC-62439-3-MIB::lreHsrLREMode.1 = INTEGER: modeh(1)
IEC-62439-3-MIB::lreSwitchingEndNode.1 = INTEGER: hsrnode(5)
IEC-62439-3-MIB::lreRedBoxIdentity.1 = INTEGER: id1a(2)
IEC-62439-3-MIB::lreEvaluateSupervision.1 = INTEGER: true(1)
IEC-62439-3-MIB::lreNodesTableClear.1 = INTEGER: noOp(0)
IEC-62439-3-MIB::lreProxyNodeTableClear.1 = INTEGER: noOp(0)
IEC-62439-3-MIB::lreDupListResideMaxTime.1 = INTEGER: 26214 binaryFractionOfSecond
IEC-62439-3-MIB::lreCntTxA.1 = Counter32: 7384
IEC-62439-3-MIB::lreCntTxB.1 = Counter32: 7385
IEC-62439-3-MIB::lreCntTxC.1 = Counter32: 4032
IEC-62439-3-MIB::lreCntErrWrongLanA.1 = Counter32: 0
IEC-62439-3-MIB::lreCntErrWrongLanB.1 = Counter32: 0
IEC-62439-3-MIB::lreCntErrWrongLanC.1 = Counter32: 0
IEC-62439-3-MIB::lreCntRxA.1 = Counter32: 4024
IEC-62439-3-MIB::lreCntRxB.1 = Counter32: 4025
IEC-62439-3-MIB::lreCntRxC.1 = Counter32: 0
IEC-62439-3-MIB::lreCntErrorsA.1 = Counter32: 3351
IEC-62439-3-MIB::lreCntErrorsB.1 = Counter32: 3351
IEC-62439-3-MIB::lreCntErrorsC.1 = Counter32: 0
IEC-62439-3-MIB::lreCntNodes.1 = INTEGER: 1
IEC-62439-3-MIB::lreCntProxyNodes.1 = INTEGER: 0
IEC-62439-3-MIB::lreCntUniqueA.1 = Counter32: 4
IEC-62439-3-MIB::lreCntUniqueB.1 = Counter32: 4
IEC-62439-3-MIB::lreCntUniqueC.1 = Counter32: 0
IEC-62439-3-MIB::lreCntDuplicateA.1 = Counter32: 0
IEC-62439-3-MIB::lreCntDuplicateB.1 = Counter32: 0
IEC-62439-3-MIB::lreCntDuplicateC.1 = Counter32: 3992
IEC-62439-3-MIB::lreCntMultiA.1 = Counter32: 0
IEC-62439-3-MIB::lreCntMultiB.1 = Counter32: 0
IEC-62439-3-MIB::lreCntMultiC.1 = Counter32: 0
IEC-62439-3-MIB::lreCntOwnRxA.1 = Counter32: 0
IEC-62439-3-MIB::lreCntOwnRxB.1 = Counter32: 0
IEC-62439-3-MIB::lreNodesMacAddress.1.1 = STRING: 70:ff:76:1c:f:8d
IEC-62439-3-MIB::lreTimeLastSeenA.1.1 = Timeticks: (0) 0:00:00.00
IEC-62439-3-MIB::lreTimeLastSeenB.1.1 = Timeticks: (1) 0:00:00.01
IEC-62439-3-MIB::lreRemNodeType.1.1 = INTEGER: danh(3)
Individual MIB variable may be queried or set using snmpset or snmpget commands. Below are some examples:-
snmpset
snmpset -v 2c -c private 192.168.2.20 IEC-62439-3-MIB::lreHsrLREMode.1 i 3
snmpget
snmpget -v 2c -c public 192.168.2.20 IEC-62439-3-MIB::lreManufacturerName.0
MIB Support
MIB variable | Group | Actions Specified by Standard | Action supported |
---|---|---|---|
lreManufacturerName | lreConfigurationGeneralGroup | get | get |
lreInterfaceCount | lreConfigurationGeneralGroup | get | get |
lreInterfaceConfigTable | lreConfigurationInterfaceGroup | NA | NA |
lreInterfaceConfigEntry | lreConfigurationInterfaceGroup | NA | NA |
lreInterfaceConfigIndex | lreConfigurationInterfaceGroup | NA | NA |
lreRowStatus | lreConfigurationInterfaceGroup | NA | get |
lreNodeType | lreConfigurationInterfaceGroup | get/set | get |
lreNodeName | lreConfigurationInterfaceGroup | get/set | get |
lreVersionName | lreConfigurationInterfaceGroup | get | get |
lreMacAddress | lreConfigurationInterfaceGroup | get/set | get |
lrePortAdminStateA | lreConfigurationInterfaceGroup | get/set | get |
lrePortAdminStateB | lreConfigurationInterfaceGroup | get/set | get |
lreLinkStatusA | lreConfigurationInterfaceGroup | get | get |
lreLinkStatusB | lreConfigurationInterfaceGroup | get | get |
lreDuplicateDiscard | lreConfigurationInterfaceGroup | get/set | get/set |
lreTransparentReception | lreConfigurationInterfaceGroup | get/set | get/set |
lreHsrLREMode | lreConfigurationInterfaceGroup | get/set | get/set |
lreSwitchingEndNode | lreConfigurationInterfaceGroup | get/set | get |
lreRedBoxIdentity | lreConfigurationInterfaceGroup | get/set | NS |
lreEvaluateSupervision | lreConfigurationInterfaceGroup | get/set | NS |
lreNodesTableClear | lreConfigurationInterfaceGroup | get/set | get/set |
lreProxyNodeTableClear | lreConfigurationInterfaceGroup | get/set | NS |
lreDupListResideMaxTime | lreConfigurationInterfaceGroup | get/set | get |
lreInterfaceStatsTable | lreStatisticsInterfaceGroup | NA | NA |
lreInterfaceStatsEntry | lreStatisticsInterfaceGroup | NA | NA |
lreInterfaceStatsIndex | lreStatisticsInterfaceGroup | NA | Yes |
lreCntTxA | lreStatisticsInterfaceGroup | get | get |
lreCntTxB | lreStatisticsInterfaceGroup | get | get |
lreCntTxC | lreStatisticsInterfaceGroup | get | get |
lreCntErrWrongLanA | lreStatisticsInterfaceGroup | get | get |
lreCntErrWrongLanB | lreStatisticsInterfaceGroup | get | get |
lreCntErrWrongLanC | lreStatisticsInterfaceGroup | get | get |
lreCntRxA | lreStatisticsInterfaceGroup | get | get |
lreCntRxB | lreStatisticsInterfaceGroup | get | get |
lreCntRxC | lreStatisticsInterfaceGroup | get | get |
lreCntErrorsA | lreStatisticsInterfaceGroup | get | get |
lreCntErrorsB | lreStatisticsInterfaceGroup | get | get |
lreCntErrorsC | lreStatisticsInterfaceGroup | get | get |
lreCntNodes | lreStatisticsInterfaceGroup | get | get |
lreCntProxyNodes | lreStatisticsInterfaceGroup | get | NS |
lreCntUniqueA | lreStatisticsInterfaceGroup | get | get |
lreCntUniqueB | lreStatisticsInterfaceGroup | get | get |
lreCntUniqueC | lreStatisticsInterfaceGroup | get | get |
lreCntDuplicateA | lreStatisticsInterfaceGroup | get | get |
lreCntDuplicateB | lreStatisticsInterfaceGroup | get | get |
lreCntDuplicateC | lreStatisticsInterfaceGroup | get | get |
lreCntMultiA | lreStatisticsInterfaceGroup | get | get |
lreCntMultiB | lreStatisticsInterfaceGroup | get | get |
lreCntMultiC | lreStatisticsInterfaceGroup | get | get |
lreCntOwnRxA | lreStatisticsInterfaceGroup | get | get |
lreCntOwnRxB | lreStatisticsInterfaceGroup | get | get |
lreNodesTable | lreStatisticsInterfaceGroup | NA | Yes |
lreNodesIndex | lreStatisticsInterfaceGroup | NA | Yes |
lreNodesMacAddress | lreStatisticsInterfaceGroup | get | get |
lreTimeLastSeenA | lreStatisticsInterfaceGroup | get | get |
lreTimeLastSeenB | lreStatisticsInterfaceGroup | get | get |
lreRemNodeType | lreStatisticsInterfaceGroup | get | get |
lreProxyNodeTable | lreStatisticsInterfaceGroup | NS | |
lreProxyNodeEntry | lreStatisticsInterfacesGroup | NA | NS |
lreProxyNodeMacAddress | lreStatisticsInterfacesGroup | get | NS |
Note NS: Not supported, NA: Not Applicable
4.2.3.12. iproute2¶
iproute2 is enhanced to allow creating a prp interface similar to hsr interface using two slave interfaces.
4.2.3.13. Test Procedure¶
4.2.3.13.1. Testing HSR/PRP Firmware Offload¶
The setup of the IDKs for testing HSR/PRP firmware offload and the configuration of the HSR/PRP interfaces after kernel boot up are no different than the case without firmware offload. The differences are, in the case of firmware offload, the correct PRU firmware needs to be loaded and the PRUETH driver needs to be configured to interface with the type of firmware loaded, during boot up.
The module parameter “ti_prueth.pruss1_ethtype” and “ti_prueth.pruss2_ethtype” are used for instructing the PRU Ethernet driver what type of PRU firmware is to be loaded to PRU-ICSS1 and PRU-ICSS2 respectively. These type values are:
ti_prueth.prussX_ethtype, X = 1,2 | firmware type |
---|---|
0 | EMAC |
1 | HSR |
2 | PRP |
These ti_prueth.prussX_type values can be set up in the Kernel boot argument in Uboot. For example, to load HSR firmware to PRU-ICSS1 and PRP firmware to PRU-ICSS2, and assuming boot using NFS rootfs, the Kernel boot argument can be configured as follows. Under Uboot prompt,
=> setenv netargs 'setenv bootargs console=${console} ${optargs} root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} rw ip=dhcp
ti_prueth.pruss1_ethtype=${pruss1_ethtype} ti_prueth.pruss2_ethtype=${pruss2_ethtype}'
=> setenv pruss1_ethtype 1
=> setenv pruss2_ethtype 2
=> saveenv
NOTE If using mmc rootfs, update args_mmc as below
=> setenv args_mmc 'run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype}
ti_prueth.pruss1_ethtype=${pruss1_ethtype} ti_prueth.pruss2_ethtype=${pruss2_ethtype}'
Just change the value of pruss1_ethtype or pruss2_ethtype in the above example to switch to a different type of firmware (see the above table). If a ti_prueth.prussX_ethtype is not configured, ie. does not appear in Kernel boot argument, the default EMAC firmware will be loaded to the corresponding PRU-ICSSX. In this case, if user sets up HSR/PRP interface, it will work without offload using the PRU EMAC firmware and driver. So using offload or no offload is controlled via selecting appropriate firmware at boot up and is transparent to user.
Remarks:
- Setting ti_prueth.prussX_ethtype to 0 is the same as not using it in the Kernel argument. In either case, default EMAC firmware is loaded.
- “ti_prueth.prussX_ethtype=”, ie. setting the module parameter but without a value, is incorrect.
- On AM572x IDK, only PRU-ICSS2 is supported. Hence only prueth.pruss2_type takes effect.
To verify PRU Ethernet type after boot, do following that display TI PRU ethernet type
dmesg | grep "TI PRU ethernet (type"
For PRU Emac, the string displayed will be
prueth pruss2_eth: TI PRU ethernet (type 0) driver initialized
For PRU HSR, the string displayed will be
prueth pruss2_eth: TI PRU ethernet (type 1) driver initialized
For PRU PRP, the string displayed will be
prueth pruss2_eth: TI PRU ethernet (type 2) driver initialized
Where type is what is set in the bootargs and is listed in the table at the beginning of this section
4.2.3.13.2. Node Tables (firmware offload)¶
In the case of HSR/PRP firmware offload, the Node Table can be displayed as follows. Note: the locations are different from those when there is no firmware offload.
To show the HSR Node Table, under the kernel prompt on the terminal connected to the IDK, do
- root@am57xx-evm:~# cat /sys/kernel/debug/prueth-hsr-<ID>/node_table
- Sample display
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-hsr-2/node_table
Remote nodes in network: 1
Node[1]:
MAC ADDR: 70:ff:76:1c:0f:99
state: valid
DANH
RxA=2992 SupRxA=148
RxB=2992 SupRxB=148
Time Last Seen: Sup=0 RxA=0 RxB=0
To show the PRP Node Table, under the kernel prompt on the terminal connected to the IDK, do
- root@am57xx-evm:~# cat /sys/kernel/debug/prueth-prp-<ID>/node_table
- Sample display
root@am57xx-evm:~# cat /sys/kernel/debug/prueth-prp-2/node_table
Remote nodes in network: 1
Node[1]:
MAC ADDR: 70:ff:76:1c:0f:99
state: valid
DupDiscard (0x80)
DANP
RxA=17 SupRxA=17
RxB=17 SupRxB=17
Time Last Seen: Sup=0 RxA=0 RxB=0
PRP LineID Err: A=0 B=0
4.2.3.13.3. LRE Statistics (firmware offload)¶
The LRE statistics is displayed as part the interface statistics using the “ethtool -S DEVNAME” command, where DEVNAME, in the case AM572x IDK, is eth2 or eth3. The fields pertaining to LRE statistics are prefixed with “lre”. Since LRE statistics are LRE specific, instead of interface specific, so either “ethtool -S eth2” or “ethtool -S eth3” will show the same LRE statistics.
Sample display:
root@am57xx-evm:~# ethtool -S eth2
NIC statistics:
txBcast: 1
txMcast: 11635
txUcast: 3
txOctets: 816642
rxBcast: 0
rxMcast: 36
rxUcast: 17
rxOctets: 4841
tx64byte: 6
tx65_127byte: 11633
tx128_255byte: 0
tx256_511byte: 0
tx512_1023byte: 0
tx1024byte: 0
rx64byte: 4
rx65_127byte: 49
rx128_255byte: 0
rx256_511byte: 0
rx512_1023byte: 0
rx1024byte: 0
lateColl: 0
singleColl: 0
multiColl: 0
excessColl: 0
rxMisAlignmentFrames: 0
stormPrevCounter: 0
macRxError: 0
SFDError: 0
defTx: 0
macTxError: 0
rxOverSizedFrames: 0
rxUnderSizedFrames: 0
rxCRCFrames: 0
droppedPackets: 0
txHWQOverFlow: 0
txHWQUnderFlow: 0
lreTxA: 11636
lreTxB: 11639
lreTxC: 66
lreErrWrongLanA: 0
lreErrWrongLanB: 0
lreErrWrongLanC: 0
lreRxA: 40
lreRxB: 40
lreRxC: 0
lreErrorsA: 11560
lreErrorsB: 11559
lreErrorsC: 0
lreNodes: 0
lreProxyNodes: 0
lreUniqueRxA: 0
lreUniqueRxB: 0
lreUniqueRxC: 0
lreDuplicateRxA: 0
lreDuplicateRxB: 0
lreDuplicateRxC: 0
lreMultiRxA: 0
lreMultiRxB: 0
lreMultiRxC: 0
lreOwnRxA: 0
lreOwnRxB: 0
lreDuplicateDiscard: 2
lreTransRecept: 1
lreNtLookupErrA: 0
lreNtLookupErrB: 0
lreNodeTableFull: 0
4.2.3.13.4. HSR Testing¶
To test HSR, user would need two AM572x EVMs.
- Setup HSR Ring network as per diagram below. Connect the PRU2ETH0 (See the marking on the EVM) Ethernet ports of the two EVMs together (corresponds to Linux interface eth2) as shown below. Similarly, connect the PRU2ETH1 ports (Linux interface eth3) as well.
- Configure the bootargs to boot PRU with HSR firmware as described above at Testing HSR/PRP Firmware Offload
- Boot the EVMs using the pre-built images from the Processor SDK release. These images are built with Linux HSR/PRP driver enabled. Login to the console using root user name.
- Note the MAC Address of eth2 at DAN-H-1(Say MAC-A) using the ifconfig command. Do ifconfig eth2 at the Linux console of DAN-H-1
- Note the MAC Address of eth2 at DAN-H-2(Say MAC-B) using the ifconfig
command. Do ifconfig eth2 at the Linux console of DAN-H-2
- ifconfig eth2 down
- ifconfig eth3 down
- ifconfig eth3 hw ether <MAC-A>
- ifconfig eth2 up
- ifconfig eth3 up
- ip link add name hsr0 type hsr slave1 eth2 slave2 eth3 supervision 45 version 1
- ifconfig hsr0 <IP Address of hsr interface at DAN-H-1> up
- Repeat the above steps for DAN-H-2, but this time use MAC-B in step 4.3 above. And use IP Address from the same subnet as that of DAN-H-1 hsr interface hsr0.
For example use Ip Address 192.168.2.20 for DAN-H-1 and 192.168.2.30 for DAN-H-2. Assume CPSW ports at the EVM are on a different Subnet than the HSR interface.
Once both hsr0 interfaces are created, user should be able to do a ping from DAN-H-1 to DAN-H-2 or vice-versa. Disconnect Ethernet cable at eth2 or eth3. The Ping should continue to go through. User could run iperf between the two HSR interfaces and test the iperf is not affected when one of the cable is disconnected. This verifies redundancy.
A Sample script that automates the steps 4.1 to 4.7, say setup.sh, is below
#!/bin/sh
if [ $# -lt 3 ]
then
echo "setup.sh <hsr/prp> <MAC-Address for both slaves> <ip address for hsr/prp interface>"
exit
fi
if [ "$1" != "hsr" ] && [ "$1" != "prp" ]
then
echo "use hsr or prp as first argument"
exit
fi
echo "Setting up $10 interface with MAC address $2 for slaves and IP address $3"
ifconfig eth2 down
ifconfig eth3 down
ifconfig eth2 hw ether $2
ifconfig eth3 hw ether $2
ifconfig eth2 up
ifconfig eth3 up
if [ "$1" == "hsr" ]
then
ip link add name hsr0 type hsr slave1 eth2 slave2 eth3 supervision 45 version 1
ifconfig hsr0 $3 up
else
ip link add name prp0 type prp slave1 eth2 slave2 eth3 supervision 45
ifconfig prp0 $3 up
fi
Using this script, user can setup hsr interface as
/setup.sh hsr <MAC-A> <IP Address of the interface>
where it is assumed that the setup.sh is copied to the root directory of the target file system and is made executable
Below script can be used to teardown the hsr interface (say teardown.sh)
#!/bin/sh
if [ $# -lt 1 ]
then
echo "teardown.sh <hsr/prp>"
exit
fi
if [ "$1" != "hsr" ] && [ "$1" != "prp" ]
then
echo "use hsr or prp as first argument"
exit
fi
if [ "$1" == "hsr" ]
then
ip link del hsr0
else
ip link del prp0
fi
Using the above script, user teardown the hsr interface as
/teardown.sh hsr
Sample script below can be used to create two instances of HSR/PRP at PRU-ICSS1 and PRU-ICSS2 on AM571x. For other platform where applicable, this can be customized by changing the slave eth interface names to match with that on the specific platform. The script also allows configuring the LRE to use VLAN tag for Supervision frames by providing an optional vlan string in the command line of the script as documented in the script.
On PRU-ICSS1 of AM571x
#!/bin/sh
if [ $# -lt 4 ]
then
echo "setup-pruss1.sh <hsr/prp> <MAC-Address of slave-A>"
echo " <ip address for hsr/prp interface>"
echo " <if_name of hsr/prp interface> [vlan]"
echo " vlan is optional and if present use vlan tag"
echo " in the SV frame. Use values of vid, pcp and"
echo " and dei hardcoded in the script"
exit
fi
if [ "$1" != "hsr" ] && [ "$1" != "prp" ]
then
echo "use hsr or prp as first argument"
exit
fi
if_a=eth4
if_b=eth5
if_name=$4
vl=$5
#change this as needed
vid=10
pcp=5
dei=0
ifconfig $if_a down
ifconfig $if_b down
ifconfig $if_a hw ether $2
ifconfig $if_b hw ether $2
ifconfig $if_a up
ifconfig $if_b up
echo "Setting up $if_name with MAC address $2 for slaves and IP address $3"
echo " using $if_a and $if_b"
if [ "$1" = "hsr" ]; then
if [ "$vl" = "vlan" ]; then
options="version 1 sv_vid $vid sv_pcp $pcp sv_dei $dei"
echo $options
else
options="version 1"
fi
else
if [ "$vl" = "vlan" ]; then
options="sv_vid $vid sv_pcp $pcp sv_dei $dei"
else
options=""
fi
fi
ip link add name $if_name type $1 slave1 $if_a slave2 $if_b supervision 0 $options
ifconfig $if_name $3 up
On PRU-ICSS2 of AM571x
#!/bin/sh
if [ $# -lt 4 ]
then
echo "setup-pruss2.sh <hsr/prp> <MAC-Address of slave-A>"
echo " <ip address for hsr/prp interface>"
echo " <if_name of hsr/prp interface> [vlan]"
echo " vlan is optional and if present use vlan tag"
echo " in the SV frame. Use values of vid, pcp and"
echo " and dei hardcoded in the script"
exit
fi
if [ "$1" != "hsr" ] && [ "$1" != "prp" ]
then
echo "use hsr or prp as first argument"
exit
fi
if_a=eth2
if_b=eth3
if_name=$4
vl=$5
#change this as needed
vid=10
pcp=5
dei=0
ifconfig $if_a down
ifconfig $if_b down
ifconfig $if_a hw ether $2
ifconfig $if_b hw ether $2
ifconfig $if_a up
ifconfig $if_b up
echo "Setting up $if_name with MAC address $2 for slaves and IP address $3"
echo " using $if_a and $if_b"
if [ "$1" = "hsr" ]; then
if [ "$vl" = "vlan" ]; then
options="version 1 sv_vid $vid sv_pcp $pcp sv_dei $dei"
echo $options
else
options="version 1"
fi
else
if [ "$vl" = "vlan" ]; then
options="sv_vid $vid sv_pcp $pcp sv_dei $dei"
else
options=""
fi
fi
ip link add name $if_name type $1 slave1 $if_a slave2 $if_b supervision 0 $options
ifconfig $if_name $3 up
Sample logs are shown below:
DAN-H-1
root@am57xx-evm:~# ifconfig eth2
eth2 Link encap:Ethernet HWaddr 70:FF:76:1C:0F:8D [ 38.944687] random: nonblocking pool is initialized
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@am57xx-evm:~# /setup.sh hsr 70:FF:76:1C:0F:8D 192.168.2.20
Setting up hsr0 interface with MAC address 70:FF:76:1C:0F:8D for slaves and IP address 192.168.2.20
[ 62.319328] remoteproc6: powering up 4b2b4000.pru0
[ 62.325015] remoteproc6: Booting fw image ti-pruss/am57xx-pru0-prueth-fw.elf, size 4350
[ 62.335303] ti-pruss 4b280000.pruss: configured system_events = 0x0000060000500000 intr_channels = 0x00000095 host_intr = 0x00000115
[ 62.348724] remoteproc6: remote processor 4b2b4000.pru0 is now up
[ 62.354947] net eth2: started
[ 62.360842] IPv6: ADDRCONF(NETDEV_UP): eth2: link is not ready
[ 62.408479] remoteproc7: powering up 4b2b8000.pru1
[ 62.413790] remoteproc7: Booting fw image ti-pruss/am57xx-pru1-prueth-fw.elf, size 4382
[ 62.422088] ti-pruss 4b280000.pruss: configured system_events = 0x0060000000a00000 intr_channels = 0x0000012a host_intr = 0x0000022a
[ 62.434059] remoteproc7: remote processor 4b2b8000.pru1 is now up
[ 62.440281] net eth3: started
[ 62.444625] IPv6: ADDRCONF(NETDEV_UP): eth3: link is not ready
[ 62.509276] device eth2 entered promiscuous mode
[ 62.549502] device eth3 entered promiscuous mode
[ 62.593878] hsr0: Slave A (eth2) is not up; please bring it up to get a fully working HSR network
[ 62.604214] IPv6: ADDRCONF(NETDEV_UP): hsr0: link is not ready
[ 62.614722] IPv6: ADDRCONF(NETDEV_CHANGE): hsr0: link becomes ready
root@am57xx-evm:~#
root@am57xx-evm:~# [ 63.648569] eth2: Link is Up - 100Mbps/Full - flow control off
[ 63.654446] IPv6: ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
[ 63.748602] eth3: Link is Up - 100Mbps/Full - flow control off
[ 63.754477] IPv6: ADDRCONF(NETDEV_CHANGE): eth3: link becomes ready
=========Setup hsr0 on DAN-H-2=============================================
root@am57xx-evm:~# ping 192.168.2.30
PING 192.168.2.30 (192.168.2.30): 56 data bytes
64 bytes from 192.168.2.30: seq=0 ttl=64 time=0.400 ms
64 bytes from 192.168.2.30: seq=1 ttl=64 time=0.190 ms
64 bytes from 192.168.2.30: seq=2 ttl=64 time=0.200 ms
--- 192.168.2.30 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.190/0.263/0.400 ms
root@am57xx-evm:~#
root@am57xx-evm:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 33546
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 108 MBytes 90.7 Mbits/sec
root@am57xx-evm:~# iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 47913
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0-10.0 sec 106 MBytes 89.0 Mbits/sec 0.078 ms 587/76246 (0.77%)
[ 3] 0.0-10.0 sec 1 datagrams received out-of-order
root@am57xx-evm:~#
root@am57xx-evm:~# cat /proc/hsr0/node-table
Remote nodes in network: 1
Node[0]:
MAC ADDR: d6:ab:09:0d:f0:e5
DANH
Time Last Seen: RxA=0 RxB=0
root@am57xx-evm:~# cat /proc/hsr0/lre-stats
LRE statistics:
Rx Offloaded: 1
lreTxA: 15915369
lreTxB: 15915369
lreTxC: 673
lreErrWrongLanA: 207816
lreErrWrongLanB: 207789
lreErrWrongLanC: 0
lreRxA: 0
lreRxB: 27
lreRxC: 15707590
lreErrorsA: 0
lreErrorsB: 0
lreErrorsC: 0
lreNodes: 1
lreProxyNodes: 0
lreUniqueRxA: 0
lreUniqueRxB: 0
lreUniqueRxC: 0
lreDuplicateRxA: 0
lreDuplicateRxB: 0
lreDuplicateRxC: 0
lreMultiRxA: 0
lreMultiRxB: 0
lreMultiRxC: 0
lreOwnRxA: 0
lreOwnRxB: 0
DAN-H-2
root@am57xx-evm:~# ifconfig eth2
eth2 Link encap:Ethernet HWaddr D6:AB:09:0D:F0:E5
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@am57xx-evm:~# /setup.sh hsr D6:AB:09:0D:F0:E5 192.168.2.30
Setting up hsr0 interface with MAC address D6:AB:09:0D:F0:E5 for slaves and IP address
192.168.2.30
[ 66.015629] remoteproc6: powering up 4b2b4000.pru0
[ 66.021263] remoteproc6: Booting fw image ti-pruss/am57xx-pru0-prueth-fw.elf, size 4350
[ 66.031502] ti-pruss 4b280000.pruss: configured system_events = 0x0000060000500000
intr_channels = 0x00000095 host_intr = 0x00000115
[ 66.044965] remoteproc6: remote processor 4b2b4000.pru0 is now up
[ 66.052043] net eth2: started
[ 66.055419] IPv6: ADDRCONF(NETDEV_UP): eth2: link is not ready
[ 66.108268] remoteproc7: powering up 4b2b8000.pru1
[ 66.113562] remoteproc7: Booting fw image ti-pruss/am57xx-pru1-prueth-fw.elf, size 4382
[ 66.123585] ti-pruss 4b280000.pruss: configured system_events = 0x0060000000a00000
intr_channels = 0x0000012a host_intr = 0x0000022a
[ 66.136973] remoteproc7: remote processor 4b2b8000.pru1 is now up
[ 66.143998] net eth3: started
[ 66.147284] IPv6: ADDRCONF(NETDEV_UP): eth3: link is not ready
[ 66.218855] device eth2 entered promiscuous mode
[ 66.258015] device eth3 entered promiscuous mode
[ 66.303911] hsr0: Slave A (eth2) is not up; please bring it up to get a fully working HSR
network
[ 66.313621] IPv6: ADDRCONF(NETDEV_UP): hsr0: link is not ready
[ 66.323162] IPv6: ADDRCONF(NETDEV_CHANGE): hsr0: link becomes ready
root@am57xx-evm:~# [ 67.358460] eth2: Link is Up - 100Mbps/Full - flow control off
[ 67.364336] IPv6: ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
[ 67.518489] eth3: Link is Up - 100Mbps/Full - flow control off
[ 67.524363] IPv6: ADDRCONF(NETDEV_CHANGE): eth3: link becomes ready
root@am57xx-evm:~# iperf -c 192.168.2.20
------------------------------------------------------------
Client connecting to 192.168.2.20, TCP port 5001
TCP window size: 70.0 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 33546 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 108 MBytes 90.9 Mbits/sec
root@am57xx-evm:~# iperf -c 192.168.2.20 -u -b 90M
------------------------------------------------------------
Client connecting to 192.168.2.20, UDP port 5001
Sending 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 47913 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 107 MBytes 89.7 Mbits/sec
[ 3] Sent 76247 datagrams
[ 3] Server Report:
[ 3] 0.0-10.0 sec 106 MBytes 89.0 Mbits/sec 0.078 ms 587/76246 (0.77%)
[ 3] 0.0-10.0 sec 1 datagrams received out-of-order
root@am57xx-evm:~# cat /proc/hsr0/node-table
Remote nodes in network: 1
Node[0]:
MAC ADDR: 70:ff:76:1c:0f:8d
DANH
Time Last Seen: RxA=0 RxB=0
root@am57xx-evm:/# cat /proc/prp0/lre-stats
LRE statistics:
Rx Offloaded: 1
lreTxA: 208128
lreTxB: 208128
lreTxC: 31305063
lreErrWrongLanA: 0
lreErrWrongLanB: 0
lreErrWrongLanC: 0
lreRxA: 0
lreRxB: 0
lreRxC: 208
lreErrorsA: 0
lreErrorsB: 0
lreErrorsC: 0
lreNodes: 1
lreProxyNodes: 0
lreUniqueRxA: 0
lreUniqueRxB: 0
lreUniqueRxC: 0
lreDuplicateRxA: 0
lreDuplicateRxB: 0
lreDuplicateRxC: 0
lreMultiRxA: 0
lreMultiRxB: 0
lreMultiRxC: 0
lreOwnRxA: 0
lreOwnRxB: 0
4.2.3.13.5. PRP Testing¶
For Testing PRP, user is required to use the setup shown in the above diagram. A DAN-P is attached to two independent networks (A and B) each of which is shown as a separate Ethernet switch. Do the following steps to setup the prp interface. Note that in the below example Linux interface eth2 is Link-A (slave1 in ip link command) and eth3 is Link-B (slave2 in ip link command). Link-A is the Ethernet cable that connects DUT to Switch A and Link-B is the Ethernet cable that connects to Switch-B. This is very important for PRP as swapping them is an incorrect connection and can produce undesirable results.
- Connect the DAN-P-1 EVM, PRU2ETH0 (marking on EVM) to a port at Ethernet switch A and PRU2ETH1 to a port at Ethernet switch B
- Similarly, connect DAN-P-2 EVM, PRU2ETH0 to a port at Ethernet switch A and PRU2ETH1 to a port at Ethernet switch B
- Configure the PRU to load PRP firmware by setting env variable as discussed at Testing HSR/PRP Firmware Offload
- Boot the EVMs using the pre-built images from the Processor SDK release. These images are built with Linux HSR/PRP driver enabled. Login to the console using root user name.
- This time user may use the script (setup.sh) to create the prp interface. Note the MAC-A and MAC-B as in the case of HSR (MAC address of eth2)
- setup the prp interface at DAN-P-1 as follows
- /setup.sh prp <MAC-A> <IP Address of prp interface>
- setup the prp interface at DAN-P-2 as follows:-
- /setup.sh prp <MAC-B> <IP Address of prp interface>
If PRP interface uses IP address 192.168.2.20 and eth2 MAC address is 70:ff:76:1c:0f:8d, following example command may be used at DAN-P-1
/setup.sh prp 70:ff:76:1c:0f:8d 192.168.2.20
If PRP interface uses IP address 192.168.2.30 and eth2 MAC address is 70:ff:76:1c:0f:8e following example command may be use at DAN-P-2
/setup.sh prp 70:ff:76:1c:0f:8e 192.168.2.30
To teardown the prp interface do
/teardown.sh prp
Sample logs are shown below:
DAN-P-1
root@am57xx-evm:~# ifconfig eth2
eth2 Link encap:Ethernet HWaddr 70:FF:76:1C:0F:8D
inet6 addr: fe80::72ff:76ff:fe1c:f8d%3068183320/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:80429 errors:0 dropped:0 overruns:0 frame:593
TX packets:40905 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:121704175 (116.0 MiB) TX bytes:2716445 (2.5 MiB)
root@am57xx-evm:~# /setup.sh prp 70:FF:76:1C:0F:8D 192.168.2.20
Setting up prp0 interface with MAC address 70:FF:76:1C:0F:8D for slaves and IP address
192.168.2.20
[21649.978346] ti-pruss 4b280000.pruss: unconfigured system_events = 0x0000060000500000
host_intr = 0x00000115
[21649.988138] remoteproc6: stopped remote processor 4b2b4000.pru0
[21649.994196] net eth2: stopped
[21650.048408] ti-pruss 4b280000.pruss: unconfigured system_events = 0x0060000000a00000
host_intr = 0x0000022a
[21650.058199] remoteproc7: stopped remote processor 4b2b8000.pru1
[21650.064258] net eth3: stopped
[21650.084733] remoteproc6: powering up 4b2b4000.pru0
[21650.090419] remoteproc6: Booting fw image ti-pruss/am57xx-pru0-prueth-fw.elf, size 4350
[21650.098711] ti-pruss 4b280000.pruss: configured system_events = 0x0000060000500000
intr_channels = 0x00000095 host_intr = 0x00000115
[21650.110746] remoteproc6: remote processor 4b2b4000.pru0 is now up
[21650.117709] net eth2: started
[21650.121113] IPv6: ADDRCONF(NETDEV_UP): eth2: link is not ready
[21650.131268] remoteproc7: powering up 4b2b8000.pru1
[21650.136538] remoteproc7: Booting fw image ti-pruss/am57xx-pru1-prueth-fw.elf, size 4382
[21650.144871] ti-pruss 4b280000.pruss: configured system_events = 0x0060000000a00000
intr_channels = 0x0000012a host_intr = 0x0000022a
[21650.156838] remoteproc7: remote processor 4b2b8000.pru1 is now up
[21650.163795] net eth3: started
[21650.167169] IPv6: ADDRCONF(NETDEV_UP): eth3: link is not ready
[21650.188520] IPv6: ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
[21650.248510] device eth2 entered promiscuous mode
[21650.287995] device eth3 entered promiscuous mode
[21650.328127] IPv6: ADDRCONF(NETDEV_CHANGE): eth3: link becomes ready
root@am57xx-evm:~# ping 192.168.2.30
PING 192.168.2.30 (192.168.2.30): 56 data bytes
64 bytes from 192.168.2.30: seq=0 ttl=64 time=0.401 ms
64 bytes from 192.168.2.30: seq=1 ttl=64 time=0.189 ms
64 bytes from 192.168.2.30: seq=2 ttl=64 time=0.186 ms
^C
--- 192.168.2.30 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.186/0.258/0.401 ms
root@am57xx-evm:~#
root@am57xx-evm:~#
root@am57xx-evm:~#
root@am57xx-evm:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 38900
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 109 MBytes 91.5 Mbits/sec
^Croot@am57xx-evm:~# iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 43497
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0-10.0 sec 106 MBytes 88.8 Mbits/sec 0.070 ms 0/76109 (0.0%)
[ 3] 0.0-10.0 sec 1 datagrams received out-of-order
^Croot@am57xx-evm:~#
root@am57xx-evm:~#
root@am57xx-evm:~#
root@am57xx-evm:/# cat /proc/prp0/node-table
Remote nodes in network: 1
Node[0]:
MAC ADDR: 2a:da:8c:50:1b:86
DANP
Time Last Seen: RxA=0 RxB=0
root@am57xx-evm:/# cat /proc/prp0/lre-stats
LRE statistics:
Rx Offloaded: 1
lreTxA: 208128
lreTxB: 208128
lreTxC: 31305063
lreErrWrongLanA: 0
lreErrWrongLanB: 0
lreErrWrongLanC: 0
lreRxA: 0
lreRxB: 0
lreRxC: 208
lreErrorsA: 0
lreErrorsB: 0
lreErrorsC: 0
lreNodes: 1
lreProxyNodes: 0
lreUniqueRxA: 0
lreUniqueRxB: 0
lreUniqueRxC: 0
lreDuplicateRxA: 0
lreDuplicateRxB: 0
lreDuplicateRxC: 0
lreMultiRxA: 0
lreMultiRxB: 0
lreMultiRxC: 0
lreOwnRxA: 0
lreOwnRxB: 0
DAN-P-2
root@am57xx-evm:~# ifconfig eth2
eth2 Link encap:Ethernet HWaddr 2A:DA:8C:50:1B:86
inet6 addr: fe80::28da:8cff:fe50:1b86%3068203800/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:40881 errors:0 dropped:10 overruns:0 frame:64
TX packets:81022 errors:0 dropped:3528075 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2718950 (2.5 MiB) TX bytes:122601929 (116.9 MiB)
root@am57xx-evm:~# /setup.sh prp 2A:DA:8C:50:1B:86 192.168.2.30
Setting up prp0 interface with MAC address 2A:DA:8C:50:1B:86 for slaves and IP address
192.168.2.30
[21684.048303] ti-pruss 4b280000.pruss: unconfigured system_events = 0x0000060000500000
host_intr = 0x00000115
[21684.058095] remoteproc6: stopped remote processor 4b2b4000.pru0
[21684.064152] net eth2: stopped
[21684.118368] ti-pruss 4b280000.pruss: unconfigured system_events = 0x0060000000a00000
host_intr = 0x0000022a
[21684.128160] remoteproc7: stopped remote processor 4b2b8000.pru1
[21684.134217] net eth3: stopped
[21684.158347] remoteproc6: powering up 4b2b4000.pru0
[21684.164069] remoteproc6: Booting fw image ti-pruss/am57xx-pru0-prueth-fw.elf, size 4350
[21684.172524] ti-pruss 4b280000.pruss: configured system_events = 0x0000060000500000
intr_channels = 0x00000095 host_intr = 0x00000115
[21684.184563] remoteproc6: remote processor 4b2b4000.pru0 is now up
[21684.191761] net eth2: started
[21684.195184] IPv6: ADDRCONF(NETDEV_UP): eth2: link is not ready
[21684.205638] remoteproc7: powering up 4b2b8000.pru1
[21684.210960] remoteproc7: Booting fw image ti-pruss/am57xx-pru1-prueth-fw.elf, size 4382
[21684.219252] ti-pruss 4b280000.pruss: configured system_events = 0x0060000000a00000
intr_channels = 0x0000012a host_intr = 0x0000022a
[21684.231220] remoteproc7: remote processor 4b2b8000.pru1 is now up
[21684.238235] net eth3: started
[21684.241684] IPv6: ADDRCONF(NETDEV_UP): eth3: link is not ready
[21684.339123] device eth2 entered promiscuous mode
[21684.377962] device eth3 entered promiscuous mode
[21684.425802] prp0: Slave A (eth2) is not up; please bring it up to get a fully working HSR
network
[21684.436772] IPv6: ADDRCONF(NETDEV_UP): prp0: link is not ready
[21684.443615] IPv6: ADDRCONF(NETDEV_CHANGE): prp0: link becomes ready
root@am57xx-evm:~# [21684.488601] IPv6: ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
[21684.518615] IPv6: ADDRCONF(NETDEV_CHANGE): eth3: link becomes ready
root@am57xx-evm:~# iperf -c 192.168.2.20
------------------------------------------------------------
Client connecting to 192.168.2.20, TCP port 5001
TCP window size: 43.8 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 38900 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 109 MBytes 91.5 Mbits/sec
root@am57xx-evm:~# iperf -c 192.168.2.20 -u -b 88M
------------------------------------------------------------
Client connecting to 192.168.2.20, UDP port 5001
Sending 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 43497 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 107 MBytes 89.5 Mbits/sec
[ 3] Sent 76110 datagrams
[ 3] Server Report:
[ 3] 0.0-10.0 sec 106 MBytes 88.8 Mbits/sec 0.069 ms 0/76109 (0.0%)
[ 3] 0.0-10.0 sec 1 datagrams received out-of-order
Remote nodes in network: 1
Node[0]:
MAC ADDR: 70:ff:76:1c:0f:8d
DANP
Time Last Seen: RxA=0 RxB=0
root@am57xx-evm:/# cat /proc/prp0/lre-stats
LRE statistics:
Rx Offloaded: 1
lreTxA: 208128
lreTxB: 208128
lreTxC: 31305063
lreErrWrongLanA: 0
lreErrWrongLanB: 0
lreErrWrongLanC: 0
lreRxA: 0
lreRxB: 0
lreRxC: 208
lreErrorsA: 0
lreErrorsB: 0
lreErrorsC: 0
lreNodes: 1
lreProxyNodes: 0
lreUniqueRxA: 0
lreUniqueRxB: 0
lreUniqueRxC: 0
lreDuplicateRxA: 0
lreDuplicateRxB: 0
lreDuplicateRxC: 0
lreMultiRxA: 0
lreMultiRxB: 0
lreMultiRxC: 0
lreOwnRxA: 0
lreOwnRxB: 0
4.2.3.14. Performance Test and Logs¶
Boot up two AM571x/572x EVM to configure PRU Ethernet in HSR or PRP mode as described at Testing HSR/PRP Firmware Offload They are connected over eth2 and eth3 as described in HSR Testing or PRP Testing
UDP
Sample iperf UDP test showing no packet loss for MTU sized packets. For HSR/PRP, there are 6 bytes of Tag effectively reducing pay load size to 1466 (1500 - 6 - 20 - 8)
Server Side
root@am57xx-evm:~# iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 34255
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0-60.0 sec 630 MBytes 88.1 Mbits/sec 0.002 ms 0/450887 (0%)
[ 3] 0.0-60.0 sec 1 datagrams received out-of-order
Client side
root@am57xx-evm:~# iperf -c 192.168.2.20 -u -b88M -l1466 -t60
------------------------------------------------------------
Client connecting to 192.168.2.20, UDP port 5001
Sending 1466 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 34255 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 630 MBytes 88.1 Mbits/sec
[ 3] Sent 450888 datagrams
[ 3] Server Report:
[ 3] 0.0-60.0 sec 630 MBytes 88.1 Mbits/sec 0.002 ms 0/450887 (0%)
[ 3] 0.0-60.0 sec 1 datagrams received out-of-order
NOTE: When doing UDP test, user may observe out of order packets sometimes. This is normal as the driver doesn’t use NAPI and packets may get queued to backlog queues of each CPU which may get delivered out of sequence to the iperf application. Out of order delivery of UDP packets are normal and kernel doesn’t guarantee in sequence delivery of UDP packets to application. So iperf may show some packets lost during the test. User may use some of the tools available to migrate the rx irq threads and iperf server to same CPU, example CPU 0, to mitigate out of order issue and get a no loss iperf stats for udp tests.
For example, here is a snapshot of the test that shows packet lost during the test. The test also shows 106 datagram received out of order.
root@am57xx-evm:~# iperf -s -u
------------------------------------------------------------
Server listening on UDP port 5001
Receiving 1470 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 5001 connected with 192.168.2.20 port 41976
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams
[ 3] 0.0-600.0 sec 6.15 GBytes 88.0 Mbits/sec 0.004 ms 5/4501411 (0.00011%)
[ 3] 0.0-600.0 sec 106 datagrams received out-of-order
Run the iperf -s -u & Do ps command and find the PID of the iperf and migrate the process to CPU 0 as follows
root@am57xx-evm:~# ps
PID TTY TIME CMD
964 ttyS2 00:00:00 login
1063 ttyS2 00:00:00 sh
1135 ttyS2 00:00:00 iperf
1141 ttyS2 00:00:00 ps
root@am57xx-evm:~# taskset -cp 0 1135
pid 1135's current affinity list: 0,1
pid 1135's new affinity list: 0
Now find the irq thread for eth2, eth3 devices using
root@am57xx-evm:~# ps -ef | grep "eth3"
root 1464 2 0 06:01 ? 00:00:00 [irq/498-eth3]
root 1495 1065 0 06:04 ttyS2 00:00:00 grep irq/498-eth3
root@am57xx-evm:~# ps -ef | grep "eth2"
root 1462 2 0 06:01 ? 00:00:00 [irq/496-eth2]
root 1497 1065 0 06:04 ttyS2 00:00:00 grep irq/496-eth2
In the above example 1462 is the process id of irq/496-eth2 thread and 1464 is the process ID of irq/498-eth3 . Do following to migrate them to CPU 0.
root@am57xx-evm:~# taskset -cp 0 1464
pid 1464's current affinity list: 0,1
pid 1464's new affinity list: 0
root@am57xx-evm:~# taskset -cp 0 1462
pid 1462's current affinity list: 0,1
pid 1462's new affinity list: 0
root@am57xx-evm:~#
root@am57xx-evm:~#
Now start iperf client on the other side. The server side log below with these tuning shows no packet loss.
[ 4] local 192.168.2.30 port 5001 connected with 192.168.2.20 port 36415
[ 4] 0.0-600.0 sec 6.15 GBytes 88.0 Mbits/sec 0.007 ms 0/4501355 (0%)
[ 4] 0.0-600.0 sec 1 datagrams received out-of-order
Packet Size | Tput with no packet loss (Mbits/sec) | |||
---|---|---|---|---|
AM335x | AM437x | AM57xx | K2G | |
1472 | 30 | 64 | 88 | 30 |
1024 | 29 | 52 | 86 | 26 |
512 | 18 | 36 | 52 | 16 |
256 | 11 | 22 | 25 | 10 |
Table: UDP Performance for HSR
Packet Size | Tput with no packet loss (Mbits/sec) | |||
---|---|---|---|---|
AM335x | AM437x | AM57xx | K2G | |
1472 | 30 | 64 | 88 | 30 |
1024 | 27 | 52 | 88 | 26 |
512 | 19 | 34 | 46 | 15 |
256 | 11 | 22 | 28 | 9 |
Table: UDP Performance for PRP
NOTE-1:Test ran for 1 minute with single direction traffic (Client to Server). Both ports were individually disconnected and then reconnected during the test. Reduced the traffic from 88Mbits/sec until there is no out of order or lost packets in the iperf stats i.e. iperf command client side
iperf3 -c <IP> -u -l1472 -b<Rate>M -t60 -i5
TCP
HSR
Server side
root@am57xx-evm:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 54148
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-60.0 sec 663 MBytes 92.7 Mbits/sec
Client side
root@am57xx-evm:~# iperf -c 192.168.2.20 -t60
------------------------------------------------------------
Client connecting to 192.168.2.20, TCP port 5001
TCP window size: 43.8 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 54148 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 663 MBytes 92.7 Mbits/sec
PRP
Server side
root@am57xx-evm:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 192.168.2.20 port 5001 connected with 192.168.2.30 port 54150
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-60.0 sec 660 MBytes 92.3 Mbits/sec
Client side
root@am57xx-evm:~# iperf -c 192.168.2.20 -t60
------------------------------------------------------------
Client connecting to 192.168.2.20, TCP port 5001
TCP window size: 43.8 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 54150 connected with 192.168.2.20 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 660 MBytes 92.3 Mbits/sec
4.2.3.15. Redundancy Test and Logs¶
For HSR and PRP redundancy is implemented using duplicate links and sending frame over both links and discarding the duplicate at the receive side. The test requires two DAN-P or DAN-H nodes connected over eth2 and eth3 Ethernet Links. Boot up the EVM with bootargs set to configure PRU Ethernet in HSR or PRP mode as described at Processor_SDK_Linux_HSR_PRP#Testing_HSR.2FPRP_Firmware_Offload Do an iperf UDP test at 88Mbits/sec for MTU sized packets (size = 1466) and then pull out either eth2 or eth3 Ethernet cable. Make sure iperf stats doesn’t show packet loss during the test period. Here is the log for HSR that show link failed during the test and there was no packet loss.
eth3 link failed
root@am57xx-evm:~# iperf -c 192.168.2.20 -u -b88M -l1466 -t60
------------------------------------------------------------
Client connecting to 192.168.2.20, UDP port 5001
Sending 1466 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 50443 connected with 192.168.2.20 port 5001
[ 108.740402] prueth pruss2_eth eth3: Link is Down
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 631 MBytes 88.2 Mbits/sec
[ 3] Sent 451002 datagrams
[ 3] Server Report:
[ 3] 0.0-60.0 sec 631 MBytes 88.2 Mbits/sec 0.003 ms 0/451001 (0%)
[ 3] 0.0-60.0 sec 1 datagrams received out-of-order
root@am57xx-evm:~# [ 181.444988] prueth pruss2_eth eth3: Link is Up - 100Mbps/Full - flow control off
eth2 link failed
root@am57xx-evm:~# iperf -c 192.168.2.20 -u -b88M -l1466 -t60
------------------------------------------------------------
Client connecting to 192.168.2.20, UDP port 5001
Sending 1466 byte datagrams
UDP buffer size: 160 KByte (default)
------------------------------------------------------------
[ 3] local 192.168.2.30 port 49260 connected with 192.168.2.20 port 5001
[ 204.253286] prueth pruss2_eth eth2: Link is Down
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 631 MBytes 88.2 Mbits/sec
[ 3] Sent 451028 datagrams
[ 3] Server Report:
[ 3] 0.0-60.0 sec 631 MBytes 88.2 Mbits/sec 0.005 ms 0/451027 (0%)
[ 3] 0.0-60.0 sec 1 datagrams received out-of-order
root@am57xx-evm:~# uname -a
Linux am57xx-evm 4.9.41-rt23-gc038d21a22 #2 SMP PREEMPT RT Wed Sep 27 06:34:09 EDT 2017 armv7l GNU/Linux
4.2.3.16. Useful Commands¶
Linux HSR/PRP driver help commands
To dump lre_info such as sv_vid, sv_pcp, sv_dei, protocol etc used at the LRE of Linux HSR/PRP driver
- cat /sys/kernel/debug/<hsr/prp-if_name>/lre_info example cat /sys/kernel/debug/hsr0/lre_info
To dump Node_Table
- cat /proc/<hsr/prp-if_name>/node-table
To set hsr-mode - echo 1 > /proc/<hsr/prp-if_name>/hsr-mode
where 1 is for Mode-H Other values are 2 (Mode-N), 3 (Mode-T), 4 (Mode-U), 5 (Mode-M)
To clear node table - echo 1 > /proc/<hsr/prp-if_name>/clear-nt
To change duplicate detection mode - echo 1 > /proc/<hsr/prp-if_name>/dd-mode
To change duplicate list max resident time - echo 1000 > /proc/<hsr/prp-if_name>/dlrmt
To change prp transparent reception mode - echo 1 > /proc/<hsr/prp-if_name>/prp-tr
To disable SV frame transmission - echo 1 > /proc/<hsr/prp-if_name>/disable-sv_frame
PRU Ethernet driver help commands
To see queue stats
- cat /sys/kernel/debug/prueth-eth<if_number>/stats
To see lre_config
- cat /sys/kernel/debug/prueth-<hsr/prp>-<ID>>/lre_config
To dump node table
- cat /sys/kernel/debug/prueth-<hsr/prp>-<ID>>/node_table
Also
- cat /sys/kernel/debug/prueth-<hsr/prp-<ID>/new_nt_bins
In the above commands ID and if_nubers are chosen as described in section PRU-ICSS Subsystem Driver
4.2.3.17. FAQ¶
- How to disable udhcpc from sending DHCP request over prueth Ethernet interfaces (eth2-eth3) when it is configured to run HSR/PRP protocol in firmware?
Linux HSR/PRP driver uses the eth2/eth3 interface as slave interfaces to implement the protocol on top of it. Application is expected to send or receive packets over the hsr or prp lre interface also known as C port. However prueth also support plain Ethernet and the file system /etc/systemd/network/10-eth.network has a general rule to enable DHCP over all of the interface matching eth*. Modify the file to match unique name instead of generic name wild cards. For example to do DHCP over only eth0 interface, 10-eth.network may be modified as follows:-
root@am57xx-evm:~# cat /etc/systemd/network/10-eth.network
[Match]
Name=eth0
KernelCommandLine=!root=/dev/nfs
[Network]
DHCP=yes
To do DHCP over hsr0 or prp0 interfaces, user may add additional files to /etc/systemd/network/ one for each prp0 or hsr0 similar to eth0, by using a Match name string of hsr0 or prp0. More details on this is at [[6]]
- Why do I see duplicate frames displayed by ping when I use PRP interface?
In ICSS firmware, PRU-0 is assumed to be for Link-A and PRU-1 for Link-B of a LRE in the case DANP. So in PRP case, Link-A should be connected network A and Link-B should be connected to Network B of a PRP network since net-id has to match as per duplicate detect alogrithm. If this convention is not followed, duplicate detection logic fails and duplicates are sent to upper layer causing ping application to complain about duplicates. So when creating prp interface, make sure ip link command parameter slave 1 use linux interface associated with PRU-0 and slave 2 use interface associated with PRU-1. Also when making network connection make sure that PRU-0 port is connected to Network A and PRU-1 port to Network B.