diff options
-rw-r--r-- | plugins/ila-plugin/ila/ila.c | 11 | ||||
-rw-r--r-- | plugins/snat-plugin/snat/out2in.c | 2 | ||||
-rw-r--r-- | plugins/snat-plugin/snat/snat.c | 8 | ||||
-rw-r--r-- | vnet/vnet/classify/input_acl.c | 2 | ||||
-rw-r--r-- | vnet/vnet/classify/policer_classify.c | 2 | ||||
-rw-r--r-- | vnet/vnet/ip/ip.h | 6 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4.h | 41 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4_forward.c | 199 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4_input.c | 18 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4_source_and_port_range_check.c | 263 | ||||
-rw-r--r-- | vnet/vnet/ip/ip4_source_check.c | 4 | ||||
-rw-r--r-- | vnet/vnet/ip/ip6.h | 19 | ||||
-rw-r--r-- | vnet/vnet/ip/ip6_forward.c | 181 | ||||
-rw-r--r-- | vnet/vnet/ip/ip6_input.c | 12 | ||||
-rw-r--r-- | vnet/vnet/ip/ip_feature_registration.c | 46 | ||||
-rw-r--r-- | vnet/vnet/ip/ip_feature_registration.h | 5 | ||||
-rw-r--r-- | vnet/vnet/ip/ip_init.c | 22 | ||||
-rw-r--r-- | vnet/vnet/ip/lookup.h | 10 | ||||
-rw-r--r-- | vnet/vnet/ipsec/ipsec.c | 4 | ||||
-rw-r--r-- | vnet/vnet/ipsec/ipsec_input.c | 4 | ||||
-rw-r--r-- | vnet/vnet/l2tp/decap.c | 3 | ||||
-rw-r--r-- | vnet/vnet/l2tp/l2tp.c | 3 | ||||
-rw-r--r-- | vnet/vnet/vnet.h | 7 | ||||
-rw-r--r-- | vpp/vpp-api/api.c | 12 |
24 files changed, 684 insertions, 200 deletions
diff --git a/plugins/ila-plugin/ila/ila.c b/plugins/ila-plugin/ila/ila.c index 2673c6269d2..99d1db8a047 100644 --- a/plugins/ila-plugin/ila/ila.c +++ b/plugins/ila-plugin/ila/ila.c @@ -421,7 +421,7 @@ ila_sir2ila (vlib_main_t * vm, { ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next, n_left_to_next; ila_main_t *ilm = &ila_main; @@ -592,9 +592,10 @@ VLIB_REGISTER_NODE (ila_sir2ila_node, static) = VNET_IP6_UNICAST_FEATURE_INIT (ila_sir2ila, static) = { - .node_name = "sir-to-ila",.runs_before = - { -"ip6-lookup", 0},.feature_index = &ila_main.ila_sir2ila_feature_index,}; + .node_name = "sir-to-ila", + .runs_before = ORDER_CONSTRAINTS{"ip6-lookup", 0}, + .feature_index = &ila_main.ila_sir2ila_feature_index, +}; int ila_add_del_entry (ila_add_del_entry_args_t * args) @@ -769,7 +770,7 @@ ila_interface (u32 sw_if_index, u8 disable) ila_main_t *ilm = &ila_main; ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; vnet_config_main_t *vcm = &cm->config_main; u32 ci, feature_index; diff --git a/plugins/snat-plugin/snat/out2in.c b/plugins/snat-plugin/snat/out2in.c index 0fa96c97f83..861dae63b0a 100644 --- a/plugins/snat-plugin/snat/out2in.c +++ b/plugins/snat-plugin/snat/out2in.c @@ -163,7 +163,7 @@ snat_out2in_node_fn (vlib_main_t * vm, u32 pkts_processed = 0; snat_main_t * sm = &snat_main; ip_lookup_main_t * lm = sm->ip4_lookup_main; - ip_config_main_t * cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; f64 now = vlib_time_now (vm); from = vlib_frame_vector_args (frame); diff --git a/plugins/snat-plugin/snat/snat.c b/plugins/snat-plugin/snat/snat.c index 3675602e917..f3e278bfad6 100644 --- a/plugins/snat-plugin/snat/snat.c +++ b/plugins/snat-plugin/snat/snat.c @@ -80,12 +80,12 @@ do { \ /* Hook up input features */ VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out, static) = { .node_name = "snat-in2out", - .runs_before = {"snat-out2in", 0}, + .runs_before = (char *[]){"snat-out2in", 0}, .feature_index = &snat_main.rx_feature_in2out, }; VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in, static) = { .node_name = "snat-out2in", - .runs_before = {"ip4-lookup", 0}, + .runs_before = (char *[]){"ip4-lookup", 0}, .feature_index = &snat_main.rx_feature_out2in, }; @@ -257,7 +257,7 @@ vl_api_snat_interface_add_del_feature_t_handler u32 ci; ip4_main_t * im = &ip4_main; ip_lookup_main_t * lm = &im->lookup_main; - ip_config_main_t * rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 feature_index; int rv = 0; @@ -471,7 +471,7 @@ snat_feature_command_fn (vlib_main_t * vm, snat_main_t * sm = &snat_main; ip4_main_t * im = &ip4_main; ip_lookup_main_t * lm = &im->lookup_main; - ip_config_main_t * rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; clib_error_t * error = 0; u32 sw_if_index, ci; u32 feature_index; diff --git a/vnet/vnet/classify/input_acl.c b/vnet/vnet/classify/input_acl.c index fb9a2a46b08..91ae06852d1 100644 --- a/vnet/vnet/classify/input_acl.c +++ b/vnet/vnet/classify/input_acl.c @@ -49,7 +49,7 @@ vnet_inacl_ip_feature_enable (vlib_main_t * vnm, ftype = ip6_main.ip6_unicast_rx_feature_check_access; } - ipcm = &lm->rx_config_mains[VNET_UNICAST]; + ipcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; ci = ipcm->config_index_by_sw_if_index[sw_if_index]; ci = ((feature_enable) diff --git a/vnet/vnet/classify/policer_classify.c b/vnet/vnet/classify/policer_classify.c index c4c44849e1d..e4580a204bb 100644 --- a/vnet/vnet/classify/policer_classify.c +++ b/vnet/vnet/classify/policer_classify.c @@ -44,7 +44,7 @@ vnet_policer_classify_feature_enable (vlib_main_t * vnm, ftype = ip6_main.ip6_unicast_rx_feature_policer_classify; } - ipcm = &lm->rx_config_mains[VNET_UNICAST]; + ipcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; ci = ipcm->config_index_by_sw_if_index[sw_if_index]; ci = (feature_enable ? vnet_config_add_feature : vnet_config_del_feature) diff --git a/vnet/vnet/ip/ip.h b/vnet/vnet/ip/ip.h index c9a82930a67..c5882c58dff 100644 --- a/vnet/vnet/ip/ip.h +++ b/vnet/vnet/ip/ip.h @@ -217,4 +217,10 @@ void ip_del_all_interface_addresses (vlib_main_t *vm, u32 sw_if_index); extern vlib_node_registration_t ip4_inacl_node; extern vlib_node_registration_t ip6_inacl_node; +void +vnet_config_update_tx_feature_count (ip_lookup_main_t * lm, + ip_config_main_t * tx_cm, + u32 sw_if_index, + int is_add); + #endif /* included_ip_main_h */ diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h index 9a54300b257..fc74e9d61ed 100644 --- a/vnet/vnet/ip/ip4.h +++ b/vnet/vnet/ip/ip4.h @@ -141,31 +141,38 @@ typedef struct ip4_main_t { /** Feature path configuration lists */ vnet_ip_feature_registration_t * next_uc_feature; vnet_ip_feature_registration_t * next_mc_feature; + vnet_ip_feature_registration_t * next_tx_feature; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_check_access; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_source_reachable_via_rx; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_source_reachable_via_any; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_policer_classify; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_ipsec; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_vpath; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_lookup; - /** Built-in unicast feature path indice, see @ref ip_feature_init_cast() */ + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ u32 ip4_unicast_rx_feature_source_and_port_range_check; - /** Built-in multicast feature path indices */ + /** Built-in multicast feature path index */ u32 ip4_multicast_rx_feature_vpath; - /** Built-in multicast feature path indices */ + /** Built-in multicast feature path index */ u32 ip4_multicast_rx_feature_lookup; + /** Built-in unicast feature path index, see @ref ip_feature_init_cast() */ + u32 ip4_unicast_tx_feature_source_and_port_range_check; + + /** Built-in tx feature path index */ + u32 ip4_tx_feature_interface_output; + /** Save results for show command */ - char ** feature_nodes[VNET_N_CAST]; + char ** feature_nodes[VNET_N_IP_FEAT]; /** Seed for Jenkins hash used to compute ip4 flow hash. */ u32 flow_hash_seed; @@ -209,6 +216,18 @@ static void __vnet_add_feature_registration_mc_##x (void) \ } \ __VA_ARGS__ vnet_ip_feature_registration_t mc_##x +#define VNET_IP4_TX_FEATURE_INIT(x,...) \ + __VA_ARGS__ vnet_ip_feature_registration_t tx_##x; \ +static void __vnet_add_feature_registration_tx_##x (void) \ + __attribute__((__constructor__)) ; \ +static void __vnet_add_feature_registration_tx_##x (void) \ +{ \ + ip4_main_t * im = &ip4_main; \ + tx_##x.next = im->next_tx_feature; \ + im->next_tx_feature = &tx_##x; \ +} \ +__VA_ARGS__ vnet_ip_feature_registration_t tx_##x + /** Global ip4 input node. Errors get attached to ip4 input node. */ extern vlib_node_registration_t ip4_input_node; diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c index 4b019bce8de..dd9fce4592b 100644 --- a/vnet/vnet/ip/ip4_forward.c +++ b/vnet/vnet/ip/ip4_forward.c @@ -1387,91 +1387,127 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip4_sw_interface_admin_up_down); /* Built-in ip4 unicast rx feature path definition */ VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = { .node_name = "ip4-inacl", - .runs_before = {"ip4-source-check-via-rx", 0}, + .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 = {"ip4-source-check-via-any", 0}, + .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 = {"ip4-policer-classify", 0}, + .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, static) = { - .node_name = "ip4-source-and-port-range-check", - .runs_before = {"ip4-policer-classify", 0}, +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 = {"ipsec-input-ip4", 0}, + .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 = {"vpath-input-ip4", 0}, + .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 = {"ip4-lookup", 0}, + .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 */ + .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 = {"ip4-lookup-multicast", 0}, + .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 */ + .runs_before = 0, /* not before any other features */ .feature_index = &ip4_main.ip4_multicast_rx_feature_lookup, }; -static char * feature_start_nodes[] = +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_CAST; cast++) + for (cast = 0; cast < VNET_N_IP_FEAT; cast++) { - ip_config_main_t * cm = &lm->rx_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + 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, - ARRAY_LEN(feature_start_nodes), + feature_start_len, cast, 1 /* is_ip4 */))) return error; } + return 0; } @@ -1486,21 +1522,23 @@ ip4_sw_interface_add_del (vnet_main_t * vnm, u32 ci, cast; u32 feature_index; - for (cast = 0; cast < VNET_N_CAST; cast++) + for (cast = 0; cast < VNET_N_IP_FEAT; cast++) { - ip_config_main_t * cm = &lm->rx_config_mains[cast]; + ip_config_main_t * cm = &lm->feature_config_mains[cast]; vnet_config_main_t * vcm = &cm->config_main; vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0); ci = cm->config_index_by_sw_if_index[sw_if_index]; - if (cast == VNET_UNICAST) + if (cast == VNET_IP_RX_UNICAST_FEAT) feature_index = im->ip4_unicast_rx_feature_lookup; - else + else if (cast == VNET_IP_RX_MULTICAST_FEAT) feature_index = im->ip4_multicast_rx_feature_lookup; + else + feature_index = im->ip4_tx_feature_interface_output; if (is_add) - ci = vnet_config_add_feature (vm, vcm, + ci = vnet_config_add_feature (vm, vcm, ci, feature_index, /* config data */ 0, @@ -1513,6 +1551,9 @@ ip4_sw_interface_add_del (vnet_main_t * vnm, /* # bytes of config data */ 0); cm->config_index_by_sw_if_index[sw_if_index] = ci; + /* + * note: do not update the tx feature count here. + */ } return /* no error */ 0; @@ -1533,7 +1574,7 @@ VLIB_REGISTER_NODE (ip4_lookup_node) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_node, ip4_lookup) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_node, ip4_lookup); static uword ip4_indirect (vlib_main_t * vm, @@ -1555,7 +1596,7 @@ VLIB_REGISTER_NODE (ip4_indirect_node) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_indirect_node, ip4_indirect) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_indirect_node, ip4_indirect); /* Global IP4 main. */ @@ -1825,7 +1866,7 @@ VLIB_REGISTER_NODE (ip4_drop_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_drop_node, ip4_drop) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_drop_node, ip4_drop); VLIB_REGISTER_NODE (ip4_punt_node,static) = { .function = ip4_punt, @@ -1840,7 +1881,7 @@ VLIB_REGISTER_NODE (ip4_punt_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_punt_node, ip4_punt) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_punt_node, ip4_punt); VLIB_REGISTER_NODE (ip4_miss_node,static) = { .function = ip4_miss, @@ -1855,7 +1896,7 @@ VLIB_REGISTER_NODE (ip4_miss_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_miss_node, ip4_miss) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_miss_node, ip4_miss); /* Compute TCP/UDP/ICMP4 checksum in software. */ u16 @@ -2299,7 +2340,7 @@ VLIB_REGISTER_NODE (ip4_local_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_node, ip4_local) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_node, ip4_local); void ip4_register_protocol (u32 protocol, u32 node_index) { @@ -2644,6 +2685,7 @@ ip4_rewrite_inline (vlib_main_t * vm, u32 n_left_from, n_left_to_next, * to_next, next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index); vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX; + ip_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -2661,6 +2703,7 @@ ip4_rewrite_inline (vlib_main_t * vm, u32 pi0, rw_len0, next0, error0, checksum0, adj_index0; u32 pi1, rw_len1, next1, error1, checksum1, adj_index1; u32 next0_override, next1_override; + u32 tx_sw_if_index0, tx_sw_if_index1; if (rewrite_for_locally_received_packets) next0_override = next1_override = 0; @@ -2826,17 +2869,44 @@ ip4_rewrite_inline (vlib_main_t * vm, { p0->current_data -= rw_len0; p0->current_length += rw_len0; - p0->error = error_node->errors[error0]; + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; vnet_buffer (p0)->sw_if_index[VLIB_TX] = - adj0[0].rewrite_header.sw_if_index; + tx_sw_if_index0; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index0))) + { + p0->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index0); + vnet_get_config_data (&cm->config_main, + &p0->current_config_index, + &next0, + /* # bytes of config data */ 0); + } } if (PREDICT_TRUE(error1 == IP4_ERROR_NONE)) { p1->current_data -= rw_len1; p1->current_length += rw_len1; - p1->error = error_node->errors[error1]; + + tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index; vnet_buffer (p1)->sw_if_index[VLIB_TX] = - adj1[0].rewrite_header.sw_if_index; + tx_sw_if_index1; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index1))) + { + p1->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index1); + vnet_get_config_data (&cm->config_main, + &p1->current_config_index, + &next1, + /* # bytes of config data */ 0); + } } /* Guess we are only writing on simple Ethernet header. */ @@ -2856,6 +2926,7 @@ ip4_rewrite_inline (vlib_main_t * vm, ip4_header_t * ip0; u32 pi0, rw_len0, adj_index0, next0, error0, checksum0; u32 next0_override; + u32 tx_sw_if_index0; if (rewrite_for_locally_received_packets) next0_override = 0; @@ -2957,10 +3028,23 @@ ip4_rewrite_inline (vlib_main_t * vm, { p0->current_data -= rw_len0; p0->current_length += rw_len0; + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = - adj0[0].rewrite_header.sw_if_index; + vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index0))) + { + p0->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index0); + vnet_get_config_data (&cm->config_main, + &p0->current_config_index, + &next0, + /* # bytes of config data */ 0); + } } if (rewrite_for_locally_received_packets) @@ -3084,7 +3168,7 @@ VLIB_REGISTER_NODE (ip4_rewrite_node) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_node, ip4_rewrite_transit) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_node, ip4_rewrite_transit); VLIB_REGISTER_NODE (ip4_rewrite_local_node) = { .function = ip4_rewrite_local, @@ -3098,7 +3182,7 @@ VLIB_REGISTER_NODE (ip4_rewrite_local_node) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_local_node, ip4_rewrite_local) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_local_node, ip4_rewrite_local); static clib_error_t * add_del_interface_table (vlib_main_t * vm, @@ -3377,7 +3461,7 @@ VLIB_REGISTER_NODE (ip4_lookup_multicast_node,static) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_multicast_node, ip4_lookup_multicast) +VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_multicast_node, ip4_lookup_multicast); VLIB_REGISTER_NODE (ip4_multicast_node,static) = { .function = ip4_drop, @@ -3602,3 +3686,44 @@ VLIB_CLI_COMMAND (set_ip_classify_command, static) = { .function = set_ip_classify_command_fn, }; + +#define TEST_CODE 1 +#if TEST_CODE > 0 + +static clib_error_t * +set_interface_output_feature_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + u32 sw_if_index = ~0; + int is_add = 1; + ip4_main_t * im = &ip4_main; + ip_lookup_main_t * lm = &im->lookup_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (input, "del")) + is_add = 0; + else + break; + } + + if (sw_if_index == ~0) + return clib_error_return (0, "unknown interface `%U'", + format_unformat_error, input); + + lm->tx_sw_if_has_ip_output_features = + clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, is_add); + + return 0; +} + +VLIB_CLI_COMMAND (set_interface_output_feature, static) = { + .path = "set interface output feature", + .function = set_interface_output_feature_command_fn, + .short_help = "set interface output feature <intfc>", +}; +#endif /* TEST_CODE */ diff --git a/vnet/vnet/ip/ip4_input.c b/vnet/vnet/ip/ip4_input.c index 96a68661376..2de2d4756b3 100644 --- a/vnet/vnet/ip/ip4_input.c +++ b/vnet/vnet/ip/ip4_input.c @@ -144,11 +144,11 @@ ip4_input_inline (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX]; - cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_MULTICAST : VNET_UNICAST; - cast1 = ip4_address_is_multicast (&ip1->dst_address) ? VNET_MULTICAST : VNET_UNICAST; + cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; + cast1 = ip4_address_is_multicast (&ip1->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cm0 = lm->rx_config_mains + cast0; - cm1 = lm->rx_config_mains + cast1; + cm0 = lm->feature_config_mains + cast0; + cm1 = lm->feature_config_mains + cast1; p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); p1->current_config_index = vec_elt (cm1->config_index_by_sw_if_index, sw_if_index1); @@ -195,8 +195,8 @@ ip4_input_inline (vlib_main_t * vm, error1 = ip4_get_fragment_offset (ip1) == 1 ? IP4_ERROR_FRAGMENT_OFFSET_ONE : error1; /* TTL < 1? Drop it. */ - error0 = (ip0->ttl < 1 && cast0 == VNET_UNICAST) ? IP4_ERROR_TIME_EXPIRED : error0; - error1 = (ip1->ttl < 1 && cast1 == VNET_UNICAST) ? IP4_ERROR_TIME_EXPIRED : error1; + error0 = (ip0->ttl < 1 && cast0 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0; + error1 = (ip1->ttl < 1 && cast1 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error1; /* Verify lengths. */ ip_len0 = clib_net_to_host_u16 (ip0->length); @@ -262,8 +262,8 @@ ip4_input_inline (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_MULTICAST : VNET_UNICAST; - cm0 = lm->rx_config_mains + cast0; + cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; + cm0 = lm->feature_config_mains + cast0; p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; vnet_get_config_data (&cm0->config_main, @@ -294,7 +294,7 @@ ip4_input_inline (vlib_main_t * vm, error0 = ip4_get_fragment_offset (ip0) == 1 ? IP4_ERROR_FRAGMENT_OFFSET_ONE : error0; /* TTL < 1? Drop it. */ - error0 = (ip0->ttl < 1 && cast0 == VNET_UNICAST) ? IP4_ERROR_TIME_EXPIRED : error0; + error0 = (ip0->ttl < 1 && cast0 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0; /* Verify lengths. */ ip_len0 = clib_net_to_host_u16 (ip0->length); diff --git a/vnet/vnet/ip/ip4_source_and_port_range_check.c b/vnet/vnet/ip/ip4_source_and_port_range_check.c index 00faddf0fb3..ebfa767d8f0 100644 --- a/vnet/vnet/ip/ip4_source_and_port_range_check.c +++ b/vnet/vnet/ip/ip4_source_and_port_range_check.c @@ -16,7 +16,8 @@ #include <vnet/ip/ip_source_and_port_range_check.h> -vlib_node_registration_t ip4_source_port_and_range_check; +vlib_node_registration_t ip4_source_port_and_range_check_rx; +vlib_node_registration_t ip4_source_port_and_range_check_tx; #define foreach_ip4_source_and_port_range_check_error \ _(CHECK_FAIL, "ip4 source and port range check bad packets") \ @@ -42,7 +43,7 @@ typedef struct u32 bypass; u32 is_tcp; ip4_address_t src_addr; - u16 dst_port; + u16 port; u32 fib_index; } ip4_source_and_port_range_check_trace_t; @@ -59,7 +60,7 @@ format_ip4_source_and_port_range_check_trace (u8 * s, va_list * va) else s = format (s, "fib %d src ip %U %s dst port %d: %s", t->fib_index, format_ip4_address, &t->src_addr, - t->is_tcp ? "TCP" : "UDP", (u32) t->dst_port, + t->is_tcp ? "TCP" : "UDP", (u32) t->port, (t->pass == 1) ? "PASS" : "FAIL"); return s; } @@ -127,12 +128,15 @@ check_adj_port_range_x1 (ip_adjacency_t * adj, u16 dst_port, u32 next) } always_inline uword - ip4_source_and_port_range_check_inline - (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) +ip4_source_and_port_range_check_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, int is_tx) { ip4_main_t *im = &ip4_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *rx_cm = + &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; + ip_config_main_t *tx_cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; u32 n_left_from, *from, *to_next; u32 next_index; vlib_node_runtime_t *error_node = node; @@ -196,12 +200,24 @@ always_inline uword ip0 = vlib_buffer_get_current (b0); ip1 = vlib_buffer_get_current (b1); - c0 = vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, sizeof (c0[0])); - c1 = vnet_get_config_data (&cm->config_main, - &b1->current_config_index, - &next1, sizeof (c1[0])); + if (is_tx) + { + c0 = vnet_get_config_data (&tx_cm->config_main, + &b0->current_config_index, + &next0, sizeof (c0[0])); + c1 = vnet_get_config_data (&tx_cm->config_main, + &b1->current_config_index, + &next1, sizeof (c1[0])); + } + else + { + c0 = vnet_get_config_data (&rx_cm->config_main, + &b0->current_config_index, + &next0, sizeof (c0[0])); + c1 = vnet_get_config_data (&rx_cm->config_main, + &b1->current_config_index, + &next1, sizeof (c1[0])); + } /* we can't use the default VRF here... */ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++) @@ -210,12 +226,28 @@ always_inline uword } - if (ip0->protocol == IP_PROTOCOL_UDP) - fib_index0 = - c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; - if (ip0->protocol == IP_PROTOCOL_TCP) - fib_index0 = - c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + if (is_tx) + { + if (ip0->protocol == IP_PROTOCOL_UDP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]; + if (ip0->protocol == IP_PROTOCOL_TCP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]; + } + else + { + if (ip0->protocol == IP_PROTOCOL_UDP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; + if (ip0->protocol == IP_PROTOCOL_TCP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + } if (PREDICT_TRUE (fib_index0 != ~0)) { @@ -239,19 +271,35 @@ always_inline uword adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0, - &ip0-> - src_address, 0 + &ip0->src_address, + 0 /* use dflt rt */ )); adj0 = ip_get_adjacency (lm, adj_index0); } - if (ip1->protocol == IP_PROTOCOL_UDP) - fib_index1 = - c1->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; - if (ip1->protocol == IP_PROTOCOL_TCP) - fib_index1 = - c1->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + if (is_tx) + { + if (ip1->protocol == IP_PROTOCOL_UDP) + fib_index1 = + c1->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]; + if (ip1->protocol == IP_PROTOCOL_TCP) + fib_index1 = + c1->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]; + } + else + { + if (ip1->protocol == IP_PROTOCOL_UDP) + fib_index1 = + c1->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; + if (ip1->protocol == IP_PROTOCOL_TCP) + fib_index1 = + c1->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + } if (PREDICT_TRUE (fib_index1 != ~0)) { @@ -275,8 +323,7 @@ always_inline uword adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, fib_index1, - &ip1-> - src_address, + &ip1->src_address, 0)); adj1 = ip_get_adjacency (lm, adj_index1); } @@ -331,7 +378,7 @@ always_inline uword t->bypass = pass0; t->fib_index = fib_index0; t->src_addr.as_u32 = ip0->src_address.as_u32; - t->dst_port = (pass0 == 0) ? + t->port = (pass0 == 0) ? clib_net_to_host_u16 (udp0->dst_port) : 0; t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP; } @@ -345,7 +392,7 @@ always_inline uword t->bypass = pass1; t->fib_index = fib_index1; t->src_addr.as_u32 = ip1->src_address.as_u32; - t->dst_port = (pass1 == 0) ? + t->port = (pass1 == 0) ? clib_net_to_host_u16 (udp1->dst_port) : 0; t->is_tcp = ip1->protocol == IP_PROTOCOL_TCP; } @@ -379,11 +426,23 @@ always_inline uword vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (b0)->sw_if_index[VLIB_RX]); + if (is_tx) + vlib_buffer_advance (b0, sizeof (ethernet_header_t)); + ip0 = vlib_buffer_get_current (b0); - c0 = vnet_get_config_data - (&cm->config_main, &b0->current_config_index, - &next0, sizeof (c0[0])); + if (is_tx) + { + c0 = vnet_get_config_data + (&tx_cm->config_main, &b0->current_config_index, + &next0, sizeof (c0[0])); + } + else + { + c0 = vnet_get_config_data + (&rx_cm->config_main, &b0->current_config_index, + &next0, sizeof (c0[0])); + } /* we can't use the default VRF here... */ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++) @@ -392,12 +451,28 @@ always_inline uword } - if (ip0->protocol == IP_PROTOCOL_UDP) - fib_index0 = - c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; - if (ip0->protocol == IP_PROTOCOL_TCP) - fib_index0 = - c0->fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + if (is_tx) + { + if (ip0->protocol == IP_PROTOCOL_UDP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN]; + if (ip0->protocol == IP_PROTOCOL_TCP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN]; + } + else + { + if (ip0->protocol == IP_PROTOCOL_UDP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT]; + if (ip0->protocol == IP_PROTOCOL_TCP) + fib_index0 = + c0->fib_index + [IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT]; + } if (fib_index0 != ~0) { @@ -458,11 +533,14 @@ always_inline uword t->bypass = pass0; t->fib_index = fib_index0; t->src_addr.as_u32 = ip0->src_address.as_u32; - t->dst_port = (pass0 == 0) ? + t->port = (pass0 == 0) ? clib_net_to_host_u16 (udp0->dst_port) : 0; t->is_tcp = ip0->protocol == IP_PROTOCOL_TCP; } + if (is_tx) + vlib_buffer_advance (b0, -sizeof (ethernet_header_t)); + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); @@ -471,24 +549,63 @@ always_inline uword vlib_put_next_frame (vm, node, next_index, n_left_to_next); } - vlib_node_increment_counter (vm, ip4_source_port_and_range_check.index, - IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK, - good_packets); + if (is_tx) + vlib_node_increment_counter (vm, ip4_source_port_and_range_check_tx.index, + IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK, + good_packets); + else + vlib_node_increment_counter (vm, ip4_source_port_and_range_check_rx.index, + IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK, + good_packets); return frame->n_vectors; } static uword -ip4_source_and_port_range_check (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) +ip4_source_and_port_range_check_rx (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { - return ip4_source_and_port_range_check_inline (vm, node, frame); + return ip4_source_and_port_range_check_inline (vm, node, frame, + 0 /* !is_tx */ ); } +static uword +ip4_source_and_port_range_check_tx (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return ip4_source_and_port_range_check_inline (vm, node, frame, + 1 /* is_tx */ ); +} + +/* Note: Calling same function for both RX and TX nodes + as always checking dst_port, although + if this changes can easily make new function +*/ + /* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_source_port_and_range_check) = { - .function = ip4_source_and_port_range_check, - .name = "ip4-source-and-port-range-check", +VLIB_REGISTER_NODE (ip4_source_port_and_range_check_rx) = { + .function = ip4_source_and_port_range_check_rx, + .name = "ip4-source-and-port-range-check-rx", + .vector_size = sizeof (u32), + + .n_errors = ARRAY_LEN(ip4_source_and_port_range_check_error_strings), + .error_strings = ip4_source_and_port_range_check_error_strings, + + .n_next_nodes = IP4_SOURCE_AND_PORT_RANGE_CHECK_N_NEXT, + .next_nodes = { + [IP4_SOURCE_AND_PORT_RANGE_CHECK_NEXT_DROP] = "error-drop", + }, + + .format_buffer = format_ip4_header, + .format_trace = format_ip4_source_and_port_range_check_trace, +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip4_source_port_and_range_check_tx) = { + .function = ip4_source_and_port_range_check_tx, + .name = "ip4-source-and-port-range-check-tx", .vector_size = sizeof (u32), .n_errors = ARRAY_LEN(ip4_source_and_port_range_check_error_strings), @@ -511,7 +628,9 @@ set_ip_source_and_port_range_check (vlib_main_t * vm, { ip4_main_t *im = &ip4_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *rx_cm = + &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; + ip_config_main_t *tx_cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; u32 ci; ip_source_and_port_range_check_config_t config; u32 feature_index; @@ -523,17 +642,41 @@ set_ip_source_and_port_range_check (vlib_main_t * vm, config.fib_index[i] = fib_index[i]; } - feature_index = im->ip4_unicast_rx_feature_source_and_port_range_check; + /* For OUT we are in the RX path */ + if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] != ~0) || + (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] != ~0)) + { + feature_index = im->ip4_unicast_rx_feature_source_and_port_range_check; + + vec_validate (rx_cm->config_index_by_sw_if_index, sw_if_index); + + ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; + ci = (is_add + ? vnet_config_add_feature + : vnet_config_del_feature) + (vm, &rx_cm->config_main, ci, feature_index, &config, + sizeof (config)); + rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + } + + /* For IN we are in the TX path */ + if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] != ~0) || + (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] != ~0)) + { + feature_index = im->ip4_unicast_tx_feature_source_and_port_range_check; - vec_validate (rx_cm->config_index_by_sw_if_index, sw_if_index); + vec_validate (tx_cm->config_index_by_sw_if_index, sw_if_index); - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_add - ? vnet_config_add_feature - : vnet_config_del_feature) - (vm, &rx_cm->config_main, ci, feature_index, &config, sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + ci = tx_cm->config_index_by_sw_if_index[sw_if_index]; + ci = (is_add + ? vnet_config_add_feature + : vnet_config_del_feature) + (vm, &tx_cm->config_main, ci, feature_index, &config, + sizeof (config)); + tx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + vnet_config_update_tx_feature_count (lm, tx_cm, sw_if_index, is_add); + } return rv; } @@ -1006,7 +1149,7 @@ VLIB_CLI_COMMAND (ip_source_and_port_range_check_command, static) = { .path = "set ip source-and-port-range-check", .function = ip_source_and_port_range_check_command_fn, .short_help = - "set ip source-and-port-range-check <ip-addr>/<mask> [range <nn>-<nn> tcp-vrf <id>] [vrf <id>] [del]", + "set ip source-and-port-range-check <ip-addr>/<mask> [range <nn> - <nn>] [vrf <id>] [del]", }; /* *INDENT-ON* */ diff --git a/vnet/vnet/ip/ip4_source_check.c b/vnet/vnet/ip/ip4_source_check.c index 64b1e0abe25..1f8e7214ff1 100644 --- a/vnet/vnet/ip/ip4_source_check.c +++ b/vnet/vnet/ip/ip4_source_check.c @@ -82,7 +82,7 @@ ip4_source_check_inline (vlib_main_t * vm, { ip4_main_t * im = &ip4_main; ip_lookup_main_t * lm = &im->lookup_main; - ip_config_main_t * cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, * from, * to_next; u32 next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index); @@ -325,7 +325,7 @@ set_ip_source_check (vlib_main_t * vm, vnet_main_t * vnm = vnet_get_main(); ip4_main_t * im = &ip4_main; ip_lookup_main_t * lm = &im->lookup_main; - ip_config_main_t * rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; clib_error_t * error = 0; u32 sw_if_index, is_del, ci; ip4_source_check_config_t config; diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h index 3d6c9f422e8..0d5d8d04bf8 100644 --- a/vnet/vnet/ip/ip6.h +++ b/vnet/vnet/ip/ip6.h @@ -145,6 +145,7 @@ typedef struct ip6_main_t { /* feature path configuration lists */ vnet_ip_feature_registration_t * next_uc_feature; vnet_ip_feature_registration_t * next_mc_feature; + vnet_ip_feature_registration_t * next_tx_feature; /* Built-in unicast feature path indices, see ip_feature_init_cast(...) */ u32 ip6_unicast_rx_feature_check_access; @@ -157,9 +158,12 @@ typedef struct ip6_main_t { /* Built-in multicast feature path indices */ u32 ip6_multicast_rx_feature_vpath; u32 ip6_multicast_rx_feature_lookup; + + /* Built-in tx feature path index */ + u32 ip6_tx_feature_interface_output; /* Save results for show command */ - char ** feature_nodes[VNET_N_CAST]; + char ** feature_nodes[VNET_N_IP_FEAT]; /* Seed for Jenkins hash used to compute ip6 flow hash. */ u32 flow_hash_seed; @@ -202,6 +206,19 @@ static void __vnet_add_feature_registration_mc_##x (void) \ } \ __VA_ARGS__ vnet_ip_feature_registration_t mc_##x +#define VNET_IP6_TX_FEATURE_INIT(x,...) \ + __VA_ARGS__ vnet_ip_feature_registration_t tx_##x; \ +static void __vnet_add_feature_registration_tx_##x (void) \ + __attribute__((__constructor__)) ; \ +static void __vnet_add_feature_registration_tx_##x (void) \ +{ \ + ip6_main_t * im = &ip6_main; \ + tx_##x.next = im->next_tx_feature; \ + im->next_tx_feature = &tx_##x; \ +} \ +__VA_ARGS__ vnet_ip_feature_registration_t tx_##x + + /* Global ip6 input node. Errors get attached to ip6 input node. */ extern vlib_node_registration_t ip6_input_node; extern vlib_node_registration_t ip6_rewrite_node; diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 1e4afa8d0c0..f79acf74d7b 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -1252,71 +1252,96 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down); /* Built-in ip6 unicast rx feature path definition */ VNET_IP6_UNICAST_FEATURE_INIT (ip6_inacl, static) = { .node_name = "ip6-inacl", - .runs_before = {"ip6-policer-classify", 0}, + .runs_before = ORDER_CONSTRAINTS {"ip6-policer-classify", 0}, .feature_index = &ip6_main.ip6_unicast_rx_feature_check_access, }; VNET_IP6_UNICAST_FEATURE_INIT (ip6_policer_classify, static) = { .node_name = "ip6-policer-classify", - .runs_before = {"ipsec-input-ip6", 0}, + .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip6", 0}, .feature_index = &ip6_main.ip6_unicast_rx_feature_policer_classify, }; VNET_IP6_UNICAST_FEATURE_INIT (ip6_ipsec, static) = { .node_name = "ipsec-input-ip6", - .runs_before = {"l2tp-decap", 0}, + .runs_before = ORDER_CONSTRAINTS {"l2tp-decap", 0}, .feature_index = &ip6_main.ip6_unicast_rx_feature_ipsec, }; VNET_IP6_UNICAST_FEATURE_INIT (ip6_l2tp, static) = { .node_name = "l2tp-decap", - .runs_before = {"vpath-input-ip6", 0}, + .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip6", 0}, .feature_index = &ip6_main.ip6_unicast_rx_feature_l2tp_decap, }; VNET_IP6_UNICAST_FEATURE_INIT (ip6_vpath, static) = { .node_name = "vpath-input-ip6", - .runs_before = {"ip6-lookup", 0}, + .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, .feature_index = &ip6_main.ip6_unicast_rx_feature_vpath, }; VNET_IP6_UNICAST_FEATURE_INIT (ip6_lookup, static) = { .node_name = "ip6-lookup", - .runs_before = {0}, /* not before any other features */ + .runs_before = 0, /* not before any other features */ .feature_index = &ip6_main.ip6_unicast_rx_feature_lookup, }; /* Built-in ip6 multicast rx feature path definition (none now) */ -VNET_IP6_MULTICAST_FEATURE_INIT (ip4_vpath_mc, static) = { +VNET_IP6_MULTICAST_FEATURE_INIT (ip6_vpath_mc, static) = { .node_name = "vpath-input-ip6", - .runs_before = {"ip6-lookup", 0}, + .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, .feature_index = &ip6_main.ip6_multicast_rx_feature_vpath, }; VNET_IP6_MULTICAST_FEATURE_INIT (ip6_lookup, static) = { .node_name = "ip6-lookup", - .runs_before = {0}, /* not before any other features */ + .runs_before = 0, /* not before any other features */ .feature_index = &ip6_main.ip6_multicast_rx_feature_lookup, }; -static char * feature_start_nodes[] = +static char * rx_feature_start_nodes[] = {"ip6-input"}; +static char * tx_feature_start_nodes[] = + {"ip6-rewrite"}; + +/* Built-in ip4 tx feature path definition */ +VNET_IP6_TX_FEATURE_INIT (interface_output, static) = { + .node_name = "interface-output", + .runs_before = 0, /* not before any other features */ + .feature_index = &ip6_main.ip6_tx_feature_interface_output, +}; + static clib_error_t * ip6_feature_init (vlib_main_t * vm, ip6_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_CAST; cast++) + for (cast = 0; cast < VNET_N_IP_FEAT; cast++) { - ip_config_main_t * cm = &lm->rx_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + 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, - ARRAY_LEN(feature_start_nodes), + feature_start_len, cast, 0 /* is_ip4 */))) return error; @@ -1335,18 +1360,20 @@ ip6_sw_interface_add_del (vnet_main_t * vnm, u32 ci, cast; u32 feature_index; - for (cast = 0; cast < VNET_N_CAST; cast++) + for (cast = 0; cast < VNET_N_IP_FEAT; cast++) { - ip_config_main_t * cm = &lm->rx_config_mains[cast]; + ip_config_main_t * cm = &lm->feature_config_mains[cast]; vnet_config_main_t * vcm = &cm->config_main; vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0); ci = cm->config_index_by_sw_if_index[sw_if_index]; - if (cast == VNET_UNICAST) + if (cast == VNET_IP_RX_UNICAST_FEAT) feature_index = im->ip6_unicast_rx_feature_lookup; - else + else if (cast == VNET_IP_RX_MULTICAST_FEAT) feature_index = im->ip6_multicast_rx_feature_lookup; + else + feature_index = im->ip6_tx_feature_interface_output; if (is_add) ci = vnet_config_add_feature (vm, vcm, @@ -1362,6 +1389,9 @@ ip6_sw_interface_add_del (vnet_main_t * vnm, /* # bytes of config data */ 0); cm->config_index_by_sw_if_index[sw_if_index] = ci; + /* + * note: do not update the tx feature count here. + */ } return /* no error */ 0; } @@ -1389,7 +1419,7 @@ VLIB_REGISTER_NODE (ip6_lookup_node) = { .next_nodes = IP6_LOOKUP_NEXT_NODES, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup); static uword ip6_indirect (vlib_main_t * vm, @@ -1409,7 +1439,7 @@ VLIB_REGISTER_NODE (ip6_indirect_node) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_indirect_node, ip6_indirect) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_indirect_node, ip6_indirect); typedef struct { /* Adjacency taken. */ @@ -1617,7 +1647,7 @@ VLIB_REGISTER_NODE (ip6_drop_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_drop_node, ip6_drop) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_drop_node, ip6_drop); VLIB_REGISTER_NODE (ip6_punt_node,static) = { .function = ip6_punt, @@ -1632,7 +1662,7 @@ VLIB_REGISTER_NODE (ip6_punt_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_punt_node, ip6_punt) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_punt_node, ip6_punt); VLIB_REGISTER_NODE (ip6_miss_node,static) = { .function = ip6_miss, @@ -1647,7 +1677,7 @@ VLIB_REGISTER_NODE (ip6_miss_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_miss_node, ip6_miss) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_miss_node, ip6_miss); VLIB_REGISTER_NODE (ip6_multicast_node,static) = { .function = ip6_drop, @@ -2027,7 +2057,7 @@ VLIB_REGISTER_NODE (ip6_local_node,static) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_local_node, ip6_local) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_local_node, ip6_local); void ip6_register_protocol (u32 protocol, u32 node_index) { @@ -2346,6 +2376,7 @@ ip6_rewrite_inline (vlib_main_t * vm, u32 n_left_from, n_left_to_next, * to_next, next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_input_node.index); vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX; + ip_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -2362,6 +2393,7 @@ ip6_rewrite_inline (vlib_main_t * vm, ip6_header_t * ip0, * ip1; u32 pi0, rw_len0, next0, error0, adj_index0; u32 pi1, rw_len1, next1, error1, adj_index1; + u32 tx_sw_if_index0, tx_sw_if_index1; /* Prefetch next iteration. */ { @@ -2485,18 +2517,44 @@ ip6_rewrite_inline (vlib_main_t * vm, p0->current_data -= rw_len0; p0->current_length += rw_len0; + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; vnet_buffer (p0)->sw_if_index[VLIB_TX] = - adj0[0].rewrite_header.sw_if_index; - next0 = adj0[0].rewrite_header.next_index; + tx_sw_if_index0; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index0))) + { + p0->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index0); + vnet_get_config_data (&cm->config_main, + &p0->current_config_index, + &next0, + /* # bytes of config data */ 0); + } } if (PREDICT_TRUE(error1 == IP6_ERROR_NONE)) { p1->current_data -= rw_len1; p1->current_length += rw_len1; - vnet_buffer (p1)->sw_if_index[VLIB_TX] = - adj1[0].rewrite_header.sw_if_index; - next1 = adj1[0].rewrite_header.next_index; + tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index; + vnet_buffer (p1)->sw_if_index[VLIB_TX] = + tx_sw_if_index1; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index1))) + { + p1->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index1); + vnet_get_config_data (&cm->config_main, + &p1->current_config_index, + &next1, + /* # bytes of config data */ 0); + } } /* Guess we are only writing on simple Ethernet header. */ @@ -2516,6 +2574,7 @@ ip6_rewrite_inline (vlib_main_t * vm, ip6_header_t * ip0; u32 pi0, rw_len0; u32 adj_index0, next0, error0; + u32 tx_sw_if_index0; pi0 = to_next[0] = from[0]; @@ -2589,9 +2648,23 @@ ip6_rewrite_inline (vlib_main_t * vm, p0->current_data -= rw_len0; p0->current_length += rw_len0; - vnet_buffer (p0)->sw_if_index[VLIB_TX] = - adj0[0].rewrite_header.sw_if_index; + tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; + + vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; + + if (PREDICT_FALSE + (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, + tx_sw_if_index0))) + { + p0->current_config_index = + vec_elt (cm->config_index_by_sw_if_index, + tx_sw_if_index0); + vnet_get_config_data (&cm->config_main, + &p0->current_config_index, + &next0, + /* # bytes of config data */ 0); + } } p0->error = error_node->errors[error0]; @@ -2648,7 +2721,7 @@ VLIB_REGISTER_NODE (ip6_rewrite_node) = { }, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite_transit) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite_transit); VLIB_REGISTER_NODE (ip6_rewrite_local_node) = { .function = ip6_rewrite_local, @@ -2662,7 +2735,7 @@ VLIB_REGISTER_NODE (ip6_rewrite_local_node) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_local_node, ip6_rewrite_local) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_local_node, ip6_rewrite_local); /* * Hop-by-Hop handling @@ -2884,7 +2957,7 @@ VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = { .n_next_nodes = 0, }; -VLIB_NODE_FUNCTION_MULTIARCH (ip6_hop_by_hop_node, ip6_hop_by_hop) +VLIB_NODE_FUNCTION_MULTIARCH (ip6_hop_by_hop_node, ip6_hop_by_hop); static clib_error_t * ip6_hop_by_hop_init (vlib_main_t * vm) @@ -3328,3 +3401,43 @@ ip6_config (vlib_main_t * vm, unformat_input_t * input) VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6"); +#define TEST_CODE 1 +#if TEST_CODE > 0 + +static clib_error_t * +set_interface_ip6_output_feature_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + u32 sw_if_index = ~0; + int is_add = 1; + ip6_main_t * im = &ip6_main; + ip_lookup_main_t * lm = &im->lookup_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (input, "del")) + is_add = 0; + else + break; + } + + if (sw_if_index == ~0) + return clib_error_return (0, "unknown interface `%U'", + format_unformat_error, input); + + lm->tx_sw_if_has_ip_output_features = + clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, is_add); + + return 0; +} + +VLIB_CLI_COMMAND (set_interface_ip6_output_feature, static) = { + .path = "set interface ip6 output feature", + .function = set_interface_ip6_output_feature_command_fn, + .short_help = "set interface output feature <intfc>", +}; +#endif /* TEST_CODE */ diff --git a/vnet/vnet/ip/ip6_input.c b/vnet/vnet/ip/ip6_input.c index 05929c55884..15791245176 100644 --- a/vnet/vnet/ip/ip6_input.c +++ b/vnet/vnet/ip/ip6_input.c @@ -143,11 +143,11 @@ ip6_input (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX]; - cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_MULTICAST : VNET_UNICAST; - cast1 = ip6_address_is_multicast (&ip1->dst_address) ? VNET_MULTICAST : VNET_UNICAST; + cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; + cast1 = ip6_address_is_multicast (&ip1->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cm0 = lm->rx_config_mains + cast0; - cm1 = lm->rx_config_mains + cast1; + cm0 = lm->feature_config_mains + cast0; + cm1 = lm->feature_config_mains + cast1; p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); p1->current_config_index = vec_elt (cm1->config_index_by_sw_if_index, sw_if_index1); @@ -232,8 +232,8 @@ ip6_input (vlib_main_t * vm, ip0 = vlib_buffer_get_current (p0); sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_MULTICAST : VNET_UNICAST; - cm0 = lm->rx_config_mains + cast0; + cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; + cm0 = lm->feature_config_mains + cast0; p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; diff --git a/vnet/vnet/ip/ip_feature_registration.c b/vnet/vnet/ip/ip_feature_registration.c index 5f0d58ea25d..72deee41004 100644 --- a/vnet/vnet/ip/ip_feature_registration.c +++ b/vnet/vnet/ip/ip_feature_registration.c @@ -57,7 +57,7 @@ ip_feature_init_cast (vlib_main_t * vm, int a_index, b_index; int n_features; u32 * result = 0; - vnet_ip_feature_registration_t * this_reg, * first_reg; + vnet_ip_feature_registration_t * this_reg, * first_reg = 0; char ** feature_nodes = 0; hash_pair_t * hp; u8 ** keys_to_delete = 0; @@ -67,20 +67,28 @@ ip_feature_init_cast (vlib_main_t * vm, index_by_name = hash_create_string (0, sizeof (uword)); reg_by_index = hash_create (0, sizeof (uword)); - if (cast == VNET_UNICAST) + if (cast == VNET_IP_RX_UNICAST_FEAT) { if (is_ip4) first_reg = im4->next_uc_feature; else first_reg = im6->next_uc_feature; } - else + else if (cast == VNET_IP_RX_MULTICAST_FEAT) { if (is_ip4) first_reg = im4->next_mc_feature; else first_reg = im6->next_mc_feature; + } + else if (cast == VNET_IP_TX_FEAT) + { + if (is_ip4) + first_reg = im4->next_tx_feature; + else + first_reg = im6->next_tx_feature; } + this_reg = first_reg; @@ -95,8 +103,7 @@ ip_feature_init_cast (vlib_main_t * vm, vec_add1 (node_names, node_name); these_constraints = this_reg->runs_before; - - while (these_constraints [0]) + while (these_constraints && these_constraints [0]) { this_constraint_c = these_constraints[0]; @@ -105,6 +112,19 @@ ip_feature_init_cast (vlib_main_t * vm, 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, + node_name, 0); + vec_add1 (constraints, constraint_tuple); + these_constraints++; + } + this_reg = this_reg->next; } @@ -220,10 +240,12 @@ ip_feature_init_cast (vlib_main_t * vm, } #define foreach_af_cast \ -_(4, VNET_UNICAST, "ip4 unicast") \ -_(4, VNET_MULTICAST, "ip4 multicast") \ -_(6, VNET_UNICAST, "ip6 unicast") \ -_(6, VNET_MULTICAST, "ip6 multicast") +_(4, VNET_IP_RX_UNICAST_FEAT, "ip4 unicast") \ +_(4, VNET_IP_RX_MULTICAST_FEAT, "ip4 multicast") \ +_(4, VNET_IP_TX_FEAT, "ip4 output") \ +_(6, VNET_IP_RX_UNICAST_FEAT, "ip6 unicast") \ +_(6, VNET_IP_RX_MULTICAST_FEAT, "ip6 multicast") \ +_(6, VNET_IP_TX_FEAT, "ip6 output") static clib_error_t * show_ip_features_command_fn (vlib_main_t * vm, @@ -295,14 +317,14 @@ show_ip_interface_features_command_fn (vlib_main_t * vm, else lm = lm6; - for (cast = VNET_UNICAST; cast < VNET_N_CAST; cast++) + for (cast = VNET_IP_RX_UNICAST_FEAT; cast < VNET_N_IP_FEAT; cast++) { - cm = lm->rx_config_mains + cast; + cm = lm->feature_config_mains + cast; vcm = &cm->config_main; vlib_cli_output (vm, "\nipv%s %scast:", (af == 0) ? "4" : "6", - cast == VNET_UNICAST ? + cast == VNET_IP_RX_UNICAST_FEAT ? "uni": "multi"); current_config_index = vec_elt (cm->config_index_by_sw_if_index, diff --git a/vnet/vnet/ip/ip_feature_registration.h b/vnet/vnet/ip/ip_feature_registration.h index da2a0055b2f..3c78abc0bc8 100644 --- a/vnet/vnet/ip/ip_feature_registration.h +++ b/vnet/vnet/ip/ip_feature_registration.h @@ -20,9 +20,12 @@ typedef struct _vnet_ip_feature_registration { struct _vnet_ip_feature_registration * next; char * node_name; u32 * feature_index; - char * runs_before[]; + char ** runs_before; + char ** runs_after; } vnet_ip_feature_registration_t; +#define ORDER_CONSTRAINTS (char*[]) + clib_error_t * ip_feature_init_cast (vlib_main_t * vm, ip_config_main_t * cm, diff --git a/vnet/vnet/ip/ip_init.c b/vnet/vnet/ip/ip_init.c index c0c1c9560bc..02da6647be3 100644 --- a/vnet/vnet/ip/ip_init.c +++ b/vnet/vnet/ip/ip_init.c @@ -140,3 +140,25 @@ do { \ } VLIB_INIT_FUNCTION (ip_main_init); + +void +vnet_config_update_tx_feature_count (ip_lookup_main_t * lm, + ip_config_main_t * tx_cm, + u32 sw_if_index, + int is_add) +{ + ASSERT (tx_cm == &lm->feature_config_mains[VNET_IP_TX_FEAT]); + + vec_validate (lm->tx_feature_count_by_sw_if_index, sw_if_index); + + lm->tx_feature_count_by_sw_if_index[sw_if_index] += is_add ? 1 : -1; + + ASSERT (lm->tx_feature_count_by_sw_if_index[sw_if_index] >= 0); + + lm->tx_sw_if_has_ip_output_features = + clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, + lm->tx_feature_count_by_sw_if_index[sw_if_index] > 0); +} + + + diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h index 2b682d27195..fcd080a4375 100644 --- a/vnet/vnet/ip/lookup.h +++ b/vnet/vnet/ip/lookup.h @@ -408,6 +408,12 @@ typedef struct ip_lookup_main_t { /** Adjacency by signature hash */ uword * adj_index_by_signature; + /** any-tx-feature-enabled interface bitmap */ + uword * tx_sw_if_has_ip_output_features; + + /** count of enabled features, per sw_if_index, to maintain bitmap */ + i16 * tx_feature_count_by_sw_if_index; + /** Temporary vectors for looking up next hops in hash. */ ip_multipath_next_hop_t * next_hop_hash_lookup_key; ip_multipath_next_hop_t * next_hop_hash_lookup_key_normalized; @@ -444,8 +450,8 @@ typedef struct ip_lookup_main_t { /** First table index to use for this interface, ~0 => none */ u32 * classify_table_index_by_sw_if_index; - /** rx/tx interface/feature configuration. */ - ip_config_main_t rx_config_mains[VNET_N_CAST], tx_config_main; + /** rx unicast, multicast, tx interface/feature configuration. */ + ip_config_main_t feature_config_mains[VNET_N_IP_FEAT]; /** Number of bytes in a fib result. Must be at least sizeof (uword). First word is always adjacency index. */ diff --git a/vnet/vnet/ipsec/ipsec.c b/vnet/vnet/ipsec/ipsec.c index 1b3b9ffcc38..3e343834a42 100644 --- a/vnet/vnet/ipsec/ipsec.c +++ b/vnet/vnet/ipsec/ipsec.c @@ -78,7 +78,7 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id, /* IPv4 */ lm = &ip4_main.lookup_main; - rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; @@ -89,7 +89,7 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id, /* IPv6 */ lm = &ip6_main.lookup_main; - rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; diff --git a/vnet/vnet/ipsec/ipsec_input.c b/vnet/vnet/ipsec/ipsec_input.c index 8364e226ae1..4087981a3fe 100644 --- a/vnet/vnet/ipsec/ipsec_input.c +++ b/vnet/vnet/ipsec/ipsec_input.c @@ -185,7 +185,7 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm, { ip4_main_t *i4m = &ip4_main; ip_lookup_main_t *lm = &i4m->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next; ipsec_main_t *im = &ipsec_main; @@ -316,7 +316,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn) { ip6_main_t *i6m = &ip6_main; ip_lookup_main_t *lm = &i6m->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next; ipsec_main_t *im = &ipsec_main; diff --git a/vnet/vnet/l2tp/decap.c b/vnet/vnet/l2tp/decap.c index 1b97e712b3b..dfd846aced3 100644 --- a/vnet/vnet/l2tp/decap.c +++ b/vnet/vnet/l2tp/decap.c @@ -220,7 +220,8 @@ done: /* Go to next node on the ip6 configuration chain */ ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *cm = + &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; ip6_l2tpv3_config_t *c0; vnet_get_config_data (&cm->config_main, diff --git a/vnet/vnet/l2tp/l2tp.c b/vnet/vnet/l2tp/l2tp.c index 99443ce4b73..a043483ede4 100644 --- a/vnet/vnet/l2tp/l2tp.c +++ b/vnet/vnet/l2tp/l2tp.c @@ -616,7 +616,8 @@ l2tpv3_interface_enable_disable (vnet_main_t * vnm, { ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; - ip_config_main_t *rx_cm = &lm->rx_config_mains[VNET_UNICAST]; + ip_config_main_t *rx_cm = + &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 ci; ip6_l2tpv3_config_t config; u32 feature_index; diff --git a/vnet/vnet/vnet.h b/vnet/vnet/vnet.h index 3bca6bf4f3d..31faef7cbb9 100644 --- a/vnet/vnet/vnet.h +++ b/vnet/vnet/vnet.h @@ -44,9 +44,10 @@ typedef enum { - VNET_UNICAST, - VNET_MULTICAST, - VNET_N_CAST, + VNET_IP_RX_UNICAST_FEAT, + VNET_IP_RX_MULTICAST_FEAT, + VNET_IP_TX_FEAT, + VNET_N_IP_FEAT, } vnet_cast_t; #include <vnet/unix/pcap.h> diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index e142be63e71..93401ed1a50 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -1455,10 +1455,14 @@ vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp) ip6_main_t *ip6m = &ip6_main; ip_lookup_main_t *ip4lm = &ip4m->lookup_main; ip_lookup_main_t *ip6lm = &ip6m->lookup_main; - ip_config_main_t *rx_cm4u = &ip4lm->rx_config_mains[VNET_UNICAST]; - ip_config_main_t *rx_cm4m = &ip4lm->rx_config_mains[VNET_MULTICAST]; - ip_config_main_t *rx_cm6u = &ip6lm->rx_config_mains[VNET_UNICAST]; - ip_config_main_t *rx_cm6m = &ip6lm->rx_config_mains[VNET_MULTICAST]; + ip_config_main_t *rx_cm4u = + &ip4lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; + ip_config_main_t *rx_cm4m = + &ip4lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; + ip_config_main_t *rx_cm6u = + &ip6lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; + ip_config_main_t *rx_cm6m = + &ip6lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; VALIDATE_SW_IF_INDEX (mp); |