nat: cleanup of deprecated features
[vpp.git] / src / plugins / af_xdp / device.c
index d27901b..cccbf69 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ethtool.h>
 #include <linux/if_link.h>
 #include <linux/sockios.h>
+#include <linux/limits.h>
 #include <bpf/libbpf.h>
 #include <vlib/vlib.h>
 #include <vlib/unix/unix.h>
 #include <vnet/interface/tx_queue_funcs.h>
 #include "af_xdp.h"
 
+#ifndef XDP_UMEM_MIN_CHUNK_SIZE
+#define XDP_UMEM_MIN_CHUNK_SIZE 2048
+#endif
+
 af_xdp_main_t af_xdp_main;
 
 typedef struct
@@ -67,6 +72,16 @@ af_xdp_mac_change (vnet_hw_interface_t * hw, const u8 * old, const u8 * new)
   return 0;
 }
 
+static clib_error_t *
+af_xdp_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hw,
+                          u32 frame_size)
+{
+  af_xdp_main_t *am = &af_xdp_main;
+  af_xdp_device_t *ad = vec_elt_at_index (am->devices, hw->dev_instance);
+  af_xdp_log (VLIB_LOG_LEVEL_ERR, ad, "set mtu not supported yet");
+  return vnet_error (VNET_ERR_UNSUPPORTED, 0);
+}
+
 static u32
 af_xdp_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
 {
@@ -82,9 +97,6 @@ af_xdp_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
       af_xdp_log (VLIB_LOG_LEVEL_ERR, ad,
                  "set promiscuous not supported yet");
       return ~0;
-    case ETHERNET_INTERFACE_FLAG_MTU:
-      af_xdp_log (VLIB_LOG_LEVEL_ERR, ad, "set mtu not supported yet");
-      return ~0;
     }
 
   af_xdp_log (VLIB_LOG_LEVEL_ERR, ad, "unknown flag %x requested", flags);
@@ -186,6 +198,12 @@ static int
 af_xdp_load_program (af_xdp_create_if_args_t * args, af_xdp_device_t * ad)
 {
   int fd;
+  struct rlimit r = { RLIM_INFINITY, RLIM_INFINITY };
+
+  if (setrlimit (RLIMIT_MEMLOCK, &r))
+    af_xdp_log (VLIB_LOG_LEVEL_WARNING, ad,
+               "setrlimit(%s) failed: %s (errno %d)", ad->linux_ifname,
+               strerror (errno), errno);
 
   ad->linux_ifindex = if_nametoindex (ad->linux_ifname);
   if (!ad->linux_ifindex)
@@ -205,10 +223,7 @@ af_xdp_load_program (af_xdp_create_if_args_t * args, af_xdp_device_t * ad)
       goto err0;
     }
 
-#ifndef XDP_FLAGS_REPLACE
-#define XDP_FLAGS_REPLACE 0
-#endif
-  if (bpf_set_link_xdp_fd (ad->linux_ifindex, fd, XDP_FLAGS_REPLACE))
+  if (bpf_set_link_xdp_fd (ad->linux_ifindex, fd, 0))
     {
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_6;
       args->error =
@@ -268,8 +283,18 @@ af_xdp_create_queue (vlib_main_t *vm, af_xdp_create_if_args_t *args,
       (umem, uword_to_pointer (vm->buffer_main->buffer_mem_start, void *),
        vm->buffer_main->buffer_mem_size, fq, cq, &umem_config))
     {
+      uword sys_page_size = clib_mem_get_page_size ();
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_1;
       args->error = clib_error_return_unix (0, "xsk_umem__create() failed");
+      /* this should mimic the Linux kernel net/xdp/xdp_umem.c:xdp_umem_reg()
+       * check */
+      if (umem_config.frame_size < XDP_UMEM_MIN_CHUNK_SIZE ||
+         umem_config.frame_size > sys_page_size)
+       args->error = clib_error_return (
+         args->error,
+         "(unsupported data-size? (should be between %d and %d))",
+         XDP_UMEM_MIN_CHUNK_SIZE - sizeof (vlib_buffer_t),
+         sys_page_size - sizeof (vlib_buffer_t));
       goto err0;
     }
 
@@ -301,6 +326,9 @@ af_xdp_create_queue (vlib_main_t *vm, af_xdp_create_if_args_t *args,
 
   fd = xsk_socket__fd (*xsk);
   optlen = sizeof (opt);
+#ifndef SOL_XDP
+#define SOL_XDP 283
+#endif
   if (getsockopt (fd, SOL_XDP, XDP_OPTIONS, &opt, &optlen))
     {
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
@@ -505,10 +533,10 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vlib_thread_main_t *tm = vlib_get_thread_main ();
+  vnet_eth_interface_registration_t eir = {};
   af_xdp_main_t *am = &af_xdp_main;
   af_xdp_device_t *ad;
   vnet_sw_interface_t *sw;
-  vnet_hw_interface_t *hw;
   int rxq_num, txq_num, q_num;
   int ns_fds[2];
   int i, ret;
@@ -647,20 +675,17 @@ af_xdp_create_if (vlib_main_t * vm, af_xdp_create_if_args_t * args)
   ethernet_mac_address_generate (ad->hwaddr);
 
   /* create interface */
-  if (ethernet_register_interface (vnm, af_xdp_device_class.index,
-                                  ad->dev_instance, ad->hwaddr,
-                                  &ad->hw_if_index, af_xdp_flag_change))
-    {
-      args->rv = VNET_API_ERROR_INVALID_INTERFACE;
-      args->error =
-       clib_error_return (0, "ethernet_register_interface() failed");
-      goto err2;
-    }
+  eir.dev_class_index = af_xdp_device_class.index;
+  eir.dev_instance = ad->dev_instance;
+  eir.address = ad->hwaddr;
+  eir.cb.flag_change = af_xdp_flag_change;
+  eir.cb.set_max_frame_size = af_xdp_set_max_frame_size;
+  ad->hw_if_index = vnet_eth_register_interface (vnm, &eir);
 
   sw = vnet_get_hw_sw_interface (vnm, ad->hw_if_index);
-  hw = vnet_get_hw_interface (vnm, ad->hw_if_index);
   args->sw_if_index = ad->sw_if_index = sw->sw_if_index;
-  hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE;
+
+  vnet_hw_if_set_caps (vnm, ad->hw_if_index, VNET_HW_IF_CAP_INT_MODE);
 
   vnet_hw_if_set_input_node (vnm, ad->hw_if_index, af_xdp_input_node.index);