init / exit function ordering 23/19623/4
authorDave Barach <dave@barachs.net>
Tue, 14 May 2019 22:01:44 +0000 (18:01 -0400)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 16 May 2019 16:11:23 +0000 (16:11 +0000)
The vlib init function subsystem now supports a mix of procedural and
formally-specified ordering constraints. We should eliminate procedural
knowledge wherever possible.

The following schemes are *roughly* equivalent:

static clib_error_t *init_runs_first (vlib_main_t *vm)
{
   clib_error_t *error;

   ... do some stuff...

   if ((error = vlib_call_init_function (init_runs_next)))
     return error;
   ...
}
VLIB_INIT_FUNCTION (init_runs_first);

and

static clib_error_t *init_runs_first (vlib_main_t *vm)
{
   ... do some stuff...
}
VLIB_INIT_FUNCTION (init_runs_first) =
{
    .runs_before = VLIB_INITS("init_runs_next"),
};

The first form will [most likely] call "init_runs_next" on the
spot. The second form means that "init_runs_first" runs before
"init_runs_next," possibly much earlier in the sequence.

Please DO NOT construct sets of init functions where A before B
actually means A *right before* B. It's not necessary - simply combine
A and B - and it leads to hugely annoying debugging exercises when
trying to switch from ad-hoc procedural ordering constraints to formal
ordering constraints.

Change-Id: I5e4353503bf43b4acb11a45fb33c79a5ade8426c
Signed-off-by: Dave Barach <dave@barachs.net>
62 files changed:
src/examples/vlib/main_stub.c
src/plugins/abf/abf_itf_attach.c
src/plugins/avf/device.c
src/plugins/cdp/cdp_input.c
src/plugins/crypto_ia32/main.c
src/plugins/crypto_ipsecmb/ipsecmb.c
src/plugins/crypto_openssl/main.c
src/plugins/dpdk/api/dpdk_api.c
src/plugins/dpdk/device/cli.c
src/plugins/dpdk/device/dpdk.h
src/plugins/dpdk/device/init.c
src/plugins/dpdk/main.c
src/plugins/gbp/gbp_vxlan.c
src/plugins/igmp/igmp.c
src/plugins/igmp/igmp_input.c
src/plugins/igmp/igmp_ssm_range.c
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2.h
src/plugins/ikev2/ikev2_cli.c
src/plugins/ioam/analyse/ioam_summary_export.c
src/plugins/ioam/encap/ip6_ioam_e2e.c
src/plugins/ioam/encap/ip6_ioam_pot.c
src/plugins/ioam/encap/ip6_ioam_trace.c
src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam_trace.c
src/plugins/ioam/udp-ping/udp_ping_export.c
src/plugins/ioam/udp-ping/udp_ping_node.c
src/plugins/ixge/ixge.c
src/plugins/lacp/input.c
src/plugins/nsh/nsh-md2-ioam/nsh_md2_ioam_trace.c
src/plugins/tlsmbedtls/tls_mbedtls.c
src/plugins/tlsopenssl/tls_openssl.c
src/vlib/init.c
src/vlib/init.h
src/vlib/linux/pci.c
src/vlib/linux/vmbus.c
src/vlib/threads.c
src/vlib/unix/input.c
src/vlib/unix/main.c
src/vlib/vmbus/vmbus.c
src/vlibmemory/memory_api.c
src/vlibmemory/socket_api.c
src/vlibmemory/vlib_api.c
src/vnet/adj/adj_bfd.c
src/vnet/classify/in_out_acl.c
src/vnet/cop/cop.c
src/vnet/devices/virtio/vhost_user.c
src/vnet/dpo/dpo.c
src/vnet/ethernet/arp.c
src/vnet/ethernet/ethernet.h
src/vnet/ethernet/init.c
src/vnet/ethernet/node.c
src/vnet/fib/fib.c
src/vnet/fib/fib_bfd.c
src/vnet/ip/ip_init.c
src/vnet/ipfix-export/flow_report.c
src/vnet/lisp-gpe/lisp_gpe_adjacency.c
src/vnet/misc.c
src/vnet/mpls/mpls_input.c
src/vnet/udp/udp.c
src/vnet/unix/tuntap.c
src/vnet/vxlan-gbp/vxlan_gbp.c
src/vpp/stats/stat_segment.c

index c5c19aa..3735055 100644 (file)
@@ -25,18 +25,17 @@ main (int argc, char *argv[])
 static clib_error_t *
 main_stub_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = unix_physmem_init (vm)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, unix_cli_init)))
-    return error;
+  clib_error_t *error = 0;
 
   return error;
 }
 
-VLIB_INIT_FUNCTION (main_stub_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (main_stub_init) =
+{
+  .runs_after = VLIB_INITS("unix_physmem_init", "unix_cli_init"),
+};
+/* *INDENT-ON* */
 
 #if 0
 /* Node test code. */
index 151fb98..9569306 100644 (file)
@@ -764,7 +764,12 @@ abf_itf_bond_init (vlib_main_t * vm)
   return (NULL);
 }
 
