VLAN support on host(af-packet) interface. 35/8435/6
authorAkshaya N <akshaya@rtbrick.com>
Fri, 15 Sep 2017 12:07:53 +0000 (17:37 +0530)
committerDamjan Marion <dmarion.lists@gmail.com>
Wed, 27 Sep 2017 18:22:37 +0000 (18:22 +0000)
On host interface if a VLAN tagged packet is received, linux kernel removes
the VLAN header from packet byte stream and adds metadata in tpacket2_hdr.
This patch explicitely checks for the presense of VLAN metadata and adds it
in VPP packet.

Change-Id: I0ba35c1e98dbc008ce18d032f22f2717d610c1aa
Signed-off-by: Akshaya N <akshaya@rtbrick.com>
src/vnet/devices/af_packet/node.c

index d3af41b..99c91f3 100644 (file)
@@ -173,12 +173,35 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
              /* copy data */
              u32 bytes_to_copy =
                data_len > n_buffer_bytes ? n_buffer_bytes : data_len;
+             u32 vlan_len = 0;
+             u32 bytes_copied = 0;
              b0->current_data = 0;
-             clib_memcpy (vlib_buffer_get_current (b0),
-                          (u8 *) tph + tph->tp_mac + offset, bytes_to_copy);
+             /* Kernel removes VLAN headers, so reconstruct VLAN */
+             if (PREDICT_FALSE (tph->tp_status & TP_STATUS_VLAN_VALID))
+               {
+                 if (PREDICT_TRUE (offset == 0))
+                   {
+                     clib_memcpy (vlib_buffer_get_current (b0),
+                                  (u8 *) tph + tph->tp_mac,
+                                  sizeof (ethernet_header_t));
+                     ethernet_header_t *eth = vlib_buffer_get_current (b0);
+                     ethernet_vlan_header_t *vlan =
+                       (ethernet_vlan_header_t *) (eth + 1);
+                     vlan->priority_cfi_and_id =
+                       clib_host_to_net_u16 (tph->tp_vlan_tci);
+                     vlan->type = eth->type;
+                     eth->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
+                     vlan_len = sizeof (ethernet_vlan_header_t);
+                     bytes_copied = sizeof (ethernet_header_t);
+                   }
+               }
+             clib_memcpy (((u8 *) vlib_buffer_get_current (b0)) +
+                          bytes_copied + vlan_len,
+                          (u8 *) tph + tph->tp_mac + offset + bytes_copied,
+                          (bytes_to_copy - bytes_copied));
 
              /* fill buffer header */
-             b0->current_length = bytes_to_copy;
+             b0->current_length = bytes_to_copy + vlan_len;
 
              if (offset == 0)
                {