TSN Switch

Browse source code on GitHub

Overview

Example on testing/debugging TSN switch.

In Zephyr, switch device is supported with DSA (Distributed Switch Architecture) driver. And Ethernet bridge over DSA user ports will be used as a way for switch configuration, like FDB, VLAN … (Unfortunately these haven’t been supported.)

For TSN protocols, gPTP stack now can be enabled on DSA user ports to make the switch as time-aware relay. Qbv can be managed by management APIs. More TSN protocols will be supported and can be enabled in this sample.

The source code for this sample application can be found at: samples/net/ethernet/tsn-switch.

Requirements

To verify TSN switch, at least two Linux hosts supporting TSN (at least gPTP) are needed to connect to the switch.

Building and Running

  1. Build and run the sample.

west build -b <board to use> samples/net/ethernet/tsn-switch
  1. Connect Linux hosts to TSN switch. Take NXP i.MX943 EVK as example.

                      i.MX943 EVK
                  +-----------------+
                  |     bridge0     | gPTP bridge as Master
                  |  IP: 192.0.2.1  |    priority1 246
                  |                 |
                  | swp0(Qbv)  swp1 |
                  +--+----------+---+
                     |          |
             +-------+          +-------+
             |                          |
+------------+-----------+  +-----------+------------+
|          eth0          |  |          eth0          |
| IP:  192.0.2.2         |  | IP:  192.0.2.3         |
| MAC: fa:fa:62:fe:a2:11 |  | MAC: a6:10:52:1d:cb:6d |
+------------------------+  +------------------------+
      Linux Host A                Linux Host B
 gPTP Slave priority1 248    gPTP slave priority1 248

The Qbv is configured for demo on first DSA user port swp0.

time cycle 10ms   gate7 6 5 4 3 2 1 0
-----------------------------------------
slot 1 - 2ms:         1 1 1 1 0 1 0 1
slot 2 - 8ms:         1 1 1 1 1 0 0 1

With IP addresses configured on Linux hosts. The basic communication among three devices can be verified with ping.

  1. Run gPTP (ptp4l with gPTP.cfg) on Linux hosts to synchronize time base to switch.

# ptp4l -i eth0 -m -f gPTP-slave.cfg > /tmp/ptp.log &
# tail -f /tmp/ptp.log
ptp4l[186.753]: rms   25 max   51 freq  -8579 +/-  32 delay  1311 +/-   0
ptp4l[187.752]: rms   19 max   39 freq  -8575 +/-  26 delay  1311 +/-   0
ptp4l[188.752]: rms   30 max   59 freq  -8592 +/-  41 delay  1311 +/-   0
ptp4l[189.752]: rms   17 max   28 freq  -8570 +/-  22 delay  1311 +/-   0
ptp4l[190.752]: rms   23 max   37 freq  -8600 +/-  25 delay  1314 +/-   0
ptp4l[191.752]: rms   24 max   42 freq  -8600 +/-  32 delay  1310 +/-   0
ptp4l[192.752]: rms   30 max   54 freq  -8574 +/-  38 delay  1310 +/-   0
ptp4l[193.753]: rms   25 max   35 freq  -8587 +/-  35 delay  1314 +/-   0
ptp4l[194.752]: rms   27 max   48 freq  -8598 +/-  35 delay  1314 +/-   0
ptp4l[195.752]: rms   26 max   42 freq  -8602 +/-  35 delay  1314 +/-   0
ptp4l[196.752]: rms   25 max   42 freq  -8588 +/-  34 delay  1318 +/-   0
  1. Send packets from Linux host B to A with pktgen to verify Qbv function.

On Linux host B, send VLAN 100 PCP 0 packets every second.

# modprobe pktgen
# cd /proc/net/pktgen
# echo "add_device eth0"           > kpktgend_0
# echo "count 0"                   > eth0
# echo "clone_skb 0"               > eth0
# echo "pkt_size 64"               > eth0
# echo "dst_mac fa:fa:62:fe:a2:11" > eth0
# echo "vlan_id 100"               > eth0
# echo "vlan_p 0"                  > eth0
# echo "delay 1000000000"          > eth0
# echo "start" > pgctrl

On Linux host A, capture packets. Because gate 0 always on, packets can be received.