-VLIB_INIT_FUNCTION (abf_itf_bond_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (abf_itf_bond_init) =
+{
+  .runs_after = VLIB_INITS("acl_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 7d01149..74b6ab4 100644 (file)
@@ -1433,12 +1433,8 @@ clib_error_t *
 avf_init (vlib_main_t * vm)
 {
   avf_main_t *am = &avf_main;
-  clib_error_t *error;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
 
-  if ((error = vlib_call_init_function (vm, pci_bus_init)))
-    return error;
-
   vec_validate_aligned (am->per_thread_data, tm->n_vlib_mains - 1,
                        CLIB_CACHE_LINE_BYTES);
 
@@ -1448,7 +1444,12 @@ avf_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (avf_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (avf_init) =
+{
+  .runs_after = VLIB_INITS ("pci_bus_init"),
+};
+/* *INDENT-OFF* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 946aaf7..dbe179a 100644 (file)
@@ -408,15 +408,11 @@ cdp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
 static clib_error_t *
 cdp_input_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
   cdp_main_t *cm = &cdp_main;
   void vnet_cdp_node_reference (void);
 
   vnet_cdp_node_reference ();
 
-  if ((error = vlib_call_init_function (vm, cdp_periodic_init)))
-    return error;
-
   cm->vlib_main = vm;
   cm->vnet_main = vnet_get_main ();
   cm->neighbor_by_sw_if_index = hash_create (0, sizeof (uword));
@@ -424,7 +420,12 @@ cdp_input_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (cdp_input_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (cdp_input_init) =
+{
+  .runs_after = VLIB_INITS("cdp_periodic_init"),
+};
+/* *INDENT-ON* */
 
 
 static u8 *
index 45bf34e..a02fc38 100644 (file)
@@ -97,10 +97,7 @@ crypto_ia32_init (vlib_main_t * vm)
 {
   crypto_ia32_main_t *cm = &crypto_ia32_main;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, vnet_crypto_init)))
-    return error;
+  clib_error_t *error = 0;
 
   vec_validate_aligned (cm->per_thread_data, tm->n_vlib_mains - 1,
                        CLIB_CACHE_LINE_BYTES);
@@ -124,7 +121,12 @@ error:
   return error;
 }
 
-VLIB_INIT_FUNCTION (crypto_ia32_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (crypto_ia32_init) =
+{
+  .runs_after = VLIB_INITS ("vnet_crypto_init"),
+};
+/* *INDENT-ON* */
 
 #include <vpp/app/version.h>
 
index 7495452..fccc697 100644 (file)
@@ -475,9 +475,6 @@ crypto_ipsecmb_init (vlib_main_t * vm)
   u32 eidx;
   u8 *name;
 
-  if ((error = vlib_call_init_function (vm, vnet_crypto_init)))
-    return error;
-
   if (!clib_cpu_supports_aes ())
     return 0;
 
@@ -547,7 +544,12 @@ crypto_ipsecmb_init (vlib_main_t * vm)
   return (NULL);
 }
 
-VLIB_INIT_FUNCTION (crypto_ipsecmb_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (crypto_ipsecmb_init) =
+{
+  .runs_after = VLIB_INITS ("vnet_crypto_init"),
+};
+/* *INDENT-ON* */
 
 /* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () =
index f6e1537..2132c5b 100644 (file)
@@ -232,13 +232,9 @@ crypto_openssl_init (vlib_main_t * vm)
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   openssl_per_thread_data_t *ptd;
   u8 *seed_data = 0;
-  clib_error_t *error;
   time_t t;
   pid_t pid;
 
-  if ((error = vlib_call_init_function (vm, vnet_crypto_init)))
-    return error;
-
   u32 eidx = vnet_crypto_register_engine (vm, "openssl", 50, "OpenSSL");
 
 #define _(m, a, b) \
@@ -284,7 +280,13 @@ crypto_openssl_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (crypto_openssl_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (crypto_openssl_init) =
+{
+  .runs_after = VLIB_INITS ("vnet_crypto_init"),
+};
+/* *INDENT-ON* */
+
 
 /* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () = {
index 97c4bc7..5ff8d5f 100755 (executable)
@@ -297,10 +297,6 @@ dpdk_api_init (vlib_main_t * vm)
   dpdk_main_t *dm = &dpdk_main;
   clib_error_t *error = 0;
 
-  /* init CLI */
-  if ((error = vlib_call_init_function (vm, dpdk_init)))
-    return error;
-
   u8 *name;
   name = format (0, "dpdk_%08x%c", api_version, 0);
 
@@ -320,8 +316,11 @@ dpdk_api_init (vlib_main_t * vm)
   return error;
 }
 
-VLIB_INIT_FUNCTION (dpdk_api_init);
-
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (dpdk_api_init) =
+{
+  .runs_after = VLIB_INITS ("dpdk_init"),
+/* *INDENT-OFF* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 765b298..04cf37f 100644 (file)
@@ -1737,6 +1737,12 @@ VLIB_CLI_COMMAND (show_vpe_version_command, static) = {
 };
 /* *INDENT-ON* */
 
+/* Dummy function to get us linked in. */
+void
+dpdk_cli_reference (void)
+{
+}
+
 clib_error_t *
 dpdk_cli_init (vlib_main_t * vm)
 {
index bd9b359..f79465c 100644 (file)
@@ -512,6 +512,7 @@ clib_error_t *unformat_hqos (unformat_input_t * input,
 
 struct rte_pci_device *dpdk_get_pci_device (const struct rte_eth_dev_info
                                            *info);
+void dpdk_cli_reference (void);
 
 #if CLI_DEBUG
 int dpdk_buffer_validate_trajectory_all (u32 * uninitialized);
index c83b2b5..22ea659 100644 (file)
@@ -1734,6 +1734,8 @@ dpdk_init (vlib_main_t * vm)
   STATIC_ASSERT (RTE_CACHE_LINE_SIZE == 1 << CLIB_LOG2_CACHE_LINE_BYTES,
                 "DPDK RTE CACHE LINE SIZE does not match with 1<<CLIB_LOG2_CACHE_LINE_BYTES");
 
+  dpdk_cli_reference ();
+
   dm->vlib_main = vm;
   dm->vnet_main = vnet_get_main ();
   dm->conf = &dpdk_config_main;
@@ -1751,10 +1753,6 @@ dpdk_init (vlib_main_t * vm)
   dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
   dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
 
-  /* init CLI */
-  if ((error = vlib_call_init_function (vm, dpdk_cli_init)))
-    return error;
-
   dm->log_default = vlib_log_register_class ("dpdk", 0);
 
   return error;
@@ -1762,7 +1760,6 @@ dpdk_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (dpdk_init);
 
-
 /*
  * fd.io coding-style-patch-verification: ON
  *
index d22b671..a1ea9e3 100644 (file)
@@ -85,16 +85,18 @@ static clib_error_t * dpdk_main_init (vlib_main_t * vm)
   dm->vlib_main = vm;
   dm->vnet_main = vnet_get_main ();
 
-  if ((error = vlib_call_init_function (vm, dpdk_init)))
-    return error;
-
   /* register custom delay function */
   rte_delay_us_callback_register (rte_delay_us_override_cb);
 
   return error;
 }
 
-VLIB_INIT_FUNCTION (dpdk_main_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (dpdk_main_init) =
+{
+    .runs_after = VLIB_INITS("dpdk_init"),
+};
+/* *INDENT-ON* */
 
 
 clib_error_t *
index 49dae7e..de635d0 100644 (file)
@@ -678,25 +678,24 @@ static clib_error_t *
 gbp_vxlan_init (vlib_main_t * vm)
 {
   vxlan_gbp_main_t *vxm = &vxlan_gbp_main;
-  clib_error_t *error;
 
   gt_logger = vlib_log_register_class ("gbp", "tun");
 
-  if ((error = vlib_call_init_function (vm, punt_init)))
-    return error;
-  if ((error = vlib_call_init_function (vm, vxlan_gbp_init)))
-    return error;
-
   punt_hdl = vlib_punt_client_register ("gbp-vxlan");
 
   vlib_punt_register (punt_hdl,
                      vxm->punt_no_such_tunnel[FIB_PROTOCOL_IP4],
                      "gbp-vxlan4");
 
-  return (error);
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (gbp_vxlan_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (gbp_vxlan_init) =
+{
+  .runs_after = VLIB_INITS("punt_init", "vxlan_gbp_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 7f82861..4e2fce1 100644 (file)
@@ -479,24 +479,24 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
 static clib_error_t *
 igmp_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
   igmp_main_t *im = &igmp_main;
 
-  if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
-    return error;
-
   im->igmp_api_client_by_client_index = hash_create (0, sizeof (u32));
 
   im->logger = vlib_log_register_class ("igmp", 0);
 
   IGMP_DBG ("initialized");
 
-  return (error);
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (igmp_init);
 /* *INDENT-OFF* */
-VLIB_PLUGIN_REGISTER () = {
+VLIB_INIT_FUNCTION (igmp_init) =
+{
+  .runs_after = VLIB_INITS("ip4_lookup_init"),
+};
+VLIB_PLUGIN_REGISTER () =
+{
   .version = VPP_BUILD_VER,
   .description = "Internet Group Management Protocol (IGMP)",
 };
index 83e11ec..d5f714b 100644 (file)
@@ -445,19 +445,19 @@ VLIB_REGISTER_NODE (igmp_parse_report_node) =
 static clib_error_t *
 igmp_input_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, igmp_init)))
-    return error;
-
   ip4_register_protocol (IP_PROTOCOL_IGMP, igmp_input_node.index);
 
   IGMP_DBG ("input-initialized");
 
-  return (error);
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (igmp_input_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (igmp_input_init) =
+{
+  .runs_after = VLIB_INITS("igmp_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 3d12712..c74d312 100644 (file)
@@ -138,20 +138,19 @@ VLIB_CLI_COMMAND (igmp_show_timers_command, static) = {
 static clib_error_t *
 igmp_ssm_range_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, igmp_init)))
-    return error;
-
   igmp_ssm_range_populate ();
 
   IGMP_DBG ("ssm-range-initialized");
 
-  return (error);
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (igmp_ssm_range_init);
-
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (igmp_ssm_range_init) =
+{
+  .runs_after = VLIB_INITS("igmp_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 2340137..e7b2f92 100644 (file)
@@ -3295,13 +3295,9 @@ clib_error_t *
 ikev2_init (vlib_main_t * vm)
 {
   ikev2_main_t *km = &ikev2_main;
-  clib_error_t *error;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   int thread_id;
 
-  if ((error = vlib_call_init_function (vm, ipsec_init)))
-    return error;
-
   clib_memset (km, 0, sizeof (ikev2_main_t));
   km->vnet_main = vnet_get_main ();
   km->vlib_main = vm;
@@ -3319,16 +3315,20 @@ ikev2_init (vlib_main_t * vm)
 
   km->sa_by_ispi = hash_create (0, sizeof (uword));
 
-
-  if ((error = vlib_call_init_function (vm, ikev2_cli_init)))
-    return error;
-
   udp_register_dst_port (vm, 500, ikev2_node.index, 1);
 
+  ikev2_cli_reference ();
+
   return 0;
 }
 
-VLIB_INIT_FUNCTION (ikev2_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ikev2_init) =
+{
+  .runs_after = VLIB_INITS("ipsec_init"),
+};
+/* *INDENT-ON* */
+
 
 static u8
 ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa)
index 55731bf..2feecf7 100644 (file)
@@ -422,6 +422,7 @@ uword unformat_ikev2_transform_dh_type (unformat_input_t * input,
                                        va_list * args);
 uword unformat_ikev2_transform_esn_type (unformat_input_t * input,
                                         va_list * args);
+void ikev2_cli_reference (void);
 
 #endif /* __included_ikev2_h__ */
 
index 8801793..0933667 100644 (file)
@@ -584,15 +584,11 @@ VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
 };
 /* *INDENT-ON* */
 
-
-clib_error_t *
-ikev2_cli_init (vlib_main_t * vm)
+void
+ikev2_cli_reference (void)
 {
-  return 0;
 }
 
-VLIB_INIT_FUNCTION (ikev2_cli_init);
-
 /*
  * fd.io coding-style-patch-verification: ON
  *
index c16e839..4851491 100644 (file)
@@ -427,15 +427,15 @@ ioam_flow_create (u8 del)
 clib_error_t *
 ioam_flow_report_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, flow_report_init)))
-    return error;
-
   return 0;
 }
 
-VLIB_INIT_FUNCTION (ioam_flow_report_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ioam_flow_report_init) =
+{
+  .runs_after = VLIB_INITS("flow_report_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index cdaf740..5871408 100644 (file)
@@ -44,7 +44,7 @@ static u8 * ioam_e2e_trace_handler (u8 * s,
   return s;
 }
 
-int 
+int
 ioam_e2e_config_handler (void *data, u8 disable)
 {
   int *analyse = data;
@@ -171,13 +171,6 @@ VLIB_CLI_COMMAND (ioam_show_e2e_cmd, static) = {
 static clib_error_t *
 ioam_e2e_init (vlib_main_t * vm)
 {
-  clib_error_t * error;
-
-  if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init)))
-    {
-      return(error);
-    }
-
   /*
    * As of now we have only PPC under E2E header.
    */
@@ -213,4 +206,9 @@ ioam_e2e_init (vlib_main_t * vm)
  * Init function for the E2E lib.
  * ip6_hop_by_hop_ioam_e2e_init gets called during init.
  */
-VLIB_INIT_FUNCTION (ioam_e2e_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ioam_e2e_init) =
+{
+    .runs_after = VLIB_INITS("ip6_hop_by_hop_ioam_init"),
+};
+/* *INDENT-ON* */
index 8dd06c1..71c0cc9 100644 (file)
@@ -29,7 +29,7 @@
   _(PROCESSED, "Pkts with ip6 hop-by-hop pot options")                 \
   _(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \
   _(PASSED, "Pkts with POT in Policy")                                 \
-  _(FAILED, "Pkts with POT out of Policy") 
+  _(FAILED, "Pkts with POT out of Policy")
 
 static char * ip6_hop_by_hop_ioam_pot_stats_strings[] = {
 #define _(sym,string) string,
@@ -47,7 +47,7 @@ typedef enum {
 typedef struct {
   /* stats */
   u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)];
-  
+
   /* convenience */
   vlib_main_t * vlib_main;
   vnet_main_t * vnet_main;
@@ -55,7 +55,7 @@ typedef struct {
 
 ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main;
 
-always_inline void 
+always_inline void
 ip6_ioam_stats_increment_counter (u32 counter_index, u64 increment)
 {
   ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main;
@@ -69,13 +69,13 @@ static u8 * format_ioam_pot (u8 * s, va_list * args)
   ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *);
   u64 random, cumulative;
   random = cumulative = 0;
-  if (pot0) 
-    { 
+  if (pot0)
+    {
       random = clib_net_to_host_u64 (pot0->random);
       cumulative = clib_net_to_host_u64 (pot0->cumulative);
     }
 
-  s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x", 
+  s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x",
              random, cumulative, pot0 ? pot0->reserved_profile_id : ~0);
   return s;
 }
@@ -117,22 +117,22 @@ ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b,
       pot0->reserved_profile_id =
        pot_profile_index & PROFILE_ID_MASK;
       pot_profile_incr_usage_stats(pot_profile);
-    } 
-  else 
+    }
+  else
     { /* Non encap node */
-      if (PREDICT_FALSE(pot0->reserved_profile_id != 
-                       pot_profile_index || pot_profile == 0)) 
+      if (PREDICT_FALSE(pot0->reserved_profile_id !=
+                       pot_profile_index || pot_profile == 0))
        {
          /* New profile announced by encap node. */
          new_profile =
-           pot_profile_find(pot0->reserved_profile_id); 
+           pot_profile_find(pot0->reserved_profile_id);
          if (PREDICT_FALSE(new_profile == 0 ||
-                           new_profile->valid == 0)) 
+                           new_profile->valid == 0))
            {
              ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
              return(-1);
-           } 
-         else 
+           }
+         else
            {
              pot_profile_index = pot0->reserved_profile_id;
              pot_profile = new_profile;
@@ -143,7 +143,7 @@ ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b,
       pot_profile_incr_usage_stats(pot_profile);
     }
 
-  if (pot0->random == 0) 
+  if (pot0->random == 0)
     {
       pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile));
       pot0->cumulative = 0;
@@ -196,7 +196,7 @@ int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 *rewrite_siz
       pot_option = (ioam_pot_option_t *)rewrite_string;
       pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
         | HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
-      pot_option->hdr.length = sizeof (ioam_pot_option_t) - 
+      pot_option->hdr.length = sizeof (ioam_pot_option_t) -
         sizeof (ip6_hop_by_hop_option_t);
       return(0);
     }
@@ -235,15 +235,11 @@ static clib_error_t *
 ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm)
 {
   ip6_hop_by_hop_ioam_pot_main_t * hm = &ip6_hop_by_hop_ioam_pot_main;
-  clib_error_t * error;
-
-  if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init)))
-    return(error);
 
   hm->vlib_main = vm;
   hm->vnet_main = vnet_get_main();
   clib_memset(hm->counters, 0, sizeof(hm->counters));
-  
+
   if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, ip6_hbh_ioam_proof_of_transit_handler,
                              ip6_hbh_ioam_proof_of_transit_trace_handler) < 0)
     return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed"));
