l2: fix DVR test failure on AWS Graviton on Ubuntu 22.04 29/41429/8
authorAndrew Yourtchenko <[email protected]>
Tue, 17 Sep 2024 13:01:44 +0000 (15:01 +0200)
committerDamjan Marion <[email protected]>
Thu, 19 Sep 2024 14:31:36 +0000 (14:31 +0000)
The AWS Graviton make test fails in dvr_test.py on Ubuntu 22.04,
due to a mismatching source MAC address. Debian 11 tests run fine.

The following can be seen in the log.txt trace:

00:00:00:756422: ethernet-input
  frame: flags 0x1, hw-if-index 3, sw-if-index 3
  IP4: 02:03:00:00:ff:02 -> de:ad:00:00:00:00 802.1q vlan 92
00:00:00:756435: l2-input
  l2-input: sw_if_index 6 dst de:ad:00:00:00:00 src 02:03:00:00:ff:02 [l2-input-vtr l2-learn l2-fwd l2-flood l2-flood ]
00:00:00:756438: l2-input-vtr
  l2-input-vtr: sw_if_index 6 dst de:ad:00:00:00:00 src 02:03:00:00:00:00 data 08 00 45 00 00 80 00 01 00 00 40 11
00:00:00:756441: l2-learn
  l2-learn: sw_if_index 6 dst de:ad:00:00:00:00 src 02:03:00:00:00:00 bd_index 1

Note how l2-input-vtr node has the two lowest bytes of the source MAC corrupted.

Discussing with Benoit, since this could be caused by unaligned memory accesses,
using clib_memcpy_fast.

Type: fix
Change-Id: I28991e1166335df0edd1e4b84fa72a2b1d0bb9bf
Signed-off-by: Andrew Yourtchenko <[email protected]>
src/vnet/l2/l2_vtr.h

index 1cd9209..4028587 100644 (file)
@@ -75,15 +75,13 @@ typedef struct
 always_inline u32
 l2_vtr_process (vlib_buffer_t * b0, vtr_config_t * config)
 {
-  u64 temp_8;
-  u32 temp_4;
   u8 *eth;
+  u8 save_macs[12];
 
   eth = vlib_buffer_get_current (b0);
 
   /* copy the 12B dmac and smac to a temporary location */
-  temp_8 = *((u64 *) eth);
-  temp_4 = *((u32 *) (eth + 8));
+  clib_memcpy_fast (save_macs, eth, sizeof (save_macs));
 
   /* adjust for popped tags */
   eth += config->pop_bytes;
@@ -95,7 +93,8 @@ l2_vtr_process (vlib_buffer_t * b0, vtr_config_t * config)
     }
 
   /* copy the 2 new tags to the start of the packet  */
-  *((u64 *) (eth + 12 - 8)) = config->raw_tags;
+  clib_memcpy_fast (eth + 12 - 8, &config->raw_tags,
+                   sizeof (config->raw_tags));
 
   /* TODO: set cos bits */
 
@@ -103,8 +102,7 @@ l2_vtr_process (vlib_buffer_t * b0, vtr_config_t * config)
   eth -= config->push_bytes;
 
   /* copy the 12 dmac and smac back to the packet */
-  *((u64 *) eth) = temp_8;
-  *((u32 *) (eth + 8)) = temp_4;
+  clib_memcpy_fast (eth, save_macs, sizeof (save_macs));
 
   /* Update l2 parameters */
   vnet_buffer (b0)->l2.l2_len +=
@@ -124,7 +122,6 @@ l2_vtr_process (vlib_buffer_t * b0, vtr_config_t * config)
   return 0;
 }
 
-
 /*
  *  Perform the egress pre-vlan tag rewrite EFP Filter check.
  * The post-vlan tag rewrite check is a separate graph node.