# tcpdump -i eth0 -e vlan
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:56:12.259668 a6:10:52:1d:cb:6d (oui Unknown) > fa:fa:62:fe:a2:11 (oui Unknown), ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype IPv4, 169.254.153.102.9 > 0.0.0.0.9: UDP, length 18
13:56:13.259696 a6:10:52:1d:cb:6d (oui Unknown) > fa:fa:62:fe:a2:11 (oui Unknown), ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype IPv4, 169.254.153.102.9 > 0.0.0.0.9: UDP, length 18
13:56:14.259714 a6:10:52:1d:cb:6d (oui Unknown) > fa:fa:62:fe:a2:11 (oui Unknown), ethertype 802.1Q (0x8100), length 64: vlan 100, p 0, ethertype IPv4, 169.254.153.102.9 > 0.0.0.0.9: UDP, length 18

On Linux host B, change to send VLAN 100 PCP 1 packets every second.

# echo "vlan_p 1" > eth0
# echo "start" > pgctrl

On Linux host A, capture packets. Because gate 1 always off, no packets can be received.

# tcpdump -i eth0 -e vlan
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
  1. Send packets from Linux host B to A with pktgen to verify Qbv performance.

On Linux host B, send VLAN 100 PCP 2 packets every 100us.

# modprobe pktgen
# cd /proc/net/pktgen
# echo "add_device eth0"           > kpktgend_0
# echo "count 0"                   > eth0
# echo "clone_skb 0"               > eth0
# echo "pkt_size 64"               > eth0
# echo "dst_mac fa:fa:62:fe:a2:11" > eth0
# echo "vlan_id 100"               > eth0
# echo "vlan_p 2"                  > eth0
# echo "delay 100000"              > eth0
# echo "start" > pgctrl

On Linux host A, capture 100000 packets and check if they fell in 2ms window. Because gate 2 has 2ms slot, packets can be received only in 2ms window. The results showed 99.98% were in 2ms window considering some critical condition.

# tcpdump -i eth0 -j adapter_unsynced --time-stamp-precision nano -tt -e vlan -c 100000 -w pcp2.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
100000 packets captured
101793 packets received by filter
0 packets dropped by kernel
#
#
# tcpdump -r pcp2.pcap --time-stamp-precision nano -tt -n 2>/dev/null | \
awk '
BEGIN{
  period=10000000; win=2000000; off=0;
  win_in=0; win_out=0; total=0;
}
$1 ~ /^[0-9]+\.[0-9]+$/ {
  split($1,a,"."); t=a[1]*1000000000 + (a[2]+0);
  phase = ((t - off) % period + period) % period;
  if (phase < win) win_in++; else win_out++;
  total++;
}
END{
  pct = (total ? (win_in*100.0/total) : 0);
  printf("period=10ms win=2ms off=%dns\n", off);
  printf("total=%d win_in=%d win_out=%d in_win=%.2f%%\n",
         total, win_in, win_out, pct);
}'
period=10ms win=2ms off=0ns
total=100000 win_in=99977 win_out=23 in_win=99.98%

On Linux host B, change to send VLAN 100 PCP 3 packets every 100us.

# echo "vlan_p 3" > eth0
# echo "start" > pgctrl

On Linux host A, capture 100000 packets and check if they fell in 8ms window. Because gate 3 has 8ms slot, packets can be received only in 8ms window. The results showed 99.98% were in 8ms window considering some critical condition.

# tcpdump -i eth0 -j adapter_unsynced --time-stamp-precision nano -tt -e vlan -c 100000 -w pcp2.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
100000 packets captured
101793 packets received by filter
0 packets dropped by kernel
#
#
# tcpdump -r pcp3.pcap --time-stamp-precision nano -tt -n 2>/dev/null | \
awk '
BEGIN{
  period=10000000; win=8000000; off=2000000;
  win_in=0; win_out=0; total=0;
}
$1 ~ /^[0-9]+\.[0-9]+$/ {
  split($1,a,"."); t=a[1]*1000000000 + (a[2]+0);
  phase = ((t - off) % period + period) % period;
  if (phase < win) win_in++; else win_out++;
  total++;
}
END{
  pct = (total ? (win_in*100.0/total) : 0);
  printf("period=10ms win=8ms off=%dns\n", off);
  printf("total=%d win_in=%d win_out=%d in_win=%.2f%%\n",
         total, win_in, win_out, pct);
}'
period=10ms win=8ms off=2000000ns
total=100000 win_in=99976 win_out=24 in_win=99.98%

See also

Ethernet Bridging API
PTP Clock
Ethernet Library