plugins: unload plugin if early init fails 55/11555/8
authorDamjan Marion <damarion@cisco.com>
Thu, 5 Apr 2018 19:32:29 +0000 (21:32 +0200)
committerDave Barach <openvpp@barachs.net>
Mon, 9 Apr 2018 16:06:20 +0000 (16:06 +0000)
Change-Id: I32f68e2ee8f5d32962acdefb0193583f71d342b3
Signed-off-by: Damjan Marion <damarion@cisco.com>
12 files changed:
Makefile
src/plugins/dpdk/main.c
src/vlib/buffer.h
src/vlib/cli.h
src/vlib/init.h
src/vlib/mc.h
src/vlib/node.h
src/vlib/pci/pci.h
src/vlib/threads.h
src/vlib/unix/plugin.c
src/vnet/feature/feature.h
src/vnet/interface.h

index c893e02..06e15f0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,7 @@ GDB?=gdb
 PLATFORM?=vpp
 SAMPLE_PLUGIN?=no
 MACHINE=$(shell uname -m)
+SUDO?=sudo
 
 ,:=,
 define disable_plugins
@@ -410,12 +411,12 @@ define run
        @echo "WARNING: STARTUP_CONF not defined or file doesn't exist."
        @echo "         Running with minimal startup config: $(MINIMAL_STARTUP_CONF)\n"
        @cd $(STARTUP_DIR) && \
-         sudo $(2) $(1)/vpp/bin/vpp $(MINIMAL_STARTUP_CONF)
+         $(SUDO) $(2) $(1)/vpp/bin/vpp $(MINIMAL_STARTUP_CONF)
 endef
 else
 define run
        @cd $(STARTUP_DIR) && \
-         sudo $(2) $(1)/vpp/bin/vpp $(shell cat $(STARTUP_CONF) | sed -e 's/#.*//')
+         $(SUDO) $(2) $(1)/vpp/bin/vpp $(shell cat $(STARTUP_CONF) | sed -e 's/#.*//')
 endef
 endif
 
@@ -445,7 +446,7 @@ build-vat:
        $(call make,$(PLATFORM)_debug,vpp-api-test-install)
 
 run-vat:
-       @sudo $(BR)/install-$(PLATFORM)_debug-native/vpp/bin/vpp_api_test
+       @$(SUDO) $(BR)/install-$(PLATFORM)_debug-native/vpp/bin/vpp_api_test
 
 pkg-deb:
        $(call make,$(PLATFORM),install-deb)
index f2f1ba2..5437e2f 100644 (file)
  * limitations under the License.
  */
 
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/vfio.h>
+#include <sys/ioctl.h>
+
 #include <vnet/vnet.h>
 #include <vnet/plugin/plugin.h>
 #include <dpdk/device/dpdk.h>
@@ -88,9 +95,45 @@ static clib_error_t * dpdk_main_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (dpdk_main_init);
 
+
+clib_error_t *
+dpdk_early_init (vlib_main_t *vm)
+{
+  int fd = -1;
+  u64 *pt = 0;
+  clib_error_t *err = 0;
+
+  /* check if pagemap is accessible - if we get zero result
+     dpdk will not be able to get physical memory address and game is over
+     unless we have IOMMU */
+  pt = clib_mem_vm_get_paddr (&pt, min_log2 (sysconf (_SC_PAGESIZE)), 1);
+  if (pt && pt[0])
+    goto done;
+
+  if ((fd = open ("/dev/vfio/vfio", O_RDWR) == -1))
+      goto error;
+
+  if (ioctl (fd, VFIO_GET_API_VERSION) != VFIO_API_VERSION)
+      goto error;
+
+  /* if we have type 1 IOMMU page map is not needed */
+  if (ioctl (fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) == 1)
+    goto done;
+
+error:
+  err = clib_error_return (0, "access to physical devices is not allowed");
+
+done:
+  if (fd != -1)
+    close (fd);
+  vec_free (pt);
+  return err;
+}
+
 /* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () = {
     .version = VPP_BUILD_VER,
     .description = "Data Plane Development Kit (DPDK)",
+    .early_init = "dpdk_early_init",
 };
 /* *INDENT-ON* */
index 4898822..6d352ce 100644 (file)
@@ -565,6 +565,10 @@ static void __vlib_add_buffer_callbacks_t_##x (void)                    \
       clib_panic ("vlib buffer callbacks already registered");          \
     vlib_buffer_callbacks = &__##x##_buffer_callbacks;                  \
 }                                                                       \
