+/* Built-in ip4 unicast rx feature path definition */
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = {
+ .node_name = "ip4-inacl",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-rx", 0},
+ .feature_index = &ip4_main.ip4_unicast_rx_feature_check_access,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_1, static) = {
+ .node_name = "ip4-source-check-via-rx",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-any", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_rx_feature_source_reachable_via_rx,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_2, static) = {
+ .node_name = "ip4-source-check-via-any",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-policer-classify", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_rx_feature_source_reachable_via_any,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_and_port_range_check_rx, static) = {
+ .node_name = "ip4-source-and-port-range-check-rx",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-policer-classify", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_rx_feature_source_and_port_range_check,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_policer_classify, static) = {
+ .node_name = "ip4-policer-classify",
+ .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip4", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_rx_feature_policer_classify,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_ipsec, static) = {
+ .node_name = "ipsec-input-ip4",
+ .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip4", 0},
+ .feature_index = &ip4_main.ip4_unicast_rx_feature_ipsec,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_vpath, static) = {
+ .node_name = "vpath-input-ip4",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-lookup", 0},
+ .feature_index = &ip4_main.ip4_unicast_rx_feature_vpath,
+};
+
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_lookup, static) = {
+ .node_name = "ip4-lookup",
+ .runs_before = 0, /* not before any other features */
+ .feature_index = &ip4_main.ip4_unicast_rx_feature_lookup,
+};
+
+/* Built-in ip4 multicast rx feature path definition */
+VNET_IP4_MULTICAST_FEATURE_INIT (ip4_vpath_mc, static) = {
+ .node_name = "vpath-input-ip4",
+ .runs_before = ORDER_CONSTRAINTS {"ip4-lookup-multicast", 0},
+ .feature_index = &ip4_main.ip4_multicast_rx_feature_vpath,
+};
+
+VNET_IP4_MULTICAST_FEATURE_INIT (ip4_lookup_mc, static) = {
+ .node_name = "ip4-lookup-multicast",
+ .runs_before = 0, /* not before any other features */
+ .feature_index = &ip4_main.ip4_multicast_rx_feature_lookup,
+};
+
+static char * rx_feature_start_nodes[] =
+ { "ip4-input", "ip4-input-no-checksum"};
+
+static char * tx_feature_start_nodes[] =
+{ "ip4-rewrite-transit"};
+
+/* Source and port-range check ip4 tx feature path definition */
+VNET_IP4_TX_FEATURE_INIT (ip4_source_and_port_range_check_tx, static) = {
+ .node_name = "ip4-source-and-port-range-check-tx",
+ .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_tx_feature_source_and_port_range_check,
+
+};
+
+/* Built-in ip4 tx feature path definition */
+VNET_IP4_TX_FEATURE_INIT (interface_output, static) = {
+ .node_name = "interface-output",
+ .runs_before = 0, /* not before any other features */
+ .feature_index = &ip4_main.ip4_tx_feature_interface_output,
+};
+
+
+static clib_error_t *
+ip4_feature_init (vlib_main_t * vm, ip4_main_t * im)
+{
+ ip_lookup_main_t * lm = &im->lookup_main;
+ clib_error_t * error;
+ vnet_cast_t cast;
+ ip_config_main_t * cm;
+ vnet_config_main_t * vcm;
+ char **feature_start_nodes;
+ int feature_start_len;
+
+ for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
+ {
+ cm = &lm->feature_config_mains[cast];
+ vcm = &cm->config_main;
+
+ if (cast < VNET_IP_TX_FEAT)
+ {
+ feature_start_nodes = rx_feature_start_nodes;
+ feature_start_len = ARRAY_LEN(rx_feature_start_nodes);
+ }
+ else
+ {
+ feature_start_nodes = tx_feature_start_nodes;
+ feature_start_len = ARRAY_LEN(tx_feature_start_nodes);
+ }
+
+ if ((error = ip_feature_init_cast (vm, cm, vcm,
+ feature_start_nodes,
+ feature_start_len,
+ cast,
+ 1 /* is_ip4 */)))
+ return error;
+ }
+
+ return 0;
+}
+