@@ -260,6 +256,9 @@ ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm)
   return (0);
 }
 
-VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init);
-
-
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init) =
+{
+  .runs_after = VLIB_INITS("ip6_hop_by_hop_ioam_init"),
+};
+/* *INDENT-OFF* */
index ddd9ae9..53fb63e 100644 (file)
@@ -417,16 +417,6 @@ static clib_error_t *
 ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm)
 {
   ip6_hop_by_hop_ioam_trace_main_t *hm = &ip6_hop_by_hop_ioam_trace_main;
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, ip_main_init)))
-    return (error);
-
-  if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init)))
-    return (error);
 
   hm->vlib_main = vm;
   hm->vnet_main = vnet_get_main ();
@@ -452,6 +442,14 @@ ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm)
   return (0);
 }
 
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_trace_init) =
+{
+  .runs_after = VLIB_INITS ("ip_main_init", "ip6_lookup_init",
+                            "ip6_hop_by_hop_ioam_init"),
+};
+/* *INDENT-ON* */
+
 int
 ip6_trace_profile_cleanup (void)
 {
@@ -490,9 +488,6 @@ ip6_trace_profile_setup (void)
   return (0);
 }
 
-
-VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_trace_init);
-
 /*
  * fd.io coding-style-patch-verification: ON
  *
index e2c130c..c51d251 100644 (file)
@@ -436,16 +436,6 @@ static clib_error_t *
 vxlan_gpe_ioam_trace_init (vlib_main_t * vm)
 {
   vxlan_gpe_ioam_trace_main_t *hm = &vxlan_gpe_ioam_trace_main;
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, ip_main_init)))
-    return (error);
-
-  if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, vxlan_gpe_init)))
-    return (error);
 
   hm->vlib_main = vm;
   hm->vnet_main = vnet_get_main ();
@@ -470,7 +460,14 @@ vxlan_gpe_ioam_trace_init (vlib_main_t * vm)
   return (0);
 }
 
-VLIB_INIT_FUNCTION (vxlan_gpe_ioam_trace_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (vxlan_gpe_ioam_trace_init) =
+{
+  .runs_after = VLIB_INITS("ip_main_init", "ip6_lookup_init",
+                           "vxlan_gpe_init"),
+};
+/* *INDENT-ON* */
+
 
 int
 vxlan_gpe_trace_profile_cleanup (void)
index 7a7cad4..d25eb10 100644 (file)
@@ -290,15 +290,16 @@ VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
 clib_error_t *
 udp_ping_flow_report_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, flow_report_init)))
-    return error;
-
   return 0;
 }
 
-VLIB_INIT_FUNCTION (udp_ping_flow_report_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
+{
+  .runs_after = VLIB_INITS ("flow_report_init"),
+};
+/* *INDENT-ON* */
+
 
 /*
  * fd.io coding-style-patch-verification: ON
index 59e4511..e5916db 100644 (file)
@@ -819,21 +819,21 @@ VLIB_REGISTER_NODE (udp_ping_local, static) =
 static clib_error_t *
 udp_ping_init (vlib_main_t * vm)
 {
-  clib_error_t *error = 0;
-
   udp_ping_main.vlib_main = vm;
   udp_ping_main.vnet_main = vnet_get_main ();
   udp_ping_main.timer_interval = 1e9;
 
-  if ((error = vlib_call_init_function (vm, ip_main_init)))
-    return (error);
-
   ip6_register_protocol (IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS,
                         udp_ping_local.index);
   return 0;
 }
 
-VLIB_INIT_FUNCTION (udp_ping_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (udp_ping_init) =
+{
+  .runs_after = VLIB_INITS("ip_main_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 8faa9a9..c27042d 100644 (file)
@@ -2788,7 +2788,6 @@ clib_error_t *
 ixge_init (vlib_main_t * vm)
 {
   ixge_main_t *xm = &ixge_main;
-  clib_error_t *error;
 
   xm->vlib_main = vm;
   clib_memset (&xm->tx_descriptor_template, 0,
@@ -2807,13 +2806,15 @@ ixge_init (vlib_main_t * vm)
       | IXGE_TX_DESCRIPTOR_STATUS0_REPORT_STATUS);
   xm->tx_descriptor_template_mask.status1 &=
     ~(IXGE_TX_DESCRIPTOR_STATUS1_DONE);
-
-  error = vlib_call_init_function (vm, pci_bus_init);
-
-  return error;
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (ixge_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ixge_init) =
+{
+  .runs_before = VLIB_INITS("pci_bus_init"),
+};
+/* *INDENT-ON* */
 
 
 static void
index 8212b11..ef7cca9 100644 (file)
@@ -233,15 +233,15 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0)
 static clib_error_t *
 lacp_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, lacp_periodic_init)))
-    return error;
-
   return 0;
 }
 