+static void __vlib_rm_buffer_callbacks_t_##x (void)                     \
+    __attribute__((__destructor__)) ;                                   \
+static void __vlib_rm_buffer_callbacks_t_##x (void)                     \
+{ vlib_buffer_callbacks = 0; }                                          \
 __VA_ARGS__ vlib_buffer_callbacks_t __##x##_buffer_callbacks
 
 /*
index e713808..e8ba507 100644 (file)
@@ -162,6 +162,15 @@ static void __vlib_cli_command_registration_##x (void)                  \
     x.next_cli_command = cm->cli_command_registrations;                 \
     cm->cli_command_registrations = &x;                                 \
 }                                                                       \
+static void __vlib_cli_command_unregistration_##x (void)                \
+    __attribute__((__destructor__)) ;                                   \
+static void __vlib_cli_command_unregistration_##x (void)                \
+{                                                                       \
+    vlib_main_t * vm = vlib_get_main();                                 \
+    vlib_cli_main_t *cm = &vm->cli_main;                                \
+    VLIB_REMOVE_FROM_LINKED_LIST (cm->cli_command_registrations, &x,    \
+                                  next_cli_command);                    \
+}                                                                       \
 __VA_ARGS__ vlib_cli_command_t x
 #define VLIB_CLI_PARSE_RULE(x) \
   vlib_cli_parse_rule_t x
index 12db3f9..1eddbb1 100644 (file)
@@ -79,6 +79,25 @@ typedef struct vlib_config_function_runtime_t
   char name[32];
 } vlib_config_function_runtime_t;
 
+#define VLIB_REMOVE_FROM_LINKED_LIST(first,p,next)              \
+{                                                               \
+  if (first == p)                                               \
+      first = (p)->next;                                        \
+  else                                                          \
+    {                                                           \
+      __typeof__ (p) current = first;                           \
+       while (current->next)                                   \
+         {                                                     \
+           if (current->next == p)                             \
+             {                                                 \
+               current->next = current->next->next;            \
+               break;                                          \
+             }                                                 \
+           current = current->next;                            \
+         }                                                     \
+    }                                                           \
+}
+
 #define _VLIB_INIT_FUNCTION_SYMBOL(x, type)    \
   _vlib_##type##_function_##x
 
@@ -106,6 +125,30 @@ static void __vlib_add_##tag##_function_##x (void)              \
     = vm->tag##_function_registrations;                         \
   vm->tag##_function_registrations = &_vlib_init_function;      \
  _vlib_init_function.f = &x;                                    \
+}                                                               \
+static void __vlib_rm_##tag##_function_##x (void)               \
+    __attribute__((__destructor__)) ;                           \
+static void __vlib_rm_##tag##_function_##x (void)               \
+{                                                               \
+  vlib_main_t * vm = vlib_get_main();                           \
+  _vlib_init_function_list_elt_t *next;                         \
+  if (vm->tag##_function_registrations->f == &x)                \
+    {                                                           \
+      vm->tag##_function_registrations =                        \
+        vm->tag##_function_registrations->next_init_function;   \
+      return;                                                   \
+    }                                                           \
+  next = vm->tag##_function_registrations;                      \
+  while (next->next_init_function)                              \
+    {                                                           \
+      if (next->next_init_function->f == &x)                    \
+        {                                                       \
+          next->next_init_function =                            \
+            next->next_init_function->next_init_function;       \
+          return;                                               \
+        }                                                       \
+      next = next->next_init_function;                          \
+    }                                                           \
 }
 
 #define VLIB_INIT_FUNCTION(x) VLIB_DECLARE_INIT_FUNCTION(x,init)
@@ -128,6 +171,16 @@ static void __vlib_add_config_function_##x (void)               \
        = vm->config_function_registrations;                     \
     vm->config_function_registrations                           \
        = &VLIB_CONFIG_FUNCTION_SYMBOL(x);                       \
+}                                                               \
+static void __vlib_rm_config_function_##x (void)                \
+    __attribute__((__destructor__)) ;                           \
+static void __vlib_rm_config_function_##x (void)                \
+{                                                               \
+    vlib_main_t * vm = vlib_get_main();                         \
+    vlib_config_function_runtime_t *p =                         \
+       & VLIB_CONFIG_FUNCTION_SYMBOL (x);                       \
+    VLIB_REMOVE_FROM_LINKED_LIST                                \
+      (vm->config_function_registrations, p, next_registration);\
 }                                                               \
   vlib_config_function_runtime_t                                \
     VLIB_CONFIG_FUNCTION_SYMBOL (x)                             \
@@ -149,6 +202,16 @@ static void __vlib_add_config_function_##x (void)               \
        = vm->config_function_registrations;                     \
     vm->config_function_registrations                           \
        = &VLIB_CONFIG_FUNCTION_SYMBOL(x);                       \
+}                                                               \
+static void __vlib_rm_config_function_##x (void)                \
+    __attribute__((__destructor__)) ;                           \
+static void __vlib_rm_config_function_##x (void)                \
+{                                                               \
+    vlib_main_t * vm = vlib_get_main();                         \
+    vlib_config_function_runtime_t *p =                         \
+       & VLIB_CONFIG_FUNCTION_SYMBOL (x);                       \
+    VLIB_REMOVE_FROM_LINKED_LIST                                \
+      (vm->config_function_registrations, p, next_registration);\
 }                                                               \
   vlib_config_function_runtime_t                                \
     VLIB_CONFIG_FUNCTION_SYMBOL (x)                             \
index dc95b0e..28f9435 100644 (file)
@@ -261,6 +261,14 @@ static void __mc_serialize_msg_registration_##x (void)          \
     x.next_registration = vm->mc_msg_registrations;             \
     vm->mc_msg_registrations = &x;                              \
 }                                                               \
+static void __mc_serialize_msg_unregistration_##x (void)        \
+    __attribute__((__destructor__)) ;                           \
+static void __mc_serialize_msg_unregistration_##x (void)        \
+{                                                               \
+    vlib_main_t * vm = vlib_get_main();                         \
+    VLIB_REMOVE_FROM_LINKED_LIST (vm->mc_msg_registrations, &x, \
+                                  next_registration);           \
+}                                                               \
 __VA_ARGS__ mc_serialize_msg_t x
 
 typedef enum
index 2acd61c..7177beb 100644 (file)
@@ -150,6 +150,14 @@ static void __vlib_add_node_registration_##x (void)                     \
     x.next_registration = vm->node_main.node_registrations;             \
     vm->node_main.node_registrations = &x;                              \
 }                                                                       \
+static void __vlib_rm_node_registration_##x (void)                      \
+    __attribute__((__destructor__)) ;                                   \
+static void __vlib_rm_node_registration_##x (void)                      \
+{                                                                       \
+    vlib_main_t * vm = vlib_get_main();                                 \
+    VLIB_REMOVE_FROM_LINKED_LIST (vm->node_main.node_registrations,     \
+                                  &x, next_registration);               \
+}                                                                       \
 __VA_ARGS__ vlib_node_registration_t x
 
 #if CLIB_DEBUG > 0
index ec805b3..a705671 100644 (file)
@@ -159,6 +159,14 @@ static void __vlib_add_pci_device_registration_##x (void)       \
     x.next_registration = pm->pci_device_registrations;         \
     pm->pci_device_registrations = &x;                          \
 }                                                               \
+static void __vlib_rm_pci_device_registration_##x (void)        \
+    __attribute__((__destructor__)) ;                           \
+static void __vlib_rm_pci_device_registration_##x (void)        \
+{                                                               \
+    vlib_pci_main_t * pm = &pci_main;                           \
+    VLIB_REMOVE_FROM_LINKED_LIST (pm->pci_device_registrations, \
+                                  &x, next_registration);       \
+}                                                               \
 __VA_ARGS__ pci_device_registration_t x
 
 clib_error_t *vlib_pci_bind_to_uio (vlib_pci_addr_t * addr,
index 8931584..aaba218 100644 (file)
@@ -362,6 +362,13 @@ static void __vlib_add_thread_registration_##x (void)   \
   x.next = tm->next;                                    \
   tm->next = &x;                                        \
 }                                                       \
+static void __vlib_rm_thread_registration_##x (void)    \
+  __attribute__((__destructor__)) ;                     \
+static void __vlib_rm_thread_registration_##x (void)    \
+{                                                       \
+  vlib_thread_main_t * tm = &vlib_thread_main;          \
+  VLIB_REMOVE_FROM_LINKED_LIST (tm->next, &x, next);    \
+}                                                       \
 __VA_ARGS__ vlib_thread_registration_t x
 
 always_inline u32
index b4eb0b9..61eaad4 100644 (file)
@@ -155,7 +155,8 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init)
     {
       /* This should never happen unless somebody chagnes registration macro */
       clib_warning ("Missing plugin registration in plugin '%s'", pi->name);
