devices: add support for l3 af_packet interface 27/34027/5
authorMohsin Kazmi <sykazmi@cisco.com>
Fri, 8 Oct 2021 15:10:49 +0000 (15:10 +0000)
committerBeno�t Ganne <bganne@cisco.com>
Fri, 22 Oct 2021 12:37:36 +0000 (12:37 +0000)
Type: improvement

Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
Change-Id: Ia6b9d4ac55be2216887bfdb99be4021f6a96f166

src/vnet/devices/af_packet/af_packet.c
src/vnet/devices/af_packet/af_packet.h
src/vnet/devices/af_packet/cli.c
src/vnet/devices/af_packet/device.c
src/vnet/devices/af_packet/node.c

index 2dc2630..69e3c87 100644 (file)
 
 af_packet_main_t af_packet_main;
 
+VNET_HW_INTERFACE_CLASS (af_packet_ip_device_hw_interface_class, static) = {
+  .name = "af-packet-ip-device",
+  .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
+};
+
 #define AF_PACKET_DEFAULT_TX_FRAMES_PER_BLOCK 1024
 #define AF_PACKET_DEFAULT_TX_FRAME_SIZE              (2048 * 5)
 #define AF_PACKET_TX_BLOCK_NR          1
@@ -367,6 +372,7 @@ af_packet_create_if (af_packet_create_if_arg_t *arg)
   apif->per_interface_next_index = ~0;
   apif->next_tx_frame = 0;
   apif->next_rx_frame = 0;
+  apif->mode = arg->mode;
 
   ret = af_packet_read_mtu (apif);
   if (ret != 0)
@@ -375,36 +381,44 @@ af_packet_create_if (af_packet_create_if_arg_t *arg)
   if (tm->n_vlib_mains > 1)
     clib_spinlock_init (&apif->lockp);
 
-  /*use configured or generate random MAC address */
-  if (arg->hw_addr)
-    clib_memcpy (hw_addr, arg->hw_addr, 6);
-  else
+  if (apif->mode == AF_PACKET_IF_MODE_ETHERNET)
     {
-      f64 now = vlib_time_now (vm);
-      u32 rnd;
-      rnd = (u32) (now * 1e6);
-      rnd = random_u32 (&rnd);
-
-      clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd));
-      hw_addr[0] = 2;
-      hw_addr[1] = 0xfe;
-    }
+      /*use configured or generate random MAC address */
+      if (arg->hw_addr)
+       clib_memcpy (hw_addr, arg->hw_addr, 6);
+      else
+       {
+         f64 now = vlib_time_now (vm);
+         u32 rnd;
+         rnd = (u32) (now * 1e6);
+         rnd = random_u32 (&rnd);
+
+         clib_memcpy (hw_addr + 2, &rnd, sizeof (rnd));
+         hw_addr[0] = 2;
+         hw_addr[1] = 0xfe;
+       }
 
-  error = ethernet_register_interface (vnm, af_packet_device_class.index,
-                                      if_index, hw_addr, &apif->hw_if_index,
-                                      af_packet_eth_flag_change);
+      error = ethernet_register_interface (
+       vnm, af_packet_device_class.index, if_index, hw_addr,
+       &apif->hw_if_index, af_packet_eth_flag_change);
 
-  if (error)
+      if (error)
+       {
+         clib_memset (apif, 0, sizeof (*apif));
+         pool_put (apm->interfaces, apif);
+         vlib_log_err (apm->log_class, "Unable to register interface: %U",
+                       format_clib_error, error);
+         clib_error_free (error);
+         ret = VNET_API_ERROR_SYSCALL_ERROR_1;
+         goto error;
+       }
+    }
+  else
     {
-      clib_memset (apif, 0, sizeof (*apif));
-      pool_put (apm->interfaces, apif);
-      vlib_log_err (apm->log_class, "Unable to register interface: %U",
-                   format_clib_error, error);
-      clib_error_free (error);
-      ret = VNET_API_ERROR_SYSCALL_ERROR_1;
-      goto error;
+      apif->hw_if_index = vnet_register_interface (
+       vnm, af_packet_device_class.index, if_index,
+       af_packet_ip_device_hw_interface_class.index, if_index);
     }
-
   sw = vnet_get_hw_sw_interface (vnm, apif->hw_if_index);
   hw = vnet_get_hw_interface (vnm, apif->hw_if_index);
   apif->sw_if_index = sw->sw_if_index;
@@ -504,7 +518,10 @@ af_packet_delete_if (u8 *host_if_name)
 
   mhash_unset (&apm->if_index_by_host_if_name, host_if_name, &if_index);
 
-  ethernet_delete_interface (vnm, apif->hw_if_index);
+  if (apif->mode == AF_PACKET_IF_MODE_ETHERNET)
+    ethernet_delete_interface (vnm, apif->hw_if_index);
+  else
+    vnet_delete_hw_interface (vnm, apif->hw_if_index);
 
   pool_put (apm->interfaces, apif);
 
index 3163aa0..652e173 100644 (file)
  */
 
 #include <vppinfra/lock.h>
-
 #include <vlib/log.h>
 