-VLIB_INIT_FUNCTION (lacp_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (lacp_init) =
+{
+  .runs_after = VLIB_INITS("lacp_periodic_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * packet trace format function, very similar to
index bd56a6a..c40e89b 100644 (file)
@@ -354,13 +354,6 @@ nsh_md2_ioam_trace_init (vlib_main_t * vm)
 {
   nsh_md2_ioam_trace_main_t *hm = &nsh_md2_ioam_trace_main;
   nsh_md2_ioam_main_t *gm = &nsh_md2_ioam_main;
-  clib_error_t *error;
-
-  if ((error = vlib_call_init_function (vm, nsh_init)))
-    return (error);
-
-  if ((error = vlib_call_init_function (vm, nsh_md2_ioam_init)))
-    return (error);
 
   hm->vlib_main = vm;
   hm->vnet_main = vnet_get_main ();
@@ -384,7 +377,12 @@ nsh_md2_ioam_trace_init (vlib_main_t * vm)
   return (0);
 }
 
-VLIB_INIT_FUNCTION (nsh_md2_ioam_trace_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (nsh_md2_ioam_trace_init) =
+{
+  .runs_after = VLIB_INITS ("nsh_init", "nsh_md2_ioam_init"),
+};
+/* *INDENT-ON* */
 
 int
 nsh_md2_ioam_trace_profile_cleanup (void)
index e356088..7311232 100644 (file)
@@ -635,14 +635,10 @@ tls_mbedtls_init (vlib_main_t * vm)
 {
   vlib_thread_main_t *vtm = vlib_get_thread_main ();
   mbedtls_main_t *mm = &mbedtls_main;
-  clib_error_t *error;
   u32 num_threads;
 
   num_threads = 1 /* main thread */  + vtm->n_threads;
 
-  if ((error = vlib_call_init_function (vm, tls_init)))
-    return error;
-
   if (tls_init_ca_chain ())
     {
       clib_warning ("failed to initialize TLS CA chain");
@@ -667,7 +663,12 @@ tls_mbedtls_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (tls_mbedtls_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (tls_mbedtls_init) =
+{
+  .runs_after = VLIB_INITS("tls_init"),
+};
+/* *INDENT-ON* */
 
 /* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () = {
index f6de0e0..4d4c4c3 100644 (file)
@@ -835,14 +835,10 @@ tls_openssl_init (vlib_main_t * vm)
 {
   vlib_thread_main_t *vtm = vlib_get_thread_main ();
   openssl_main_t *om = &openssl_main;
-  clib_error_t *error;
   u32 num_threads;
 
   num_threads = 1 /* main thread */  + vtm->n_threads;
 
-  if ((error = vlib_call_init_function (vm, tls_init)))
-    return error;
-
   SSL_library_init ();
   SSL_load_error_strings ();
 
@@ -864,6 +860,12 @@ tls_openssl_init (vlib_main_t * vm)
 
   return 0;
 }
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (tls_openssl_init) =
+{
+  .runs_after = VLIB_INITS("tls_init"),
+};
+/* *INDENT-ON* */
 
 #ifdef HAVE_OPENSSL_ASYNC
 static clib_error_t *
@@ -938,9 +940,6 @@ VLIB_CLI_COMMAND (tls_openssl_set_command, static) =
 /* *INDENT-ON* */
 #endif
 
-
-VLIB_INIT_FUNCTION (tls_openssl_init);
-
 /* *INDENT-OFF* */
 VLIB_PLUGIN_REGISTER () = {
     .version = VPP_BUILD_VER,
index 8d47845..8010e9e 100644 (file)
  */
 
 #include <vlib/vlib.h>
+#include <vppinfra/ptclosure.h>
+
+/**
+ * @file
+ * @brief Init function ordering and execution implementation
+ * Topological sort for all classes of init functions, and
+ * a relatively simple API routine to invoke them.
+ */
+
+/*? %%clicmd:group_label Init functions %% ?*/
+
+static int
+comma_split (u8 * s, u8 ** a, u8 ** b)
+{
+  *a = s;
+
+  while (*s && *s != ',')
+    s++;
+
+  if (*s == ',')
+    *s = 0;
+  else
+    return 1;
+
+  *b = (u8 *) (s + 1);
+  return 0;
+}
+
+/**
+ * @brief Topological sorter for init function chains.
+ * @param head [in/out] address of the listhead to be sorted
+ * @returns 0 on success, otherwise a clib_error_t *.
+ */
+
+static clib_error_t *init_exit_function_sort
+  (_vlib_init_function_list_elt_t ** head)
+{
+  uword *index_by_name;
+  uword *reg_by_index;
+  u8 **init_f_names = 0;
+  u8 *init_f_name;
+  char **these_constraints;
+  char *this_constraint_c;
+  u8 **constraints = 0;
+  u8 *constraint_tuple;
+  u8 *this_constraint;
+  char *prev_name;
+  u8 **orig, **closure;
+  uword *p;
+  int i, j, k;
+  u8 *a_name, *b_name;
+  int a_index, b_index;
+  int n_init_fns;
+  u32 *result = 0;
+  _vlib_init_function_list_elt_t *this_reg = 0;
+  hash_pair_t *hp;
+  u8 **keys_to_delete = 0;
+
+  /*
+   * two hash tables: name to index in init_f_names, and
+   * init function registration pointer by index
+   */
+  index_by_name = hash_create_string (0, sizeof (uword));
+  reg_by_index = hash_create (0, sizeof (uword));
+
+  this_reg = *head;
+
+  /* pass 1, collect init fcn names, construct a before b pairs */
+  while (this_reg)
+    {
+      init_f_name = format (0, "%s%c", this_reg->name, 0);
+      hash_set (reg_by_index, vec_len (init_f_names), (uword) this_reg);
+
+      hash_set_mem (index_by_name, init_f_name, vec_len (init_f_names));
+
+      vec_add1 (init_f_names, init_f_name);
+
+      these_constraints = this_reg->runs_before;
+      while (these_constraints && these_constraints[0])
+       {
+         this_constraint_c = these_constraints[0];
+
+         constraint_tuple = format (0, "%s,%s%c", init_f_name,
+                                    this_constraint_c, 0);
+         vec_add1 (constraints, constraint_tuple);
+         these_constraints++;
+       }
+
+      these_constraints = this_reg->runs_after;
+      while (these_constraints && these_constraints[0])
+       {
+         this_constraint_c = these_constraints[0];
+
+         constraint_tuple = format (0, "%s,%s%c",
+                                    this_constraint_c, init_f_name, 0);
+         vec_add1 (constraints, constraint_tuple);
+         these_constraints++;
+       }
+
+      this_reg = this_reg->next_init_function;
+    }
+
+  /*
+   * pass 2: collect "a then b then c then d" constraints.
+   * all init fcns must be known at this point.
+   */
+  this_reg = *head;
+  while (this_reg)
+    {
+      these_constraints = this_reg->init_order;
+
+      prev_name = 0;
+      /* Across the list of constraints */
+      while (these_constraints && these_constraints[0])
+       {
+         this_constraint_c = these_constraints[0];
+         p = hash_get_mem (index_by_name, this_constraint_c);
+         if (p == 0)
+           {
+             clib_warning
+               ("order constraint fcn '%s' not found", this_constraint_c);
+             these_constraints++;
+             continue;
+           }
+
+         if (prev_name == 0)
+           {
+             prev_name = this_constraint_c;
+             these_constraints++;
+             continue;
+           }
+
+         constraint_tuple = format (0, "%s,%s%c", prev_name,
+                                    this_constraint_c, 0);
+         vec_add1 (constraints, constraint_tuple);
+         prev_name = this_constraint_c;
+         these_constraints++;
+       }
+      this_reg = this_reg->next_init_function;
+    }
+
+  n_init_fns = vec_len (init_f_names);
+  orig = clib_ptclosure_alloc (n_init_fns);
+
+  for (i = 0; i < vec_len (constraints); i++)
+    {
+      this_constraint = constraints[i];
+
+      if (comma_split (this_constraint, &a_name, &b_name))
+       return clib_error_return (0, "comma_split failed!");
+
+      p = hash_get_mem (index_by_name, a_name);
+      /*
+       * Note: the next two errors mean that something is
+       * b0rked. As in: if you code "A runs before on B," and you type
+       * B incorrectly, you lose. Nonexistent init functions are tolerated.
+       */
+      if (p == 0)
+       {
+         clib_warning ("init function '%s' not found (before '%s')",
+                       a_name, b_name);
+         continue;
+       }
+      a_index = p[0];
+
+      p = hash_get_mem (index_by_name, b_name);
+      if (p == 0)
+       {
+         clib_warning ("init function '%s' not found (after '%s')",
+                       b_name, a_name);
+         continue;
+       }
+      b_index = p[0];
+
+      /* add a before b to the original set of constraints */
+      orig[a_index][b_index] = 1;
+      vec_free (this_constraint);
+    }
+
+  /* Compute the positive transitive closure of the original constraints */
+  closure = clib_ptclosure (orig);
+
+  /* Compute a partial order across feature nodes, if one exists. */
+again:
+  for (i = 0; i < n_init_fns; i++)
+    {
+      for (j = 0; j < n_init_fns; j++)
+       {
+         if (closure[i][j])
+           goto item_constrained;
+       }
+      /* Item i can be output */
+      vec_add1 (result, i);
+      {
+       for (k = 0; k < n_init_fns; k++)
+         closure[k][i] = 0;
+       /*
+        * Add a "Magic" a before a constraint.
+        * This means we'll never output it again
+        */
+       closure[i][i] = 1;
+       goto again;
+      }
+    item_constrained:
+      ;
+    }
+
+  /* see if we got a partial order... */
+  if (vec_len (result) != n_init_fns)
+    return clib_error_return
+      (0, "Failed to find a suitable init function order!");
+
+  /*
+   * We win.
+   * Bind the index variables, and output the feature node name vector
+   * using the partial order we just computed. Result is in stack
+   * order, because the entry with the fewest constraints (e.g. none)
+   * is output first, etc.
+   * Reset the listhead, and add items in result (aka reverse) order.
+   */
+  *head = 0;
+  for (i = 0; i < n_init_fns; i++)
+    {
+      p = hash_get (reg_by_index, result[i]);
+      ASSERT (p != 0);
+      this_reg = (_vlib_init_function_list_elt_t *) p[0];
+
+      this_reg->next_init_function = *head;
+      *head = this_reg;
+    }
+
+  /* Finally, clean up all the fine data we allocated */
+  /* *INDENT-OFF* */
+  hash_foreach_pair (hp, index_by_name,
+  ({
+    vec_add1 (keys_to_delete, (u8 *)hp->key);
+  }));
+  /* *INDENT-ON* */
+  hash_free (index_by_name);
+  for (i = 0; i < vec_len (keys_to_delete); i++)
+    vec_free (keys_to_delete[i]);
+  vec_free (keys_to_delete);
+  hash_free (reg_by_index);
+  vec_free (result);
+  clib_ptclosure_free (orig);
+  clib_ptclosure_free (closure);
+  return 0;
+}
+
+/**
+ * @brief call a set of init / exit / main-loop enter functions
+ * @param vm vlib_main_t
+ * @param head address of the listhead to sort and then invoke
+ * @returns 0 on success, clib_error_t * on error
+ *
+ * The "init_functions_called" hash supports a subtle mix of procedural
+ * and formally-specified ordering constraints. The following schemes
+ * are *roughly* equivalent:
+ *
+ * static clib_error_t *init_runs_first (vlib_main_t *vm)
+ * {
+ *    clib_error_t *error;
+ *
+ *    ... do some stuff...
+ *
+ *    if ((error = vlib_call_init_function (init_runs_next)))
+ *      return error;
+ *    ...
+ * }
+ * VLIB_INIT_FUNCTION (init_runs_first);
+ *
+ * and
+ *
+ * static clib_error_t *init_runs_first (vlib_main_t *vm)
+ * {
+ *    ... do some stuff...
+ * }
+ * VLIB_INIT_FUNCTION (init_runs_first) =
+ * {
+ *     .runs_before = VLIB_INITS("init_runs_next"),
+ * };
+ *
+ * The first form will [most likely] call "init_runs_next" on the
+ * spot. The second form means that "init_runs_first" runs before
+ * "init_runs_next," possibly much earlier in the sequence.
+ *
+ * Please DO NOT construct sets of init functions where A before B
+ * actually means A *right before* B. It's not necessary - simply combine
+ * A and B - and it leads to hugely annoying debugging exercises.
+ */
 
 clib_error_t *
 vlib_call_init_exit_functions (vlib_main_t * vm,
-                              _vlib_init_function_list_elt_t * head,
+                              _vlib_init_function_list_elt_t ** headp,
                               int call_once)
 {
   clib_error_t *error = 0;
   _vlib_init_function_list_elt_t *i;
 
-  i = head;
+  if ((error = init_exit_function_sort (headp)))
+    return (error);
+
+  i = *headp;
   while (i)
     {
       if (call_once && !hash_get (vm->init_functions_called, i->f))
@@ -73,21 +366,21 @@ vlib_call_all_init_functions (vlib_main_t * vm)
 #undef _
 
   return vlib_call_init_exit_functions
-    (vm, vm->init_function_registrations, 1 /* call_once */ );
+    (vm, &vm->init_function_registrations, 1 /* call_once */ );
 }
 
 clib_error_t *
 vlib_call_all_main_loop_enter_functions (vlib_main_t * vm)
 {
   return vlib_call_init_exit_functions
-    (vm, vm->main_loop_enter_function_registrations, 1 /* call_once */ );
+    (vm, &vm->main_loop_enter_function_registrations, 1 /* call_once */ );
 }
 
 clib_error_t *
 vlib_call_all_main_loop_exit_functions (vlib_main_t * vm)
 {
   return vlib_call_init_exit_functions
-    (vm, vm->main_loop_exit_function_registrations, 1 /* call_once */ );
+    (vm, &vm->main_loop_exit_function_registrations, 1 /* call_once */ );
 }
 
 clib_error_t *
@@ -159,6 +452,204 @@ done:
   return error;
 }
 
+void
+vlib_init_dump (void)
+{
+  vlib_main_t *vm = vlib_get_main ();
+  int i = 0;
+
+  _vlib_init_function_list_elt_t *head, *this;
+  head = vm->init_function_registrations;
+
+  this = head;
+  while (this)
+    {
+      fformat (stdout, "[%d]: %s\n", i++, this->name);
+      this = this->next_init_function;
+    }
+}
+
+static clib_error_t *
+show_init_function_command_fn (vlib_main_t * vm,
+                              unformat_input_t * input,
+                              vlib_cli_command_t * cmd)
+{
+  int which = 1;
+  int verbose = 0;
+  int i, n_init_fns;
+  _vlib_init_function_list_elt_t *head, *this;
+  uword *index_by_name;
+  uword *reg_by_index;
+  u8 **init_f_names = 0;
+  u8 *init_f_name;
+  uword *p;
+  _vlib_init_function_list_elt_t *this_reg = 0;
+  hash_pair_t *hp;
+  u8 **keys_to_delete = 0;
+
+  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (input, "init"))
+       which = 1;
+      else if (unformat (input, "enter"))
+       which = 2;
+      else if (unformat (input, "exit"))
+       which = 3;
+      else if (unformat (input, "verbose %d", &verbose))
+       ;
+      else if (unformat (input, "verbose"))
+       verbose = 1;
+      else
+       break;
+    }
+
+  switch (which)
+    {
+    case 1:
+      head = vm->init_function_registrations;
+      break;
+    case 2:
+      head = vm->main_loop_enter_function_registrations;
+      break;
+    case 3:
+      head = vm->main_loop_exit_function_registrations;
+      break;
+    default:
+      return clib_error_return (0, "BUG");
+    }
+
+  if (verbose == 0)
+    {
+      this = head;
+      i = 0;
+      while (this)
+       {
+         vlib_cli_output (vm, "[%d]: %s", i++, this->name);
+         this = this->next_init_function;
+       }
+      return 0;
+    }
+
+  index_by_name = hash_create_string (0, sizeof (uword));
+  reg_by_index = hash_create (0, sizeof (uword));
+
+  this_reg = head;
+  n_init_fns = 0;
+  /* collect init fcn names */
+  while (this_reg)
+    {
+      init_f_name = format (0, "%s%c", this_reg->name, 0);
+      hash_set (reg_by_index, vec_len (init_f_names), (uword) this_reg);
+
+      hash_set_mem (index_by_name, init_f_name, vec_len (init_f_names));
+      vec_add1 (init_f_names, init_f_name);
+      n_init_fns++;
+      this_reg = this_reg->next_init_function;
+    }
+
+  for (i = 0; i < n_init_fns; i++)
+    {
+      p = hash_get (reg_by_index, i);
+      ASSERT (p != 0);
+      this_reg = (_vlib_init_function_list_elt_t *) p[0];
+      vlib_cli_output (vm, "[%d] %s", i, this_reg->name);
+      {
+       char **runs_before, **runs_after, **init_order;
+       runs_before = this_reg->runs_before;
+       while (runs_before && runs_before[0])
+         {
+           _vlib_init_function_list_elt_t *successor;
+           uword successor_index;
+           p = hash_get_mem (index_by_name, runs_before[0]);
+           if (p == 0)
+             {
+               clib_warning ("couldn't find successor '%s'", runs_before[0]);
+               runs_before++;
+               continue;
+             }
+           successor_index = p[0];
+           p = hash_get (reg_by_index, p[0]);
+           ASSERT (p != 0);
+           successor = (_vlib_init_function_list_elt_t *) p[0];
+           vlib_cli_output (vm, "  before '%s' [%lld]",
+                            successor->name, successor_index);
+           runs_before++;
+         }
+       runs_after = this_reg->runs_after;
+       while (runs_after && runs_after[0])
+         {
+           _vlib_init_function_list_elt_t *predecessor;
+           uword predecessor_index;
+           p = hash_get_mem (index_by_name, runs_after[0]);
+           if (p == 0)
+             {
+               clib_warning ("couldn't find predecessor '%s'",
+                             runs_after[0]);
+               runs_after++;
+               continue;
+             }
+           predecessor_index = p[0];
+           p = hash_get (reg_by_index, p[0]);
+           ASSERT (p != 0);
+           predecessor = (_vlib_init_function_list_elt_t *) p[0];
+           vlib_cli_output (vm, "  after '%s' [%lld]",
+                            predecessor->name, predecessor_index);
+           runs_after++;
+         }
+       init_order = this_reg->init_order;
+       while (init_order && init_order[0])
+         {
+           _vlib_init_function_list_elt_t *inorder;
+           uword inorder_index;
+           p = hash_get_mem (index_by_name, init_order[0]);
+           if (p == 0)
+             {
+               clib_warning ("couldn't find order element'%s'",
+                             init_order[0]);
+               init_order++;
+               continue;
+             }
+           inorder_index = p[0];
+           p = hash_get (reg_by_index, p[0]);
+           ASSERT (p != 0);
+           inorder = (_vlib_init_function_list_elt_t *) p[0];
+           vlib_cli_output (vm, "  in order '%s' [%lld]",
+                            inorder->name, inorder_index);
+           init_order++;
+         }
+      }
+    }
+  /* *INDENT-OFF* */
+  hash_foreach_pair (hp, index_by_name,
+  ({
+    vec_add1 (keys_to_delete, (u8 *)hp->key);
+  }));
+  /* *INDENT-ON* */
+  hash_free (index_by_name);
+  for (i = 0; i < vec_len (keys_to_delete); i++)
+    vec_free (keys_to_delete[i]);
+  vec_free (keys_to_delete);
+  hash_free (reg_by_index);
+
+  return 0;
+}
+
+/*?
+ * Show init function order
+ *
+ * @cliexpar
+ * @cliexstart{show init-function [init | enter | exit] [verbose [nn]]}
+ * @cliexend
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_init_function, static) = {
+  .path = "show init-function",
+  .short_help = "show init-function [init | enter | exit][verbose [nn]]",
+  .function = show_init_function_command_fn,
+};
+/* *INDENT-ON* */
+
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index a936769..6d27114 100644 (file)
@@ -54,6 +54,10 @@ typedef struct _vlib_init_function_list_elt
 {
   struct _vlib_init_function_list_elt *next_init_function;
   vlib_init_function_t *f;
+  char *name;
+  char **runs_before;
+  char **runs_after;
+  char **init_order;
 } _vlib_init_function_list_elt_t;
 
 /* Configuration functions: called with configuration input just before
@@ -116,48 +120,54 @@ typedef struct vlib_config_function_runtime_t
    be called from other modules to resolve init function depend. */
 
 #ifndef CLIB_MARCH_VARIANT
-#define VLIB_DECLARE_INIT_FUNCTION(x, tag)                      \
-vlib_init_function_t * _VLIB_INIT_FUNCTION_SYMBOL (x, tag) = x; \
-static void __vlib_add_##tag##_function_##x (void)              \
-    __attribute__((__constructor__)) ;                          \
-static void __vlib_add_##tag##_function_##x (void)              \
-{                                                               \
- vlib_main_t * vm = vlib_get_main();                            \
- static _vlib_init_function_list_elt_t _vlib_init_function;     \
- _vlib_init_function.next_init_function                         \
-    = 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_DECLARE_INIT_FUNCTION(x, tag)                              \
+vlib_init_function_t * _VLIB_INIT_FUNCTION_SYMBOL (x, tag) = x;         \
+static void __vlib_add_##tag##_function_##x (void)                      \
+    __attribute__((__constructor__)) ;                                  \
+static _vlib_init_function_list_elt_t _vlib_init_function_##tag_##x;    \
+static void __vlib_add_##tag##_function_##x (void)                      \
+{                                                                       \
+ vlib_main_t * vm = vlib_get_main();                                    \
+ _vlib_init_function_##tag_##x.next_init_function                       \
+    = vm->tag##_function_registrations;                                 \
+  vm->tag##_function_registrations = &_vlib_init_function_##tag_##x;    \
+ _vlib_init_function_##tag_##x.f = &x;                                  \
+ _vlib_init_function_##tag_##x.name = #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 *this, *prev;                          \
+  this = vm->tag##_function_registrations;                              \
+  if (this == 0)                                                       \
+    return;                                                            \
+  if (this->f == &x)                                                   \
+    {                                                                   \
+      vm->tag##_function_registrations = this->next_init_function;     \
+      return;                                                           \
+    }                                                                   \
+  prev = this;                                                         \
+  this = this->next_init_function;                                     \
+  while (this)                                                         \
+    {                                                                   \
+      if (this->f == &x)                                               \
+        {                                                               \
+          prev->next_init_function =                                    \
+            this->next_init_function;                                  \
+          return;                                                       \
+        }                                                               \
+      prev = this;                                                     \
+      this = this->next_init_function;                                  \
+    }                                                                   \
+}                                                                      \
+static _vlib_init_function_list_elt_t _vlib_init_function_##tag_##x
 #else
 /* create unused pointer to silence compiler warnings and get whole
    function optimized out */
 #define VLIB_DECLARE_INIT_FUNCTION(x, tag)                      \
-static __clib_unused void * __clib_unused_##tag##_##x = x;
+static __clib_unused void * __clib_unused_##tag##_##x = x
 #endif
 
 #define VLIB_INIT_FUNCTION(x) VLIB_DECLARE_INIT_FUNCTION(x,init)
@@ -316,8 +326,8 @@ clib_error_t *vlib_call_all_main_loop_enter_functions (struct vlib_main_t
                                                       *vm);
 clib_error_t *vlib_call_all_main_loop_exit_functions (struct vlib_main_t *vm);
 clib_error_t *vlib_call_init_exit_functions (struct vlib_main_t *vm,
-                                            _vlib_init_function_list_elt_t *
-                                            head, int call_once);
+                                            _vlib_init_function_list_elt_t **
+                                            headp, int call_once);
 
 #define foreach_vlib_module_reference          \
   _ (node_cli)                                 \
@@ -327,6 +337,7 @@ clib_error_t *vlib_call_init_exit_functions (struct vlib_main_t *vm,
 #define _(x) void vlib_##x##_reference (void);
 foreach_vlib_module_reference
 #undef _
+#define VLIB_INITS(...)  (char*[]) { __VA_ARGS__, 0}
 #endif /* included_vlib_init_h */
 /*
  * fd.io coding-style-patch-verification: ON
index 8b614c7..20d44cd 100644 (file)
@@ -1449,13 +1449,9 @@ linux_pci_init (vlib_main_t * vm)
 {
   vlib_pci_main_t *pm = &pci_main;
   vlib_pci_addr_t *addr = 0, *addrs;
-  clib_error_t *error;
 
   pm->vlib_main = vm;
 
-  if ((error = vlib_call_init_function (vm, unix_input_init)))
-    return error;
-
   ASSERT (sizeof (vlib_pci_addr_t) == sizeof (u32));
 
   addrs = vlib_pci_get_all_dev_addrs ();
@@ -1471,10 +1467,15 @@ linux_pci_init (vlib_main_t * vm)
     }
   /* *INDENT-ON* */
 
-  return error;
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (linux_pci_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (linux_pci_init) =
+{
+  .runs_after = VLIB_INITS("unix_input_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index d0efbd7..2fc438b 100644 (file)
@@ -407,10 +407,15 @@ linux_vmbus_init (vlib_main_t * vm)
 
   pm->vlib_main = vm;
 
-  return vlib_call_init_function (vm, unix_input_init);
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (linux_vmbus_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (linux_vmbus_init) =
+{
+  .runs_before = VLIB_INITS("unix_input_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index cb1eb5f..6a23bfd 100644 (file)
@@ -1736,7 +1736,7 @@ vlib_worker_thread_fn (void *arg)
     vlib_worker_thread_barrier_check ();
 
   e = vlib_call_init_exit_functions
-    (vm, vm->worker_init_function_registrations, 1 /* call_once */ );
+    (vm, &vm->worker_init_function_registrations, 1 /* call_once */ );
   if (e)
     clib_error_report (e);
 
index 1c1cb1a..43bb206 100644 (file)
@@ -411,10 +411,15 @@ VLIB_INIT_FUNCTION (linux_epoll_input_init);
 static clib_error_t *
 unix_input_init (vlib_main_t * vm)
 {
-  return vlib_call_init_function (vm, linux_epoll_input_init);
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (unix_input_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (unix_input_init) =
+{
+  .runs_before = VLIB_INITS ("linux_epoll_input_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 8c9bc1b..3ec4c34 100755 (executable)
@@ -67,10 +67,15 @@ unix_main_init (vlib_main_t * vm)
 {
   unix_main_t *um = &unix_main;
   um->vlib_main = vm;
-  return vlib_call_init_function (vm, unix_input_init);
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (unix_main_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (unix_main_init) =
+{
+  .runs_before = VLIB_INITS ("unix_input_init"),
+};
+/* *INDENT-ON* */
 
 static int
 unsetup_signal_handlers (int sig)
index ea395ec..eadf5f1 100644 (file)
@@ -30,11 +30,10 @@ vlib_vmbus_addr_t * __attribute__ ((weak)) vlib_vmbus_get_all_dev_addrs ()
   return NULL;
 }
 
-
 clib_error_t *
 vmbus_bus_init (vlib_main_t * vm)
 {
-  return vlib_call_init_function (vm, vmbus_bus_init);
+  return 0;
 }
 
 VLIB_INIT_FUNCTION (vmbus_bus_init);
index 9fc26b9..10425dd 100644 (file)
@@ -954,8 +954,10 @@ vlibmemory_init (vlib_main_t * vm)
 {
   api_main_t *am = &api_main;
   svm_map_region_args_t _a, *a = &_a;
-  clib_error_t *error;
   u8 *remove_path1, *remove_path2;
+  void vlibsocket_reference (void);
+
+  vlibsocket_reference ();
 
   /*
    * By popular request / to avoid support fires, remove any old api segment
@@ -993,9 +995,7 @@ vlibmemory_init (vlib_main_t * vm)
 
   svm_region_init_args (a);
 
-  error = vlib_call_init_function (vm, vlibsocket_init);
-
-  return error;
+  return 0;
 }
 
 void
index f0c7f1f..31c1ff9 100644 (file)
@@ -805,14 +805,11 @@ socksvr_config (vlib_main_t * vm, unformat_input_t * input)
 
 VLIB_CONFIG_FUNCTION (socksvr_config, "socksvr");
 
-clib_error_t *
-vlibsocket_init (vlib_main_t * vm)
+void
+vlibsocket_reference ()
 {
-  return 0;
 }
 
-VLIB_INIT_FUNCTION (vlibsocket_init);
-
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 7763a88..73dd5bd 100644 (file)
@@ -306,7 +306,7 @@ vl_api_clnt_process (vlib_main_t * vm, vlib_node_runtime_t * node,
   q = shm->vl_input_queue;
 
   e = vlib_call_init_exit_functions
-    (vm, vm->api_init_function_registrations, 1 /* call_once */ );
+    (vm, &vm->api_init_function_registrations, 1 /* call_once */ );
   if (e)
     clib_error_report (e);
 
index b7ff64d..2d787d4 100644 (file)
@@ -280,16 +280,16 @@ const static adj_delegate_vft_t adj_delegate_vft = {
 static clib_error_t *
 adj_bfd_main_init (vlib_main_t * vm)
 {
-    clib_error_t * error = NULL;
-
-    if ((error = vlib_call_init_function (vm, bfd_main_init)))
-        return (error);
-
     bfd_register_listener(adj_bfd_notify);
 
     adj_delegate_register_type (ADJ_DELEGATE_BFD, &adj_delegate_vft);
 
-    return (error);
+    return (0);
 }
 
-VLIB_INIT_FUNCTION (adj_bfd_main_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (adj_bfd_main_init)=
+{
+    .runs_after = VLIB_INITS("bfd_main_init"),
+};
+/* *INDENT-ON* */
index 553c353..7f5a926 100644 (file)
@@ -251,10 +251,6 @@ clib_error_t *
 in_out_acl_init (vlib_main_t * vm)
 {
   in_out_acl_main_t *am = &in_out_acl_main;
-  clib_error_t *error = 0;
-
-  if ((error = vlib_call_init_function (vm, ip_in_out_acl_init)))
-    return error;
 
   am->vlib_main = vm;
   am->vnet_main = vnet_get_main ();
@@ -262,8 +258,12 @@ in_out_acl_init (vlib_main_t * vm)
 
   return 0;
 }
-
-VLIB_INIT_FUNCTION (in_out_acl_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (in_out_acl_init) =
+{
+  .runs_after = VLIB_INITS("ip_in_out_acl_init"),
+};
+/* *INDENT-ON* */
 
 uword
 unformat_acl_type (unformat_input_t * input, va_list * args)
index 700bd73..edd0985 100644 (file)
@@ -29,7 +29,7 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
 
   clib_memset (data, 0, sizeof(*data));
 
-  /* 
+  /*
    * Ignore local interface, pg interfaces. $$$ need a #define for the
    * first "real" interface. The answer is 5 at the moment.
    */
@@ -41,7 +41,7 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
     {
       ccm = &cm->cop_config_mains[address_family];
 
-      /* 
+      /*
        * Once-only code to initialize the per-address-family
        * cop feature subgraphs.
        * Since the (single) start-node, cop-input, must be able
@@ -60,8 +60,8 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
                   [IP4_RX_COP_WHITELIST] = "ip4-cop-whitelist",
                   [IP4_RX_COP_INPUT] = "ip4-input",
                 };
-                
-                vnet_config_init (vm, &ccm->config_main, 
+
+                vnet_config_init (vm, &ccm->config_main,
                                   start_nodes, ARRAY_LEN(start_nodes),
                                   feature_nodes, ARRAY_LEN(feature_nodes));
               }
@@ -73,7 +73,7 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
                   [IP6_RX_COP_WHITELIST] = "ip6-cop-whitelist",
                   [IP6_RX_COP_INPUT] = "ip6-input",
                 };
-                vnet_config_init (vm, &ccm->config_main, 
+                vnet_config_init (vm, &ccm->config_main,
                                   start_nodes, ARRAY_LEN(start_nodes),
                                   feature_nodes, ARRAY_LEN(feature_nodes));
               }
@@ -86,7 +86,7 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
                   [DEFAULT_RX_COP_WHITELIST] = "default-cop-whitelist",
                   [DEFAULT_RX_COP_INPUT] = "ethernet-input",
                 };
-                vnet_config_init (vm, &ccm->config_main, 
+                vnet_config_init (vm, &ccm->config_main,
                                   start_nodes, ARRAY_LEN(start_nodes),
                                   feature_nodes, ARRAY_LEN(feature_nodes));
               }
@@ -109,15 +109,15 @@ cop_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
         default_next = IP6_RX_COP_INPUT;
       else
         default_next = DEFAULT_RX_COP_INPUT;
-        
+
       if (is_add)
         ci = vnet_config_add_feature (vm, &ccm->config_main,
-                                      ci, 
+                                      ci,
                                       default_next,
                                       data, sizeof(*data));
       else
         ci = vnet_config_del_feature (vm, &ccm->config_main,
-                                      ci, 
+                                      ci,
                                       default_next,
                                       data, sizeof(*data));
 
@@ -132,13 +132,6 @@ static clib_error_t *
 cop_init (vlib_main_t *vm)
 {
   cop_main_t * cm = &cop_main;
-  clib_error_t * error;
-
-  if ((error = vlib_call_init_function (vm, ip4_whitelist_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip6_whitelist_init)))
-    return error;
 
   cm->vlib_main = vm;
   cm->vnet_main = vnet_get_main();
@@ -146,7 +139,12 @@ cop_init (vlib_main_t *vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (cop_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (cop_init) =
+{
+  .runs_after = VLIB_INITS ("ip4_whitelist_init", "ip6_whitelist_init"),
+};
+/* *INDENT-ON* */
 
 int cop_interface_enable_disable (u32 sw_if_index, int enable_disable)
 {
@@ -159,11 +157,11 @@ int cop_interface_enable_disable (u32 sw_if_index, int enable_disable)
   sw = vnet_get_sw_interface (cm->vnet_main, sw_if_index);
   if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
-  
-  /* 
+
+  /*
    * Redirect pkts from the driver to the cop node.
    * Returns VNET_API_ERROR_UNIMPLEMENTED if the h/w driver
-   * doesn't implement the API. 
+   * doesn't implement the API.
    *
    * Node_index = ~0 => shut off redirection
    */
@@ -180,7 +178,7 @@ cop_enable_disable_command_fn (vlib_main_t * vm,
   cop_main_t * cm = &cop_main;
   u32 sw_if_index = ~0;
   int enable_disable = 1;
-    
+
   int rv;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
@@ -195,7 +193,7 @@ cop_enable_disable_command_fn (vlib_main_t * vm,
 
   if (sw_if_index == ~0)
     return clib_error_return (0, "Please specify an interface...");
-    
+
   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
 
   switch(rv) {
@@ -203,7 +201,7 @@ cop_enable_disable_command_fn (vlib_main_t * vm,
     break;
 
   case VNET_API_ERROR_INVALID_SW_IF_INDEX:
-    return clib_error_return 
+    return clib_error_return
       (0, "Invalid interface, only works on physical ports");
     break;
 
@@ -220,7 +218,7 @@ cop_enable_disable_command_fn (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (cop_interface_command, static) = {
     .path = "cop interface",
-    .short_help = 
+    .short_help =
     "cop interface <interface-name> [disable]",
     .function = cop_enable_disable_command_fn,
 };
@@ -246,10 +244,10 @@ int cop_whitelist_enable_disable (cop_whitelist_enable_disable_args_t *a)
    */
 
   for (address_family = VNET_COP_IP4; address_family < VNET_N_COPS;
-       address_family++) 
+       address_family++)
     {
       ccm = &cm->cop_config_mains[address_family];
-    
+
       switch(address_family)
         {
         case VNET_COP_IP4:
@@ -267,7 +265,7 @@ int cop_whitelist_enable_disable (cop_whitelist_enable_disable_args_t *a)
                 continue;
             }
           break;
-              
+
         case VNET_COP_IP6:
           is_add = (a->ip6 != 0);
           next_to_add_del = IP6_RX_COP_WHITELIST;
@@ -287,7 +285,7 @@ int cop_whitelist_enable_disable (cop_whitelist_enable_disable_args_t *a)
           is_add = (a->default_cop != 0);
           next_to_add_del = DEFAULT_RX_COP_WHITELIST;
           break;
-        
+
         default:
           clib_warning ("BUG");
         }
@@ -343,7 +341,7 @@ cop_whitelist_enable_disable_command_fn (vlib_main_t * vm,
 
   if (sw_if_index == ~0)
     return clib_error_return (0, "Please specify an interface...");
-    
+
   a->sw_if_index = sw_if_index;
   a->ip4 = ip4;
   a->ip6 = ip6;
@@ -357,12 +355,12 @@ cop_whitelist_enable_disable_command_fn (vlib_main_t * vm,
     break;
 
   case VNET_API_ERROR_INVALID_SW_IF_INDEX:
-    return clib_error_return 
+    return clib_error_return
       (0, "Invalid interface, only works on physical ports");
     break;
 
   case VNET_API_ERROR_NO_SUCH_FIB:
-    return clib_error_return 
+    return clib_error_return
       (0, "Invalid fib");
     break;
 
@@ -380,8 +378,7 @@ cop_whitelist_enable_disable_command_fn (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (cop_whitelist_command, static) = {
     .path = "cop whitelist",
-    .short_help = 
+    .short_help =
     "cop whitelist <interface-name> [ip4][ip6][default][fib-id <NN>][disable]",
     .function = cop_whitelist_enable_disable_command_fn,
 };
-
index 1d52b42..72b71f9 100644 (file)
@@ -953,14 +953,9 @@ vhost_user_socksvr_accept_ready (clib_file_t * uf)
 static clib_error_t *
 vhost_user_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
   vhost_user_main_t *vum = &vhost_user_main;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
 
-  error = vlib_call_init_function (vm, ip4_init);
-  if (error)
-    return error;
-
   vum->log_default = vlib_log_register_class ("vhost-user", 0);
 
   vum->coalesce_frames = 32;
@@ -983,7 +978,12 @@ vhost_user_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (vhost_user_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (vhost_user_init) =
+{
+  .runs_after = VLIB_INITS("ip4_init"),
+};
+/* *INDENT-ON* */
 
 static uword
 vhost_user_send_interrupt_process (vlib_main_t * vm,
index df78456..13ae37a 100644 (file)
@@ -16,7 +16,7 @@
  * @brief
  * A Data-Path Object is an object that represents actions that are
  * applied to packets are they are switched through VPP.
- * 
+ *
  * The DPO is a base class that is specialised by other objects to provide
  * concrete actions
  *
@@ -267,10 +267,10 @@ dpo_copy (dpo_id_t *dst,
      * the destination is written in a single u64 write - hence atomically w.r.t
      * any packets inflight.
      */
-    *((u64*)dst) = *(u64*)src; 
+    *((u64*)dst) = *(u64*)src;
 
     dpo_lock(dst);
-    dpo_unlock(&tmp);    
+    dpo_unlock(&tmp);
 }
 
 int
@@ -592,7 +592,12 @@ dpo_module_init (vlib_main_t * vm)
     return (NULL);
 }
 
-VLIB_INIT_FUNCTION(dpo_module_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION(dpo_module_init) =
+{
+    .runs_before = VLIB_INITS ("ip_main_init"),
+};
+/* *INDENT-ON* */
 
 static clib_error_t *
 dpo_memory_show (vlib_main_t * vm,
index 12c3fa4..f294893 100644 (file)
@@ -1761,12 +1761,8 @@ ethernet_arp_init (vlib_main_t * vm)
 {
   ethernet_arp_main_t *am = &ethernet_arp_main;
   ip4_main_t *im = &ip4_main;
-  clib_error_t *error;
   pg_node_t *pn;
 
-  if ((error = vlib_call_init_function (vm, ethernet_init)))
-    return error;
-
   ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
 
   pn = pg_get_node (arp_input_node.index);
@@ -1809,8 +1805,12 @@ ethernet_arp_init (vlib_main_t * vm)
 
   return 0;
 }
-
-VLIB_INIT_FUNCTION (ethernet_arp_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ethernet_arp_init) =
+{
+  .runs_after = VLIB_INITS("ethernet_init"),
+};
+/* *INDENT-ON* */
 
 static void
 arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
index 94322a7..344705b 100644 (file)
@@ -544,6 +544,7 @@ u8 *ethernet_build_rewrite (vnet_main_t * vnm,
                            vnet_link_t link_type, const void *dst_address);
 const u8 *ethernet_ip4_mcast_dst_addr (void);
 const u8 *ethernet_ip6_mcast_dst_addr (void);
+void ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em);
 
 extern vlib_node_registration_t ethernet_input_node;
 
index 5d10c60..9fd95f1 100644 (file)
@@ -83,14 +83,6 @@ static clib_error_t *
 ethernet_init (vlib_main_t * vm)
 {
   ethernet_main_t *em = &ethernet_main;
-  clib_error_t *error;
-
-  /*
-   * Set up the L2 path now, or we'll wipe out the L2 ARP
-   * registration set up by ethernet_arp_init.
-   */
-  if ((error = vlib_call_init_function (vm, l2_init)))
-    return error;
 
   em->vlib_main = vm;
 
@@ -101,17 +93,28 @@ ethernet_init (vlib_main_t * vm)
 #include "types.def"
 #undef ethernet_type
 
-  if ((error = vlib_call_init_function (vm, llc_init)))
-    return error;
-  if ((error = vlib_call_init_function (vm, ethernet_input_init)))
-    return error;
-  if ((error = vlib_call_init_function (vm, vnet_feature_init)))
-    return error;
-
+  /*
+   * ethernet_input_init is effectively part of this function.
+   * Simply ensuring that it happens after we set up the hash tables
+   * is not sufficient.
+   */
+  ethernet_input_init (vm, em);
   return 0;
 }
 
-VLIB_INIT_FUNCTION (ethernet_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ethernet_init) =
+{
+  /*
+   * Set up the L2 path before ethernet_init, or we'll wipe out the L2 ARP
+   * registration set up by ethernet_arp_init.
+   */
+  .init_order = VLIB_INITS("l2_init",
+                           "ethernet_init",
+                           "llc_init",
+                           "vnet_feature_init"),
+};
+/* *INDENT-ON* */
 
 ethernet_main_t *
 ethernet_get_main (vlib_main_t * vm)
index 87c447f..286ec3c 100755 (executable)
@@ -2025,11 +2025,9 @@ next_by_ethertype_register (next_by_ethertype_t * l3_next,
   return 0;
 }
 
-
-static clib_error_t *
-ethernet_input_init (vlib_main_t * vm)
+void
+ethernet_input_init (vlib_main_t * vm, ethernet_main_t * em)
 {
-  ethernet_main_t *em = &ethernet_main;
   __attribute__ ((unused)) vlan_table_t *invalid_vlan_table;
   __attribute__ ((unused)) qinq_table_t *invalid_qinq_table;
 
@@ -2048,12 +2046,8 @@ ethernet_input_init (vlib_main_t * vm)
   pool_get (em->vlan_pool, invalid_vlan_table);        // first id = 0
   // The first qinq pool will always be reserved for an invalid table
   pool_get (em->qinq_pool, invalid_qinq_table);        // first id = 0
-
-  return 0;
 }
 
-VLIB_INIT_FUNCTION (ethernet_input_init);
-
 void
 ethernet_register_input_type (vlib_main_t * vm,
                              ethernet_type_t type, u32 node_index)
index 413f93e..28e18dd 100644 (file)
 static clib_error_t *
 fib_module_init (vlib_main_t * vm)
 {
-    clib_error_t * error;
-
-    if ((error = vlib_call_init_function (vm, dpo_module_init)))
-       return (error);
-    if ((error = vlib_call_init_function (vm, adj_module_init)))
-       return (error);
-
     fib_entry_module_init();
     fib_entry_src_module_init();
     fib_path_module_init();
@@ -38,4 +31,9 @@ fib_module_init (vlib_main_t * vm)
     return (NULL);
 }
 
-VLIB_INIT_FUNCTION (fib_module_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (fib_module_init) =
+{
+    .runs_after = VLIB_INITS("dpo_module_init", "adj_module_init"),
+};
+/* *INDENT-ON* */
index ae7ceec..f785ba2 100644 (file)
@@ -183,14 +183,14 @@ fib_bfd_notify (bfd_listen_event_e event,
 static clib_error_t *
 fib_bfd_main_init (vlib_main_t * vm)
 {
-    clib_error_t * error = NULL;
-
-    if ((error = vlib_call_init_function (vm, bfd_main_init)))
-        return (error);
-
     bfd_register_listener(fib_bfd_notify);
 
-    return (error);
+    return (NULL);
 }
 
-VLIB_INIT_FUNCTION (fib_bfd_main_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (fib_bfd_main_init) =
+{
+    .runs_after = VLIB_INITS("bfd_main_init"),
+};
+/* *INDENT-ON* */
index 638cbd1..b3ab90d 100644 (file)
@@ -101,50 +101,28 @@ do {                                              \
       }
   }
 
-  if ((error = vlib_call_init_function (vm, vnet_main_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip4_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip6_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, icmp4_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, icmp6_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, udp_local_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, udp_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip_classify_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, in_out_acl_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, policer_classify_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, flow_classify_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, dns_init)))
-    return error;
-
   return error;
 }
 
-VLIB_INIT_FUNCTION (ip_main_init);
-
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (ip_main_init) =
+{
+  .init_order =
+  VLIB_INITS ("vnet_main_init",
+              "ip4_init",
+              "ip6_init",
+              "icmp4_init",
+              "icmp6_init",
+              "ip6_hop_by_hop_init",
+              "udp_local_init",
+              "udp_init",
+              "ip_classify_init",
+              "in_out_acl_init",
+              "policer_classify_init",
+              "flow_classify_init",
+              "dns_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 103392a..d904479 100644 (file)
@@ -607,7 +607,7 @@ flow_report_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (flow_report_init)
+VLIB_INIT_FUNCTION (flow_report_init);
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 7361e8e..1b53e4d 100644 (file)
@@ -592,7 +592,7 @@ lisp_gpe_adj_module_init (vlib_main_t * vm)
   return (NULL);
 }
 
-VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init)
+VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init);
 /*
  * fd.io coding-style-patch-verification: ON
  *
index ff85e3d..ab0f823 100644 (file)
@@ -74,31 +74,9 @@ clib_error_t *
 vnet_main_init (vlib_main_t * vm)
 {
   vnet_main_t *vnm = vnet_get_main ();
-  clib_error_t *error;
   u32 hw_if_index;
   vnet_hw_interface_t *hw;
 
-  if ((error = vlib_call_init_function (vm, vnet_interface_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, fib_module_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, mfib_module_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip_main_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
-    return error;
-
-  if ((error = vlib_call_init_function (vm, mpls_init)))
-    return error;
-
   vnm->vlib_main = vm;
 
   hw_if_index = vnet_register_interface
@@ -117,7 +95,20 @@ vnet_main_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (vnet_main_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (vnet_main_init)=
+{
+  .init_order = VLIB_INITS("vnet_interface_init",
+                           "ethernet_init",
+                           "fib_module_init",
+                           "mfib_module_init",
+                           "ip_main_init",
+                           "ip4_lookup_init",
+                           "ip6_lookup_init",
+                           "mpls_init",
+                           "vnet_main_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 1dd5e32..37fa1ae 100644 (file)
@@ -50,8 +50,8 @@ format_mpls_input_trace (u8 * s, va_list * args)
 #define _(a,b) if (t->next_index == MPLS_INPUT_NEXT_##a) next_name = b;
   foreach_mpls_input_next;
 #undef _
-  
-  s = format (s, "MPLS: next %s[%d]  label %d ttl %d exp %d", 
+
+  s = format (s, "MPLS: next %s[%d]  label %d ttl %d exp %d",
               next_name, t->next_index,
              vnet_mpls_uc_get_label(label),
              vnet_mpls_uc_get_ttl(label),
@@ -209,9 +209,9 @@ mpls_input_inline (vlib_main_t * vm,
               vlib_increment_simple_counter (cm, thread_index, sw_if_index0, 1);
             }
 
-          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
+          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
             {
-              mpls_input_trace_t *tr = vlib_add_trace (vm, node, 
+              mpls_input_trace_t *tr = vlib_add_trace (vm, node,
                                                       b0, sizeof (*tr));
               tr->next_index = next0;
               tr->label_net_byte_order = *(u32*)h0;
@@ -278,16 +278,15 @@ mpls_setup_nodes (vlib_main_t * vm)
 
 static clib_error_t * mpls_input_init (vlib_main_t * vm)
 {
-  clib_error_t * error; 
-
-  error = vlib_call_init_function (vm, mpls_init);
-  if (error)
-    clib_error_report (error);
-
   mpls_setup_nodes (vm);
 
   return 0;
 }
 
-VLIB_INIT_FUNCTION (mpls_input_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (mpls_input_init) =
+{
+  .runs_after = VLIB_INITS("mpls_init"),
+};
+/* *INDENT-ON* */
 #endif /* CLIB_MARCH_VARIANT */
index d5166d9..81bdb8b 100644 (file)
@@ -395,17 +395,9 @@ udp_init (vlib_main_t * vm)
   ip_main_t *im = &ip_main;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   u32 num_threads;
-  clib_error_t *error = 0;
   ip_protocol_info_t *pi;
   int i;
 
-  if ((error = vlib_call_init_function (vm, ip_main_init)))
-    return error;
-  if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
-    return error;
-  if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
-    return error;
-
   /*
    * Registrations
    */
@@ -443,10 +435,17 @@ udp_init (vlib_main_t * vm)
        clib_spinlock_init (&um->peekers_readers_locks[i]);
        clib_spinlock_init (&um->peekers_write_locks[i]);
       }
-  return error;
+  return 0;
 }
 
-VLIB_INIT_FUNCTION (udp_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (udp_init) =
+{
+  .runs_after = VLIB_INITS("ip_main_init", "ip4_lookup_init",
+                           "ip6_lookup_init"),
+};
+/* *INDENT-ON* */
+
 
 static clib_error_t *
 show_udp_punt_fn (vlib_main_t * vm, unformat_input_t * input,
index 103b649..9d6f899 100644 (file)
@@ -1011,7 +1011,6 @@ VNET_DEVICE_CLASS (tuntap_dev_class,static) = {
 static clib_error_t *
 tuntap_init (vlib_main_t * vm)
 {
-  clib_error_t *error;
   ip4_main_t *im4 = &ip4_main;
   ip6_main_t *im6 = &ip6_main;
   ip4_add_del_interface_address_callback_t cb4;
@@ -1019,10 +1018,6 @@ tuntap_init (vlib_main_t * vm)
   tuntap_main_t *tm = &tuntap_main;
   vlib_thread_main_t *m = vlib_get_thread_main ();
 
-  error = vlib_call_init_function (vm, ip4_init);
-  if (error)
-    return error;
-
   mhash_init (&tm->subif_mhash, sizeof (u32), sizeof (subif_address_t));
 
   cb4.function = tuntap_ip4_add_del_interface_address;
@@ -1038,7 +1033,12 @@ tuntap_init (vlib_main_t * vm)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (tuntap_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (tuntap_init) =
+{
+  .runs_after = VLIB_INITS("ip4_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index e39c26f..001de73 100644 (file)
@@ -1144,14 +1144,10 @@ clib_error_t *
 vxlan_gbp_init (vlib_main_t * vm)
 {
   vxlan_gbp_main_t *vxm = &vxlan_gbp_main;
-  clib_error_t *error;
 
   vxm->vnet_main = vnet_get_main ();
   vxm->vlib_main = vm;
 
-  if ((error = vlib_call_init_function (vm, punt_init)))
-    return (error);
-
   /* initialize the ip6 hash */
   clib_bihash_init_16_8 (&vxm->vxlan4_gbp_tunnel_by_key, "vxlan4-gbp",
                         VXLAN_GBP_HASH_NUM_BUCKETS,
@@ -1175,10 +1171,15 @@ vxlan_gbp_init (vlib_main_t * vm)
                          "VXLAN-GBP-no-such-v6-tunnel",
                          &vxm->punt_no_such_tunnel[FIB_PROTOCOL_IP6]);
 
-  return (error);
+  return (0);
 }
 
-VLIB_INIT_FUNCTION (vxlan_gbp_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (vxlan_gbp_init) =
+{
+  .runs_after = VLIB_INITS("punt_init"),
+};
+/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON
index 300cfe7..bb2ffad 100644 (file)
@@ -680,11 +680,6 @@ static clib_error_t *
 statseg_init (vlib_main_t * vm)
 {
   stat_segment_main_t *sm = &stat_segment_main;
-  clib_error_t *error;
-
-  /* dependent on unix_input_init */
-  if ((error = vlib_call_init_function (vm, unix_input_init)))
-    return error;
 
   if (sm->socket_name)
     stats_segment_socket_init ();
@@ -692,6 +687,14 @@ statseg_init (vlib_main_t * vm)
   return 0;
 }
 
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (statseg_init) =
+{
+  .runs_after = VLIB_INITS("unix_input_init"),
+};
+/* *INDENT-ON* */
+
+
 clib_error_t *
 stat_segment_register_gauge (u8 * name, stat_segment_update_fn update_fn,
                             u32 caller_index)
@@ -832,7 +835,6 @@ statseg_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
   return 0;
 }
 
-VLIB_INIT_FUNCTION (statseg_init);
 VLIB_EARLY_CONFIG_FUNCTION (statseg_config, "statseg");
 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (statseg_sw_interface_add_del);