-      os_exit (1);
+      dlclose (pi->handle);
+      goto error;
     }
 
   pi->reg = reg;
@@ -175,7 +176,8 @@ load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init)
          if (error)
            {
              clib_error_report (error);
-             os_exit (1);
+             dlclose (pi->handle);
+             goto error;
            }
        }
       else
index eb6c95c..70a456e 100644 (file)
@@ -109,6 +109,14 @@ static void __vnet_add_feature_arc_registration_##x (void) \
   vnet_feat_arc_##x.next = fm->next_arc;                       \
   fm->next_arc = & vnet_feat_arc_##x;                          \
 }                                                              \
+static void __vnet_rm_feature_arc_registration_##x (void)      \
+  __attribute__((__destructor__)) ;                            \
+static void __vnet_rm_feature_arc_registration_##x (void)      \
+{                                                              \
+  vnet_feature_main_t * fm = &feature_main;                    \
+  vnet_feature_arc_registration_t *r = &vnet_feat_arc_##x;     \
+  VLIB_REMOVE_FROM_LINKED_LIST (fm->next_arc, r, next);                \
+}                                                              \
 __VA_ARGS__ vnet_feature_arc_registration_t vnet_feat_arc_##x
 
 #define VNET_FEATURE_INIT(x,...)                               \