+typedef enum
+{
+  AF_PACKET_IF_MODE_ETHERNET = 1,
+  AF_PACKET_IF_MODE_IP = 2
+} af_packet_if_mode_t;
+
 typedef struct
 {
   u32 sw_if_index;
@@ -49,6 +54,7 @@ typedef struct
   u8 is_admin_up;
   u32 queue_index;
   u32 host_mtu;
+  af_packet_if_mode_t mode;
 } af_packet_if_t;
 
 typedef struct
@@ -77,6 +83,7 @@ typedef struct
   u32 tx_frame_size;
   u32 rx_frames_per_block;
   u32 tx_frames_per_block;
+  af_packet_if_mode_t mode;
 
   /* return */
   u32 sw_if_index;
index bae4f61..3dd3c8e 100644 (file)
@@ -51,6 +51,9 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
   clib_memset (arg, 0, sizeof (*arg));
 
+  // Default mode
+  arg->mode = AF_PACKET_IF_MODE_ETHERNET;
+
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -69,6 +72,8 @@ af_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
       else if (unformat (line_input, "tx-per-block %u",
                         &arg->tx_frames_per_block))
        ;
+      else if (unformat (line_input, "mode ip"))
+       arg->mode = AF_PACKET_IF_MODE_IP;
       else if (unformat (line_input, "hw-addr %U", unformat_ethernet_address,
                         hwaddr))
        arg->hw_addr = hwaddr;
@@ -140,7 +145,8 @@ done:
 ?*/
 VLIB_CLI_COMMAND (af_packet_create_command, static) = {
   .path = "create host-interface",
-  .short_help = "create host-interface name <ifname> [hw-addr <mac-addr>]",
+  .short_help =
+    "create host-interface name <ifname> [hw-addr <mac-addr>] [mode ip]",
   .function = af_packet_create_command_fn,
 };
 
index 0542b16..8e4bc2b 100644 (file)
@@ -339,6 +339,14 @@ static clib_error_t *af_packet_set_mac_address_function
   int rv, fd = socket (AF_UNIX, SOCK_DGRAM, 0);
   struct ifreq ifr;
 
+  if (apif->mode == AF_PACKET_IF_MODE_IP)
+    {
+      vlib_log_warn (apm->log_class, "af_packet_%s interface is in IP mode",
+                    apif->host_if_name);
+      return clib_error_return (0,
+                               " MAC update failed, interface is in IP mode");
+    }
+
   if (0 > fd)
     {
       vlib_log_warn (apm->log_class, "af_packet_%s could not open socket",
index e2f87b1..0fdae5c 100644 (file)
@@ -194,7 +194,7 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
 {
   af_packet_main_t *apm = &af_packet_main;
   struct tpacket2_hdr *tph;
-  u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
+  u32 next_index;
   u32 block = 0;
   u32 rx_frame;
   u32 n_free_bufs;
@@ -209,6 +209,21 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 thread_index = vm->thread_index;
   u32 n_buffer_bytes = vlib_buffer_get_default_data_size (vm);
   u32 min_bufs = apif->rx_req->tp_frame_size / n_buffer_bytes;
+  vlib_buffer_t bt;
+
+  if (apif->mode == AF_PACKET_IF_MODE_IP)
+    {
+      next_index = VNET_DEVICE_INPUT_NEXT_IP4_INPUT;
+    }
+  else
+    {
+      next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
+      if (PREDICT_FALSE (apif->per_interface_next_index != ~0))
+       next_index = apif->per_interface_next_index;
+
+      /* redirect if feature path enabled */
+      vnet_feature_start_device_input_x1 (apif->sw_if_index, &next_index, &bt);
+    }
 
   n_free_bufs = vec_len (apm->rx_buffers[thread_index]);
   if (PREDICT_FALSE (n_free_bufs < VLIB_FRAME_SIZE))
@@ -317,14 +332,30 @@ af_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
            }
          else
            {
-             next0 = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
-
-             if (PREDICT_FALSE (apif->per_interface_next_index != ~0))
-               next0 = apif->per_interface_next_index;
-
-             /* redirect if feature path enabled */
-             vnet_feature_start_device_input_x1 (apif->sw_if_index, &next0,
-                                                 first_b0);
+             if (PREDICT_FALSE (apif->mode == AF_PACKET_IF_MODE_IP))
+               {
+                 switch (first_b0->data[0] & 0xf0)
+                   {
+                   case 0x40:
+                     next0 = VNET_DEVICE_INPUT_NEXT_IP4_INPUT;
+                     break;
+                   case 0x60:
+                     next0 = VNET_DEVICE_INPUT_NEXT_IP6_INPUT;
+                     break;
+                   default:
+                     next0 = VNET_DEVICE_INPUT_NEXT_DROP;
+                     break;
+                   }
+                 if (PREDICT_FALSE (apif->per_interface_next_index != ~0))
+                   next0 = apif->per_interface_next_index;
+               }
+             else
+               {
+                 /* copy feature arc data from template */
+                 first_b0->current_config_index = bt.current_config_index;
+                 vnet_buffer (first_b0)->feature_arc_index =
+                   vnet_buffer (&bt)->feature_arc_index;
+               }
            }
 
          /* trace */