@@ -121,6 +129,14 @@ static void __vnet_add_feature_registration_##x (void)             \
   vnet_feat_##x.next = fm->next_feature;                       \
   fm->next_feature = & vnet_feat_##x;                          \
 }                                                              \
+static void __vnet_rm_feature_registration_##x (void)          \
+  __attribute__((__destructor__)) ;                            \
+static void __vnet_rm_feature_registration_##x (void)          \
+{                                                              \
+  vnet_feature_main_t * fm = &feature_main;                    \
+  vnet_feature_registration_t *r = &vnet_feat_##x;             \
+  VLIB_REMOVE_FROM_LINKED_LIST (fm->next_feature, r, next);    \
+}                                                              \
 __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x
 
 void
index 00a7353..6a140d2 100644 (file)
@@ -101,6 +101,31 @@ static void __vnet_interface_function_init_##tag##_##f (void)           \
  init_function.next_interface_function = vnm->tag##_functions[p];       \
  vnm->tag##_functions[p] = &init_function;                              \
  init_function.fp = (void *) &f;                                        \
+}                                                                       \
+static void __vnet_interface_function_deinit_##tag##_##f (void)         \
+    __attribute__((__destructor__)) ;                                   \
+                                                                        \
+static void __vnet_interface_function_deinit_##tag##_##f (void)         \
+{                                                                       \
+ vnet_main_t * vnm = vnet_get_main();                                   \
+ _vnet_interface_function_list_elt_t *next;                             \
+ if (vnm->tag##_functions[p]->fp == (void *) &f)                        \
+    {                                                                   \
+      vnm->tag##_functions[p] =                                         \
+        vnm->tag##_functions[p]->next_interface_function;               \
+      return;                                                           \
+    }                                                                   \
+  next = vnm->tag##_functions[p];                                       \
+  while (next->next_interface_function)                                 \
+    {                                                                   \
+      if (next->next_interface_function->fp == (void *) &f)             \
+        {                                                               \
+          next->next_interface_function =                               \
+            next->next_interface_function->next_interface_function;     \
+          return;                                                       \
+        }                                                               \
+      next = next->next_interface_function;                             \
+    }                                                                   \
 }
 
 #define _VNET_INTERFACE_FUNCTION_DECL(f,tag)                            \
@@ -200,6 +225,14 @@ static void __vnet_add_device_class_registration_##x (void)             \
     x.next_class_registration = vnm->device_class_registrations;        \
     vnm->device_class_registrations = &x;                               \
 }                                                                       \
+static void __vnet_rm_device_class_registration_##x (void)              \
+    __attribute__((__destructor__)) ;                                   \
+static void __vnet_rm_device_class_registration_##x (void)              \
+{                                                                       \
+    vnet_main_t * vnm = vnet_get_main();                                \
+    VLIB_REMOVE_FROM_LINKED_LIST (vnm->device_class_registrations,      \
+                                  &x, next_class_registration);         \
+}                                                                       \
 __VA_ARGS__ vnet_device_class_t x
 
 #define VLIB_DEVICE_TX_FUNCTION_CLONE_TEMPLATE(arch, fn, tgt)          \
@@ -368,6 +401,14 @@ static void __vnet_add_hw_interface_class_registration_##x (void)       \
     x.next_class_registration = vnm->hw_interface_class_registrations;  \
     vnm->hw_interface_class_registrations = &x;                         \
 }                                                                       \
+static void __vnet_rm_hw_interface_class_registration_##x (void)        \
+    __attribute__((__destructor__)) ;                                   \
+static void __vnet_rm_hw_interface_class_registration_##x (void)        \
+{                                                                       \
+    vnet_main_t * vnm = vnet_get_main();                                \
+    VLIB_REMOVE_FROM_LINKED_LIST (vnm->hw_interface_class_registrations,\
+                                  &x, next_class_registration);         \
+}                                                                       \
 __VA_ARGS__ vnet_hw_interface_class_t x
 
 /* Hardware-interface.  This corresponds to a physical wire