summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c24
-rw-r--r--plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h3
-rw-r--r--plugins/flowperpkt-plugin/flowperpkt/node.c20
-rw-r--r--plugins/ila-plugin/ila/ila.c39
-rw-r--r--plugins/ila-plugin/ila/ila.h2
-rw-r--r--plugins/snat-plugin/snat/out2in.c27
-rw-r--r--plugins/snat-plugin/snat/snat.c50
-rw-r--r--plugins/snat-plugin/snat/snat.h6
-rw-r--r--vnet/vnet/adj/adj_l2.c11
-rw-r--r--vnet/vnet/adj/adj_midchain.c130
-rw-r--r--vnet/vnet/classify/flow_classify.c34
-rw-r--r--vnet/vnet/classify/input_acl.c40
-rw-r--r--vnet/vnet/classify/policer_classify.c37
-rw-r--r--vnet/vnet/devices/devices.c1
-rw-r--r--vnet/vnet/ethernet/ethernet.h26
-rw-r--r--vnet/vnet/ethernet/init.c34
-rw-r--r--vnet/vnet/feature/feature.c45
-rw-r--r--vnet/vnet/feature/feature.h22
-rw-r--r--vnet/vnet/feature/registration.c211
-rw-r--r--vnet/vnet/ip/ip.h6
-rw-r--r--vnet/vnet/ip/ip4.h77
-rw-r--r--vnet/vnet/ip/ip4_forward.c279
-rw-r--r--vnet/vnet/ip/ip4_input.c47
-rw-r--r--vnet/vnet/ip/ip4_source_and_port_range_check.c66
-rw-r--r--vnet/vnet/ip/ip4_source_check.c42
-rw-r--r--vnet/vnet/ip/ip6.h62
-rw-r--r--vnet/vnet/ip/ip6_forward.c310
-rw-r--r--vnet/vnet/ip/ip6_input.c42
-rw-r--r--vnet/vnet/ip/ip_init.c21
-rw-r--r--vnet/vnet/ip/lookup.h12
-rw-r--r--vnet/vnet/ipsec/ipsec.c31
-rw-r--r--vnet/vnet/ipsec/ipsec_input.c23
-rw-r--r--vnet/vnet/l2tp/decap.c10
-rw-r--r--vnet/vnet/l2tp/l2tp.c18
-rw-r--r--vnet/vnet/mpls/interface.c24
-rw-r--r--vnet/vnet/mpls/mpls.h40
-rw-r--r--vnet/vnet/mpls/mpls_features.c119
-rw-r--r--vnet/vnet/mpls/node.c14
-rw-r--r--vnet/vnet/vnet.h15
-rw-r--r--vpp/vpp-api/api.c74
40 files changed, 481 insertions, 1613 deletions
diff --git a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
index ac508582669..dbdb189865d 100644
--- a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
+++ b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
@@ -59,10 +59,10 @@ flowperpkt_main_t flowperpkt_main;
/* Define the per-interface configurable feature */
/* *INDENT-OFF* */
-VNET_IP4_TX_FEATURE_INIT (flow_perpacket, static) = {
+VNET_FEATURE_INIT (flow_perpacket, static) = {
+ .arc_name = "ip4-output",
.node_name = "flowperpkt",
- .runs_before = (char *[]){"interface-output", 0},
- .feature_index = &flowperpkt_main.ip4_tx_feature_index,
+ .runs_before = VNET_FEATURES ("interface-output"),
};
/* *INDENT-ON* */
@@ -249,11 +249,6 @@ flowperpkt_data_callback (flow_report_main_t * frm,
static int flowperpkt_tx_interface_add_del_feature
(flowperpkt_main_t * fm, u32 sw_if_index, int is_add)
{
- u32 ci;
- ip4_main_t *im = &ip4_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
- u32 feature_index;
flow_report_main_t *frm = &flow_report_main;
vnet_flow_report_add_del_args_t _a, *a = &_a;
int rv;
@@ -276,18 +271,9 @@ static int flowperpkt_tx_interface_add_del_feature
}
}
- feature_index = fm->ip4_tx_feature_index;
+ vnet_feature_enable_disable ("ip4-output", "flowperpkt", sw_if_index,
+ is_add, 0, 0);
- ci = cm->config_index_by_sw_if_index[sw_if_index];
- ci = (is_add
- ? vnet_config_add_feature
- : vnet_config_del_feature)
- (fm->vlib_main, &cm->config_main,
- ci, feature_index, 0 /* config struct */ ,
- 0 /* sizeof config struct */ );
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
-
- vnet_config_update_tx_feature_count (lm, cm, sw_if_index, is_add);
return 0;
}
diff --git a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h
index 5ddba9ce1da..31e685eb68d 100644
--- a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h
+++ b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h
@@ -35,9 +35,6 @@ typedef struct
/** API message ID base */
u16 msg_id_base;
- /** ip4 feature index */
- u32 ip4_tx_feature_index;
-
/** Has the report been created? */
int report_created;
diff --git a/plugins/flowperpkt-plugin/flowperpkt/node.c b/plugins/flowperpkt-plugin/flowperpkt/node.c
index b01f2be3a05..86da3a1cf59 100644
--- a/plugins/flowperpkt-plugin/flowperpkt/node.c
+++ b/plugins/flowperpkt-plugin/flowperpkt/node.c
@@ -284,9 +284,6 @@ flowperpkt_node_fn (vlib_main_t * vm,
{
u32 n_left_from, *from, *to_next;
flowperpkt_next_t next_index;
- ip4_main_t *im = &ip4_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
flowperpkt_main_t *fm = &flowperpkt_main;
u64 now;
@@ -337,14 +334,10 @@ flowperpkt_node_fn (vlib_main_t * vm,
b0 = vlib_get_buffer (vm, bi0);
b1 = vlib_get_buffer (vm, bi1);
-
- vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0, 0 /* sizeof config data */ );
-
- vnet_get_config_data (&cm->config_main,
- &b1->current_config_index,
- &next1, 0 /* sizeof config data */ );
+ vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
+ &next0, b0);
+ vnet_feature_next (vnet_buffer (b1)->sw_if_index[VLIB_TX],
+ &next1, b1);
ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
vnet_buffer (b0)->ip.save_rewrite_length);
@@ -413,9 +406,8 @@ flowperpkt_node_fn (vlib_main_t * vm,
b0 = vlib_get_buffer (vm, bi0);
- vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0, 0 /* sizeof config data */ );
+ vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
+ &next0, b0);
ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
vnet_buffer (b0)->ip.save_rewrite_length);
diff --git a/plugins/ila-plugin/ila/ila.c b/plugins/ila-plugin/ila/ila.c
index 61ce0f7bacd..336f4cf560c 100644
--- a/plugins/ila-plugin/ila/ila.c
+++ b/plugins/ila-plugin/ila/ila.c
@@ -425,9 +425,6 @@ static uword
ila_sir2ila (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- ip6_main_t *im = &ip6_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_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;
@@ -519,11 +516,8 @@ ila_sir2ila (vlib_main_t * vm,
ip61->dst_address.as_u64[0] = ila_address1->as_u64[0];
ip61->dst_address.as_u64[1] = ila_address1->as_u64[1];
- vnet_get_config_data (&cm->config_main,
- &p0->current_config_index, &next0, 0);
-
- vnet_get_config_data (&cm->config_main,
- &p1->current_config_index, &next1, 0);
+ vnet_feature_next (vnet_buffer (p0)->sw_if_index[VLIB_RX], &next0, p0);
+ vnet_feature_next (vnet_buffer (p1)->sw_if_index[VLIB_RX], &next1, p1);
vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
n_left_to_next, pi0, pi1, next0,
@@ -574,8 +568,7 @@ ila_sir2ila (vlib_main_t * vm,
ip60->dst_address.as_u64[0] = ila_address0->as_u64[0];
ip60->dst_address.as_u64[1] = ila_address0->as_u64[1];
- vnet_get_config_data (&cm->config_main,
- &p0->current_config_index, &next0, 0);
+ vnet_feature_next (vnet_buffer (p0)->sw_if_index[VLIB_RX], &next0, p0);
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, pi0, next0);
@@ -603,11 +596,11 @@ VLIB_REGISTER_NODE (ila_sir2ila_node, static) =
/** *INDENT-ON* */
/** *INDENT-OFF* */
-VNET_IP6_UNICAST_FEATURE_INIT (ila_sir2ila, static) =
+VNET_FEATURE_INIT (ila_sir2ila, static) =
{
+ .arc_name = "ip6-unicast",
.node_name = "sir-to-ila",
- .runs_before = ORDER_CONSTRAINTS{"ip6-lookup", 0},
- .feature_index = &ila_main.ila_sir2ila_feature_index,
+ .runs_before = VNET_FEATURES ("ip6-lookup"),
};
/** *INDENT-ON* */
@@ -823,24 +816,8 @@ ila_add_del_entry (ila_add_del_entry_args_t * args)
int
ila_interface (u32 sw_if_index, u8 disable)
{
- vlib_main_t *vm = vlib_get_main ();
- ila_main_t *ilm = &ila_main;
- ip6_main_t *im = &ip6_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_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;
-
- 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];
- feature_index = ilm->ila_sir2ila_feature_index;
-
- ci = ((disable) ? vnet_config_del_feature : vnet_config_add_feature)
- (vm, vcm, ci, feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
-
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ vnet_feature_enable_disable ("ip4-unicast", "sir-to-ila", sw_if_index,
+ !disable, 0, 0);
return 0;
}
diff --git a/plugins/ila-plugin/ila/ila.h b/plugins/ila-plugin/ila/ila.h
index 657511f00f2..26620983823 100644
--- a/plugins/ila-plugin/ila/ila.h
+++ b/plugins/ila-plugin/ila/ila.h
@@ -94,8 +94,6 @@ typedef struct {
u64 lookup_table_size;
clib_bihash_24_8_t id_to_entry_table;
- u32 ila_sir2ila_feature_index;
-
u32 ip6_lookup_next_index;
} ila_main_t;
diff --git a/plugins/snat-plugin/snat/out2in.c b/plugins/snat-plugin/snat/out2in.c
index 190350ada2b..35edcc5f7b3 100644
--- a/plugins/snat-plugin/snat/out2in.c
+++ b/plugins/snat-plugin/snat/out2in.c
@@ -284,8 +284,6 @@ snat_out2in_node_fn (vlib_main_t * vm,
snat_out2in_next_t next_index;
u32 pkts_processed = 0;
snat_main_t * sm = &snat_main;
- ip_lookup_main_t * lm = sm->ip4_lookup_main;
- vnet_feature_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);
@@ -355,10 +353,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index0);
- vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0,
- 0 /* sizeof config data */);
+ vnet_feature_next (sw_if_index0, &next0, b0);
proto0 = ~0;
proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
? SNAT_PROTOCOL_UDP : proto0;
@@ -474,10 +469,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index1);
- vnet_get_config_data (&cm->config_main,
- &b1->current_config_index,
- &next1,
- 0 /* sizeof config data */);
+ vnet_feature_next (sw_if_index1, &next1, b1);
+
proto1 = ~0;
proto1 = (ip1->protocol == IP_PROTOCOL_UDP)
? SNAT_PROTOCOL_UDP : proto1;
@@ -628,10 +621,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index0);
- vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0,
- 0 /* sizeof config data */);
+ vnet_feature_next (sw_if_index0, &next0, b0);
+
proto0 = ~0;
proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
? SNAT_PROTOCOL_UDP : proto0;
@@ -853,8 +844,6 @@ snat_out2in_fast_node_fn (vlib_main_t * vm,
snat_out2in_next_t next_index;
u32 pkts_processed = 0;
snat_main_t * sm = &snat_main;
- ip_lookup_main_t * lm = sm->ip4_lookup_main;
- vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -902,10 +891,8 @@ snat_out2in_fast_node_fn (vlib_main_t * vm,
sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0,
- 0 /* sizeof config data */);
+ vnet_feature_next (sw_if_index0, &next0, b0);
+
proto0 = ~0;
proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
? SNAT_PROTOCOL_UDP : proto0;
diff --git a/plugins/snat-plugin/snat/snat.c b/plugins/snat-plugin/snat/snat.c
index 0b972110f19..66c03817ca0 100644
--- a/plugins/snat-plugin/snat/snat.c
+++ b/plugins/snat-plugin/snat/snat.c
@@ -93,25 +93,25 @@ do { \
/* Hook up input features */
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out, static) = {
+VNET_FEATURE_INIT (ip4_snat_in2out, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "snat-in2out",
- .runs_before = (char *[]){"snat-out2in", 0},
- .feature_index = &snat_main.rx_feature_in2out,
+ .runs_before = VNET_FEATURES ("snat-out2in"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in, static) = {
+VNET_FEATURE_INIT (ip4_snat_out2in, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "snat-out2in",
- .runs_before = (char *[]){"ip4-lookup", 0},
- .feature_index = &snat_main.rx_feature_out2in,
+ .runs_before = VNET_FEATURES ("ip4-lookup"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
+VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "snat-in2out-fast",
- .runs_before = (char *[]){"snat-out2in-fast", 0},
- .feature_index = &snat_main.rx_feature_in2out_fast,
+ .runs_before = VNET_FEATURES ("snat-out2in-fast"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
+VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "snat-out2in-fast",
- .runs_before = (char *[]){"ip4-lookup", 0},
- .feature_index = &snat_main.rx_feature_out2in_fast,
+ .runs_before = VNET_FEATURES ("ip4-lookup"),
};
@@ -540,29 +540,15 @@ static int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
{
snat_main_t *sm = &snat_main;
snat_interface_t *i;
- u32 ci;
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- vnet_feature_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- u32 feature_index;
+ const char * feature_name;
if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
- feature_index = is_inside ? sm->rx_feature_in2out_fast
- : sm->rx_feature_out2in_fast;
+ feature_name = is_inside ? "snat-in2out-fast" : "snat-out2in-fast";
else
- feature_index = is_inside ? sm->rx_feature_in2out
- : sm->rx_feature_out2in;
-
- ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
- ci = (is_del
- ? vnet_config_del_feature
- : vnet_config_add_feature)
- (sm->vlib_main, &rx_cm->config_main,
- ci,
- feature_index,
- 0 /* config struct */,
- 0 /* sizeof config struct*/);
- rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ feature_name = is_inside ? "snat-in2out" : "snat-out2in";
+
+ vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
+ !is_del, 0, 0);
pool_foreach (i, sm->interfaces,
({
diff --git a/plugins/snat-plugin/snat/snat.h b/plugins/snat-plugin/snat/snat.h
index 1469f60e59d..ca10b76adce 100644
--- a/plugins/snat-plugin/snat/snat.h
+++ b/plugins/snat-plugin/snat/snat.h
@@ -166,12 +166,6 @@ typedef struct {
/* Randomize port allocation order */
u32 random_seed;
- /* ip4 feature path indices */
- u32 rx_feature_in2out;
- u32 rx_feature_out2in;
- u32 rx_feature_in2out_fast;
- u32 rx_feature_out2in_fast;
-
/* Config parameters */
u8 static_mapping_only;
u8 static_mapping_connection_tracking;
diff --git a/vnet/vnet/adj/adj_l2.c b/vnet/vnet/adj/adj_l2.c
index c49ec77ec78..4d2dd7082f1 100644
--- a/vnet/vnet/adj/adj_l2.c
+++ b/vnet/vnet/adj/adj_l2.c
@@ -53,7 +53,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
u32 * from = vlib_frame_vector_args (frame);
u32 n_left_from, n_left_to_next, * to_next, next_index;
u32 cpu_index = os_get_cpu_number();
- vnet_feature_config_main_t * cm = &ethernet_main.feature_config_mains[VNET_IP_TX_FEAT];
+ ethernet_main_t * em = &ethernet_main;
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
@@ -67,7 +67,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
ip_adjacency_t * adj0;
vlib_buffer_t * p0;
char *h0;
- u32 pi0, rw_len0, adj_index0, next0;
+ u32 pi0, rw_len0, adj_index0, next0 = 0;
u32 tx_sw_if_index0;
pi0 = to_next[0] = from[0];
@@ -121,12 +121,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm,
* Follow the feature ARC. this will result eventually in
* the midchain-tx node
*/
- 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);
+ vnet_feature_arc_start(em->output_feature_arc_index, tx_sw_if_index0, &next0, p0);
}
else
{
diff --git a/vnet/vnet/adj/adj_midchain.c b/vnet/vnet/adj/adj_midchain.c
index d40ea792152..92ea1ea9510 100644
--- a/vnet/vnet/adj/adj_midchain.c
+++ b/vnet/vnet/adj/adj_midchain.c
@@ -260,45 +260,53 @@ VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node, static) = {
},
};
-VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = {
+ .arc_name = "ip4-output",
.node_name = "adj-midchain-tx",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4],
};
-VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = {
+ .arc_name = "ip4-output",
.node_name = "adj-midchain-tx-no-count",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4],
};
-VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = {
+ .arc_name = "ip6-output",
.node_name = "adj-midchain-tx",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6],
};
-VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = {
+ .arc_name = "ip6-output",
.node_name = "adj-midchain-tx-no-count",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6],
};
-VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
+ .arc_name = "mpls-output",
.node_name = "adj-midchain-tx",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS],
};
-VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = {
+ .arc_name = "mpls-output",
.node_name = "adj-midchain-tx-no-count",
- .runs_before = ORDER_CONSTRAINTS {"interface-output", 0},
- .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS],
+ .runs_before = VNET_FEATURES ("interface-output"),
+ .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS],
};
-VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = {
+ .arc_name = "ethernet-output",
.node_name = "adj-midchain-tx",
- .runs_before = ORDER_CONSTRAINTS {"error-drop", 0},
- .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
+ .runs_before = VNET_FEATURES ("error-drop"),
+ .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET],
};
-VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
+VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = {
+ .arc_name = "ethernet-output",
.node_name = "adj-midchain-tx-no-count",
- .runs_before = ORDER_CONSTRAINTS {"error-drop", 0},
- .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET],
+ .runs_before = VNET_FEATURES ("error-drop"),
+ .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET],
};
static inline u32
@@ -320,36 +328,30 @@ adj_get_midchain_node (vnet_link_t link)
return (0);
}
-static vnet_feature_config_main_t *
-adj_midchain_get_config_for_link_type (const ip_adjacency_t *adj)
+static u8
+adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj)
{
- vnet_feature_config_main_t *cm = NULL;
-
+ u8 arc = (u8) ~0;
switch (adj->ia_link)
{
case VNET_LINK_IP4:
{
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
+ arc = ip4_main.lookup_main.output_feature_arc_index;
break;
}
case VNET_LINK_IP6:
{
- ip6_main_t * im = &ip6_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
+ arc = ip6_main.lookup_main.output_feature_arc_index;
break;
}
case VNET_LINK_MPLS:
{
- mpls_main_t * mm = &mpls_main;
- cm = &mm->feature_config_mains[VNET_IP_TX_FEAT];
+ arc = mpls_main.output_feature_arc_index;
break;
}
case VNET_LINK_ETHERNET:
{
- cm = &ethernet_main.feature_config_mains[VNET_IP_TX_FEAT];
+ arc = ethernet_main.output_feature_arc_index;
break;
}
case VNET_LINK_ARP:
@@ -357,7 +359,9 @@ adj_midchain_get_config_for_link_type (const ip_adjacency_t *adj)
break;
}
- return (cm);
+ ASSERT (arc != (u8) ~0);
+
+ return (arc);
}
/**
@@ -373,10 +377,9 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
adj_midchain_flag_t flags,
u8 *rewrite)
{
- vnet_config_main_t * vcm;
- vnet_feature_config_main_t *cm;
ip_adjacency_t *adj;
- u32 ci;
+ u8 arc_index;
+ u32 feature_index;
ASSERT(ADJ_INDEX_INVALID != adj_index);
@@ -394,43 +397,18 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
adj->sub_type.midchain.fixup_func = fixup;
- cm = adj_midchain_get_config_for_link_type(adj);
- vcm = &(cm->config_main);
- vec_validate_init_empty(cm->config_index_by_sw_if_index,
- adj->rewrite_header.sw_if_index, ~0);
- ci = cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index];
-
- /*
- * Choose the adj tx function based on whether the client wants
- * to count against the interface or not and insert the appropriate
- * TX feature.
- */
- if (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT)
- {
- adj->sub_type.midchain.tx_function_node =
- adj_midchain_tx_no_count_node.index;
-
- ci = vnet_config_add_feature(
- vlib_get_main(),
- vcm, ci,
- adj_midchain_tx_no_count_feature_node[adj->ia_link],
- /* config data */ 0,
- /* # bytes of config data */ 0);
- }
- else
- {
- adj->sub_type.midchain.tx_function_node =
- adj_midchain_tx_node.index;
- ci = vnet_config_add_feature(
- vlib_get_main(),
- vcm, ci,
- adj_midchain_tx_feature_node[adj->ia_link],
- /* config data */ 0,
- /* # bytes of config data */ 0);
- }
+ arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
+ feature_index = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ?
+ adj_midchain_tx_no_count_feature_node[adj->ia_link] :
+ adj_midchain_tx_feature_node[adj->ia_link];
- cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index] = ci;
+ adj->sub_type.midchain.tx_function_node = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ?
+ adj_midchain_tx_no_count_node.index :
+ adj_midchain_tx_node.index;
+ vnet_feature_enable_disable_with_index (arc_index, feature_index,
+ adj->rewrite_header.sw_if_index,
+ 1 /* enable */, 0, 0);
/*
* stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
diff --git a/vnet/vnet/classify/flow_classify.c b/vnet/vnet/classify/flow_classify.c
index 527b13cb887..0a624204e34 100644
--- a/vnet/vnet/classify/flow_classify.c
+++ b/vnet/vnet/classify/flow_classify.c
@@ -21,30 +21,24 @@ vnet_flow_classify_feature_enable (vlib_main_t * vnm,
flow_classify_table_id_t tid,
int feature_enable)
{
- ip_lookup_main_t * lm;
- vnet_feature_config_main_t * ifcm;
- u32 ftype;
- u32 ci;
+ vnet_feature_config_main_t *vfcm;
+ u8 arc;
if (tid == FLOW_CLASSIFY_TABLE_IP4)
- {
- lm = &ip4_main.lookup_main;
- ftype = ip4_main.ip4_unicast_rx_feature_flow_classify;
- }
+ {
+ vnet_feature_enable_disable ("ip4-unicast", "ip4-flow-classify",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip4-unicast");
+ }
else
- {
- lm = &ip6_main.lookup_main;
- ftype = ip6_main.ip6_unicast_rx_feature_flow_classify;
- }
-
- ifcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
-
- ci = ifcm->config_index_by_sw_if_index[sw_if_index];
- ci = (feature_enable ? vnet_config_add_feature : vnet_config_del_feature)
- (vnm, &ifcm->config_main, ci, ftype, 0, 0);
+ {
+ vnet_feature_enable_disable ("ip6-unicast", "ip6-flow-classify",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip6-unicast");
+ }
- ifcm->config_index_by_sw_if_index[sw_if_index] = ci;
- fcm->vnet_config_main[tid] = &ifcm->config_main;
+ vfcm = vnet_get_feature_arc_config_main (arc);
+ fcm->vnet_config_main[tid] = &vfcm->config_main;
}
int vnet_set_flow_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
diff --git a/vnet/vnet/classify/input_acl.c b/vnet/vnet/classify/input_acl.c
index ddb4332767a..c446f2d687c 100644
--- a/vnet/vnet/classify/input_acl.c
+++ b/vnet/vnet/classify/input_acl.c
@@ -33,34 +33,24 @@ vnet_inacl_ip_feature_enable (vlib_main_t * vnm,
}
else
{ /* IP[46] */
- ip_lookup_main_t * lm;
- vnet_feature_config_main_t * ipcm;
- u32 ftype;
- u32 ci;
+ vnet_feature_config_main_t *fcm;
+ u8 arc;
if (tid == INPUT_ACL_TABLE_IP4)
- {
- lm = &ip4_main.lookup_main;
- ftype = ip4_main.ip4_unicast_rx_feature_check_access;
- }
+ {
+ vnet_feature_enable_disable ("ip4-unicast", "ip4-inacl",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip4-unicast");
+ }
else
- {
- lm = &ip6_main.lookup_main;
- ftype = ip6_main.ip6_unicast_rx_feature_check_access;
- }
-
- 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)
- (vnm, &ipcm->config_main, ci, ftype,
- /* config data */ 0,
- /* # bytes of config data */ 0);
-
- ipcm->config_index_by_sw_if_index[sw_if_index] = ci;
- am->vnet_config_main[tid] = &ipcm->config_main;
+ {
+ vnet_feature_enable_disable ("ip6-unicast", "ip6-inacl",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip6-unicast");
+ }
+
+ fcm = vnet_get_feature_arc_config_main (arc);
+ am->vnet_config_main[tid] = &fcm->config_main;
}
return 0;
diff --git a/vnet/vnet/classify/policer_classify.c b/vnet/vnet/classify/policer_classify.c
index ada0dae34d0..569234fba3b 100644
--- a/vnet/vnet/classify/policer_classify.c
+++ b/vnet/vnet/classify/policer_classify.c
@@ -28,30 +28,25 @@ vnet_policer_classify_feature_enable (vlib_main_t * vnm,
}
else
{
- ip_lookup_main_t * lm;
- vnet_feature_config_main_t * ipcm;
- u32 ftype;
- u32 ci;
+ vnet_feature_config_main_t * fcm;
+ u8 arc;
if (tid == POLICER_CLASSIFY_TABLE_IP4)
- {
- lm = &ip4_main.lookup_main;
- ftype = ip4_main.ip4_unicast_rx_feature_policer_classify;
- }
+ {
+ vnet_feature_enable_disable ("ip4-unicast", "ip4-policer-classify",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip4-unicast");
+ }
+
else
- {
- lm = &ip6_main.lookup_main;
- ftype = ip6_main.ip6_unicast_rx_feature_policer_classify;
- }
-
- 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)
- (vnm, &ipcm->config_main, ci, ftype, 0, 0);
-
- ipcm->config_index_by_sw_if_index[sw_if_index] = ci;
- pcm->vnet_config_main[tid] = &ipcm->config_main;
+ {
+ vnet_feature_enable_disable ("ip6-unicast", "ip6-policer-classify",
+ sw_if_index, feature_enable, 0, 0);
+ arc = vnet_get_feature_arc_index ("ip6-unicast");
+ }
+
+ fcm = vnet_get_feature_arc_config_main (arc);
+ pcm->vnet_config_main[tid] = &fcm->config_main;
}
}
diff --git a/vnet/vnet/devices/devices.c b/vnet/vnet/devices/devices.c
index 26753305db2..928b0b4757a 100644
--- a/vnet/vnet/devices/devices.c
+++ b/vnet/vnet/devices/devices.c
@@ -37,6 +37,7 @@ VNET_FEATURE_ARC_INIT (device_input, static) =
{
.arc_name = "device-input",
.start_nodes = VNET_FEATURES ("device-input"),
+ .arc_index_ptr = &feature_main.device_input_feature_arc_index,
};
VNET_FEATURE_INIT (l2_patch, static) = {
diff --git a/vnet/vnet/ethernet/ethernet.h b/vnet/vnet/ethernet/ethernet.h
index c31025b7840..e557a2c23cc 100644
--- a/vnet/vnet/ethernet/ethernet.h
+++ b/vnet/vnet/ethernet/ethernet.h
@@ -263,34 +263,12 @@ typedef struct
/* debug: make sure we don't wipe out an ethernet registration by mistake */
u8 next_by_ethertype_register_called;
- /** per-interface features */
- vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT];
-
- /** Feature path configuration lists */
- vnet_feature_registration_t *next_feature[VNET_N_IP_FEAT];
-
- /** Save results for show command */
- char **feature_nodes[VNET_N_IP_FEAT];
-
- /** feature node indicies */
- u32 ethernet_tx_feature_drop;
+ /* Feature arc index */
+ u8 output_feature_arc_index;
} ethernet_main_t;
ethernet_main_t ethernet_main;
-#define VNET_ETHERNET_TX_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_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) \
-{ \
- ethernet_main_t * im = &ethernet_main; \
- tx_##x.next = im->next_feature[VNET_IP_TX_FEAT]; \
- im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t tx_##x
-
-
always_inline ethernet_type_info_t *
ethernet_get_type_info (ethernet_main_t * em, ethernet_type_t type)
{
diff --git a/vnet/vnet/ethernet/init.c b/vnet/vnet/ethernet/init.c
index b636c4af1a8..2d20adc9610 100644
--- a/vnet/vnet/ethernet/init.c
+++ b/vnet/vnet/ethernet/init.c
@@ -61,36 +61,24 @@ add_type (ethernet_main_t * em, ethernet_type_t type, char *type_name)
hash_set_mem (em->type_info_by_name, ti->name, i);
}
-static char *feature_start_nodes[] = {
- "adj-l2-midchain",
-};
-
/* Built-in ip4 tx feature path definition */
/* *INDENT-OFF* */
-VNET_ETHERNET_TX_FEATURE_INIT (ethernet_tx_drop, static) =
+VNET_FEATURE_ARC_INIT (ethernet_output, static) =
+{
+ .arc_name = "ethernet-output",
+ .start_nodes = VNET_FEATURES ("adj-l2-midchain"),
+ .arc_index_ptr = &ethernet_main.output_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (ethernet_tx_drop, static) =
{
+ .arc_name = "ethernet-output",
.node_name = "error-drop",
.runs_before = 0, /* not before any other features */
- .feature_index = &ethernet_main.ethernet_tx_feature_drop,
};
/* *INDENT-ON* */
static clib_error_t *
-ethernet_feature_init (vlib_main_t * vm)
-{
- vnet_feature_config_main_t *cm =
- &ethernet_main.feature_config_mains[VNET_IP_TX_FEAT];
- vnet_config_main_t *vcm = &cm->config_main;
-
- return (vnet_feature_arc_init (vm, vcm,
- feature_start_nodes,
- ARRAY_LEN (feature_start_nodes),
- ethernet_main.next_feature[VNET_IP_TX_FEAT],
- &ethernet_main.feature_nodes
- [VNET_IP_TX_FEAT]));
-}
-
-static clib_error_t *
ethernet_init (vlib_main_t * vm)
{
ethernet_main_t *em = &ethernet_main;
@@ -116,8 +104,10 @@ ethernet_init (vlib_main_t * vm)
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;
- return (ethernet_feature_init (vm));
+ return 0;
}
VLIB_INIT_FUNCTION (ethernet_init);
diff --git a/vnet/vnet/feature/feature.c b/vnet/vnet/feature/feature.c
index 25f098d33ad..1f46285aa21 100644
--- a/vnet/vnet/feature/feature.c
+++ b/vnet/vnet/feature/feature.c
@@ -34,6 +34,8 @@ vnet_feature_init (vlib_main_t * vm)
char *s;
int i = 0;
areg->feature_arc_index = arc_index;
+ if (areg->arc_index_ptr)
+ *areg->arc_index_ptr = arc_index;
hash_set_mem (fm->arc_index_by_name, areg->arc_name,
pointer_to_uword (areg));
@@ -111,8 +113,6 @@ vnet_feature_init (vlib_main_t * vm)
arc_index++;
}
- fm->device_input_feature_arc_index =
- vnet_get_feature_arc_index ("device-input");
return 0;
}
@@ -164,29 +164,27 @@ vnet_get_feature_index (u8 arc, const char *s)
return ~0;
reg = uword_to_pointer (p[0], vnet_feature_registration_t *);
- return reg->feature_index_u32;
+ return reg->feature_index;
}
int
-vnet_feature_enable_disable (const char *arc_name, const char *node_name,
- u32 sw_if_index, int enable_disable,
- void *feature_config, u32 n_feature_config_bytes)
+vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
+ u32 sw_if_index, int enable_disable,
+ void *feature_config,
+ u32 n_feature_config_bytes)
{
vnet_feature_main_t *fm = &feature_main;
vnet_feature_config_main_t *cm;
- u32 feature_index, ci;
- u8 arc_index;
-
- arc_index = vnet_get_feature_arc_index (arc_name);
+ u32 ci;
if (arc_index == (u8) ~ 0)
return VNET_API_ERROR_INVALID_VALUE;
- cm = &fm->feature_config_mains[arc_index];
- vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
- feature_index = vnet_get_feature_index (arc_index, node_name);
if (feature_index == ~0)
return VNET_API_ERROR_INVALID_VALUE_2;
+
+ cm = &fm->feature_config_mains[arc_index];
+ 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];
ci = (enable_disable
@@ -202,6 +200,27 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name,
return 0;
}
+int
+vnet_feature_enable_disable (const char *arc_name, const char *node_name,
+ u32 sw_if_index, int enable_disable,
+ void *feature_config, u32 n_feature_config_bytes)
+{
+ u32 feature_index;
+ u8 arc_index;
+
+ arc_index = vnet_get_feature_arc_index (arc_name);
+
+ if (arc_index == (u8) ~ 0)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ feature_index = vnet_get_feature_index (arc_index, node_name);
+
+ return vnet_feature_enable_disable_with_index (arc_index, feature_index,
+ sw_if_index, enable_disable,
+ feature_config,
+ n_feature_config_bytes);
+}
+
/** Display the set of available driver features.
Useful for verifying that expected features are present
diff --git a/vnet/vnet/feature/feature.h b/vnet/vnet/feature/feature.h
index 793678b74fc..b026cdf1c8f 100644
--- a/vnet/vnet/feature/feature.h
+++ b/vnet/vnet/feature/feature.h
@@ -31,6 +31,7 @@ typedef struct _vnet_feature_arc_registration
int n_start_nodes;
/* Feature arc index, assigned by init function */
u8 feature_arc_index;
+ u8 *arc_index_ptr;
} vnet_feature_arc_registration_t;
/** feature registration object */
@@ -43,8 +44,8 @@ typedef struct _vnet_feature_registration
/** Graph node name */
char *node_name;
/** Pointer to this feature index, filled in by vnet_feature_arc_init */
- u32 *feature_index;
- u32 feature_index_u32;
+ u32 *feature_index_ptr;
+ u32 feature_index;
/** Constraints of the form "this feature runs before X" */
char **runs_before;
/** Constraints of the form "this feature runs after Y" */
@@ -122,11 +123,27 @@ u32 vnet_get_feature_index (u8 arc, const char *s);
u8 vnet_get_feature_arc_index (const char *s);
int
+vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
+ u32 sw_if_index, int enable_disable,
+ void *feature_config,
+ u32 n_feature_config_bytes);
+
+int
vnet_feature_enable_disable (const char *arc_name, const char *node_name,
u32 sw_if_index, int enable_disable,
void *feature_config,
u32 n_feature_config_bytes);
+static inline vnet_feature_config_main_t *
+vnet_get_feature_arc_config_main (u8 arc_index)
+{
+ vnet_feature_main_t *fm = &feature_main;
+
+ if (arc_index == (u8) ~ 0)
+ return 0;
+
+ return &fm->feature_config_mains[arc_index];
+}
static_always_inline int
vnet_have_features (u8 arc, u32 sw_if_index)
@@ -259,7 +276,6 @@ vnet_feature_start_device_input_x2 (u32 sw_if_index,
}
-#define ORDER_CONSTRAINTS (char*[])
#define VNET_FEATURES(...) (char*[]) { __VA_ARGS__, 0}
clib_error_t *vnet_feature_arc_init (vlib_main_t * vm,
diff --git a/vnet/vnet/feature/registration.c b/vnet/vnet/feature/registration.c
index e6b0968e53c..1deeeef904c 100644
--- a/vnet/vnet/feature/registration.c
+++ b/vnet/vnet/feature/registration.c
@@ -79,7 +79,6 @@
vnet_feature_next.
*/
-static const char *vnet_cast_names[] = VNET_CAST_NAMES;
static int
comma_split (u8 * s, u8 ** a, u8 ** b)
@@ -196,7 +195,7 @@ vnet_feature_arc_init (vlib_main_t * vm,
p = hash_get_mem (index_by_name, a_name);
/*
- * Note: the next two errors mean that the xxx_FEATURE_INIT macros are
+ * Note: the next two errors mean that something is
* b0rked. As in: if you code "A depends on B," and you forget
* to define a FEATURE_INIT macro for B, you lose.
* Nonexistent graph nodes are tolerated.
@@ -260,9 +259,9 @@ again:
p = hash_get (reg_by_index, result[i]);
ASSERT (p != 0);
this_reg = (vnet_feature_registration_t *) p[0];
- if (this_reg->feature_index)
- *this_reg->feature_index = n_features - (i + 1);
- this_reg->feature_index_u32 = n_features - (i + 1);
+ if (this_reg->feature_index_ptr)
+ *this_reg->feature_index_ptr = n_features - (i + 1);
+ this_reg->feature_index = n_features - (i + 1);
vec_add1 (feature_nodes, this_reg->node_name);
}
@@ -293,208 +292,6 @@ again:
return 0;
}
-#define foreach_af_cast \
-_(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")
-
-/** Display the set of available ip features.
- Useful for verifying that expected features are present
-*/
-
-static clib_error_t *
-show_ip_features_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- ip4_main_t *im4 = &ip4_main;
- ip6_main_t *im6 = &ip6_main;
- int i;
- char **features;
-
- vlib_cli_output (vm, "Available IP feature nodes");
-
-#define _(a,c,s) \
- do { \
- features = im##a->feature_nodes[c]; \
- vlib_cli_output (vm, "%s:", s); \
- for (i = 0; i < vec_len(features); i++) \
- vlib_cli_output (vm, " %s\n", features[i]); \
- } while(0);
- foreach_af_cast;
-#undef _
-
- return 0;
-}
-
-/*?
- * This command is used to display the set of available IP features.
- * This can be useful for verifying that expected features are present.
- *
- * @cliexpar
- * Example of how to display the set of available IP features:
- * @cliexstart{show ip features}
- * Available IP feature nodes
- * ip4 unicast:
- * ip4-inacl
- * ip4-source-check-via-rx
- * ip4-source-check-via-any
- * ip4-source-and-port-range-check-rx
- * ip4-policer-classify
- * ipsec-input-ip4
- * vpath-input-ip4
- * snat-in2out
- * snat-out2in
- * ip4-lookup
- * ip4 multicast:
- * vpath-input-ip4
- * ip4-lookup-multicast
- * ip4 output:
- * ip4-source-and-port-range-check-tx
- * interface-output
- * ip6 unicast:
- * ip6-inacl
- * ip6-policer-classify
- * ipsec-input-ip6
- * l2tp-decap
- * vpath-input-ip6
- * sir-to-ila
- * ip6-lookup
- * ip6 multicast:
- * vpath-input-ip6
- * ip6-lookup
- * ip6 output:
- * interface-output
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_ip_features_command, static) = {
- .path = "show ip features",
- .short_help = "show ip features",
- .function = show_ip_features_command_fn,
-};
-/* *INDENT-ON* */
-
-/** Display the set of IP features configured on a specific interface
- */
-
-void
-ip_interface_features_show (vlib_main_t * vm,
- const char *pname,
- vnet_feature_config_main_t * cm, u32 sw_if_index)
-{
- u32 node_index, current_config_index;
- vnet_cast_t cast;
- vnet_config_main_t *vcm;
- vnet_config_t *cfg;
- u32 cfg_index;
- vnet_config_feature_t *feat;
- vlib_node_t *n;
- int i;
-
- vlib_cli_output (vm, "%s feature paths configured on %U...",
- pname, format_vnet_sw_if_index_name,
- vnet_get_main (), sw_if_index);
-
- for (cast = VNET_IP_RX_UNICAST_FEAT; cast < VNET_N_IP_FEAT; cast++)
- {
- vcm = &(cm[cast].config_main);
-
- vlib_cli_output (vm, "\n%s %s:", pname, vnet_cast_names[cast]);
-
- if (NULL == cm[cast].config_index_by_sw_if_index ||
- vec_len (cm[cast].config_index_by_sw_if_index) < sw_if_index)
- {
- vlib_cli_output (vm, "none configured");
- continue;
- }
-
- current_config_index = vec_elt (cm[cast].config_index_by_sw_if_index,
- sw_if_index);
-
- ASSERT (current_config_index
- < vec_len (vcm->config_pool_index_by_user_index));
-
- cfg_index = vcm->config_pool_index_by_user_index[current_config_index];
- cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
-
- for (i = 0; i < vec_len (cfg->features); i++)
- {
- feat = cfg->features + i;
- node_index = feat->node_index;
- n = vlib_get_node (vm, node_index);
- vlib_cli_output (vm, " %v", n->name);
- }
- }
-}
-
-static clib_error_t *
-show_ip_interface_features_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vnet_main_t *vnm = vnet_get_main ();
- ip4_main_t *im4 = &ip4_main;
- ip_lookup_main_t *lm4 = &im4->lookup_main;
- ip6_main_t *im6 = &ip6_main;
- ip_lookup_main_t *lm6 = &im6->lookup_main;
-
- ip_lookup_main_t *lm;
- u32 sw_if_index, af;
-
- if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
- return clib_error_return (0, "Interface not specified...");
-
- vlib_cli_output (vm, "IP feature paths configured on %U...",
- format_vnet_sw_if_index_name, vnm, sw_if_index);
-
- for (af = 0; af < 2; af++)
- {
- if (af == 0)
- lm = lm4;
- else
- lm = lm6;
-
- ip_interface_features_show (vm, (af == 0) ? "ip4" : "ip6",
- lm->feature_config_mains, sw_if_index);
- }
-
- return 0;
-}
-
-/*?
- * This command is used to display the set of IP features configured
- * on a specific interface
- *
- * @cliexpar
- * Example of how to display the set of available IP features on an interface:
- * @cliexstart{show ip interface features GigabitEthernet2/0/0}
- * IP feature paths configured on GigabitEthernet2/0/0...
- * ipv4 unicast:
- * ip4-lookup
- * ipv4 multicast:
- * ip4-lookup-multicast
- * ipv4 multicast:
- * interface-output
- * ipv6 unicast:
- * ip6-lookup
- * ipv6 multicast:
- * ip6-lookup
- * ipv6 multicast:
- * interface-output
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_ip_interface_features_command, static) = {
- .path = "show ip interface features",
- .short_help = "show ip interface features <interface>",
- .function = show_ip_interface_features_command_fn,
-};
-/* *INDENT-ON* */
-
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/vnet/vnet/ip/ip.h b/vnet/vnet/ip/ip.h
index a57d162c8c3..c9a82930a67 100644
--- a/vnet/vnet/ip/ip.h
+++ b/vnet/vnet/ip/ip.h
@@ -217,10 +217,4 @@ 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,
- vnet_feature_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 f0806c08449..62bb5f8513c 100644
--- a/vnet/vnet/ip/ip4.h
+++ b/vnet/vnet/ip/ip4.h
@@ -116,46 +116,6 @@ typedef struct ip4_main_t {
/** Template used to generate IP4 ARP packets. */
vlib_packet_template_t ip4_arp_request_packet_template;
- /** Feature path configuration lists */
- vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT];
-
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_check_access;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_source_reachable_via_rx;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_source_reachable_via_any;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_policer_classify;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_flow_classify;
- /** Built-in unicast feature path indix, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_ipsec;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_vpath;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_lookup;
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_source_and_port_range_check;
- /** Built-in unicast feature path indice, see @ref vnet_feature_arc_init() */
- u32 ip4_unicast_rx_feature_drop;
-
- /** Built-in multicast feature path index */
- u32 ip4_multicast_rx_feature_vpath;
- /** Built-in multicast feature path index */
- u32 ip4_multicast_rx_feature_lookup;
- /** Built-in multicast feature path indices */
- u32 ip4_multicast_rx_feature_drop;
-
- /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */
- 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_IP_FEAT];
-
/** Seed for Jenkins hash used to compute ip4 flow hash. */
u32 flow_hash_seed;
@@ -174,43 +134,6 @@ typedef struct ip4_main_t {
/** Global ip4 main structure. */
extern ip4_main_t ip4_main;
-#define VNET_IP4_UNICAST_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_feature_registration_t uc_##x; \
-static void __vnet_add_feature_registration_uc_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vnet_add_feature_registration_uc_##x (void) \
-{ \
- ip4_main_t * im = &ip4_main; \
- uc_##x.next = im->next_feature[VNET_IP_RX_UNICAST_FEAT]; \
- im->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t uc_##x
-
-#define VNET_IP4_MULTICAST_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_feature_registration_t mc_##x; \
-static void __vnet_add_feature_registration_mc_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vnet_add_feature_registration_mc_##x (void) \
-{ \
- ip4_main_t * im = &ip4_main; \
- mc_##x.next = im->next_feature[VNET_IP_RX_MULTICAST_FEAT]; \
- im->next_feature[VNET_IP_RX_MULTICAST_FEAT] = &mc_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t mc_##x
-
-#define VNET_IP4_TX_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_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_feature[VNET_IP_TX_FEAT]; \
- im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t tx_##x
-
-
/** Global ip4 input node. Errors get attached to ip4 input node. */
extern vlib_node_registration_t ip4_input_node;
extern vlib_node_registration_t ip4_lookup_node;
diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c
index 632925a4a59..6d3dd88b176 100644
--- a/vnet/vnet/ip/ip4_forward.c
+++ b/vnet/vnet/ip/ip4_forward.c
@@ -709,11 +709,7 @@ void
ip4_sw_interface_enable_disable (u32 sw_if_index,
u32 is_enable)
{
- vlib_main_t * vm = vlib_get_main();
ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- u32 ci, cast;
- u32 lookup_feature_index;
vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0);
@@ -731,34 +727,12 @@ ip4_sw_interface_enable_disable (u32 sw_if_index,
if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index])
return;
}
+ vnet_feature_enable_disable ("ip4-unicast", "ip4-lookup", sw_if_index,
+ is_enable, 0, 0);
- for (cast = 0; cast <= VNET_IP_RX_MULTICAST_FEAT; cast++)
- {
- vnet_feature_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];
+ vnet_feature_enable_disable ("ip4-multicast", "ip4-lookup-multicast", sw_if_index,
+ is_enable, 0, 0);
- if (cast == VNET_IP_RX_UNICAST_FEAT)
- lookup_feature_index = im->ip4_unicast_rx_feature_lookup;
- else
- lookup_feature_index = im->ip4_multicast_rx_feature_lookup;
-
- if (is_enable)
- ci = vnet_config_add_feature (vm, vcm,
- ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- ci = vnet_config_del_feature (vm, vcm,
- ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
- }
}
static clib_error_t *
@@ -854,202 +828,140 @@ ip4_add_del_interface_address (vlib_main_t * vm, u32 sw_if_index,
}
/* Built-in ip4 unicast rx feature path definition */
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_flow_classify, static) = {
+VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
+{
+ .arc_name = "ip4-unicast",
+ .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (ip4_flow_classify, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ip4-flow-classify",
- .runs_before = ORDER_CONSTRAINTS {"ip4-inacl", 0},
- .feature_index = &ip4_main.ip4_unicast_rx_feature_flow_classify,
+ .runs_before = VNET_FEATURES ("ip4-inacl"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = {
+VNET_FEATURE_INIT (ip4_inacl, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ip4-inacl",
- .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-rx", 0},
- .feature_index = &ip4_main.ip4_unicast_rx_feature_check_access,
+ .runs_before = VNET_FEATURES ("ip4-source-check-via-rx"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_1, static) = {
+VNET_FEATURE_INIT (ip4_source_check_1, static) = {
+ .arc_name = "ip4-unicast",
.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,
+ .runs_before = VNET_FEATURES ("ip4-source-check-via-any"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_2, static) = {
+VNET_FEATURE_INIT (ip4_source_check_2, static) = {
+ .arc_name = "ip4-unicast",
.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,
+ .runs_before = VNET_FEATURES ("ip4-policer-classify"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_and_port_range_check_rx, static) = {
+VNET_FEATURE_INIT (ip4_source_and_port_range_check_rx, static) = {
+ .arc_name = "ip4-unicast",
.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,
+ .runs_before = VNET_FEATURES ("ip4-policer-classify"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_policer_classify, static) = {
+VNET_FEATURE_INIT (ip4_policer_classify, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ip4-policer-classify",
- .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip4", 0},
- .feature_index =
- &ip4_main.ip4_unicast_rx_feature_policer_classify,
+ .runs_before = VNET_FEATURES ("ipsec-input-ip4"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_ipsec, static) = {
+VNET_FEATURE_INIT (ip4_ipsec, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ipsec-input-ip4",
- .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip4", 0},
- .feature_index = &ip4_main.ip4_unicast_rx_feature_ipsec,
+ .runs_before = VNET_FEATURES ("vpath-input-ip4"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_vpath, static) = {
+VNET_FEATURE_INIT (ip4_vpath, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "vpath-input-ip4",
- .runs_before = ORDER_CONSTRAINTS {"ip4-lookup", 0},
- .feature_index = &ip4_main.ip4_unicast_rx_feature_vpath,
+ .runs_before = VNET_FEATURES ("ip4-lookup"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_lookup, static) = {
+VNET_FEATURE_INIT (ip4_lookup, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ip4-lookup",
- .runs_before = ORDER_CONSTRAINTS {"ip4-drop", 0},
- .feature_index = &ip4_main.ip4_unicast_rx_feature_lookup,
+ .runs_before = VNET_FEATURES ("ip4-drop"),
};
-VNET_IP4_UNICAST_FEATURE_INIT (ip4_drop, static) = {
+VNET_FEATURE_INIT (ip4_drop, static) = {
+ .arc_name = "ip4-unicast",
.node_name = "ip4-drop",
.runs_before = 0, /* not before any other features */
- .feature_index = &ip4_main.ip4_unicast_rx_feature_drop,
};
/* Built-in ip4 multicast rx feature path definition */
-VNET_IP4_MULTICAST_FEATURE_INIT (ip4_vpath_mc, static) = {
+VNET_FEATURE_ARC_INIT (ip4_multicast, static) =
+{
+ .arc_name = "ip4-multicast",
+ .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (ip4_vpath_mc, static) = {
+ .arc_name = "ip4-multicast",
.node_name = "vpath-input-ip4",
- .runs_before = ORDER_CONSTRAINTS {"ip4-lookup-multicast", 0},
- .feature_index = &ip4_main.ip4_multicast_rx_feature_vpath,
+ .runs_before = VNET_FEATURES ("ip4-lookup-multicast"),
};
-VNET_IP4_MULTICAST_FEATURE_INIT (ip4_lookup_mc, static) = {
+VNET_FEATURE_INIT (ip4_lookup_mc, static) = {
+ .arc_name = "ip4-multicast",
.node_name = "ip4-lookup-multicast",
- .runs_before = ORDER_CONSTRAINTS {"ip4-drop", 0},
- .feature_index = &ip4_main.ip4_multicast_rx_feature_lookup,
+ .runs_before = VNET_FEATURES ("ip4-drop"),
};
-VNET_IP4_MULTICAST_FEATURE_INIT (ip4_mc_drop, static) = {
+VNET_FEATURE_INIT (ip4_mc_drop, static) = {
+ .arc_name = "ip4-multicast",
.node_name = "ip4-drop",
.runs_before = 0, /* last feature */
- .feature_index = &ip4_main.ip4_multicast_rx_feature_drop,
};
-static char * rx_feature_start_nodes[] =
- { "ip4-input", "ip4-input-no-checksum"};
-
-static char * tx_feature_start_nodes[] =
+/* Source and port-range check ip4 tx feature path definition */
+VNET_FEATURE_ARC_INIT (ip4_output, static) =
{
- "ip4-rewrite-transit",
- "ip4-midchain",
+ .arc_name = "ip4-output",
+ .start_nodes = VNET_FEATURES ("ip4-rewrite-transit", "ip4-midchain"),
+ .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
};
-/* Source and port-range check ip4 tx feature path definition */
-VNET_IP4_TX_FEATURE_INIT (ip4_source_and_port_range_check_tx, static) = {
+VNET_FEATURE_INIT (ip4_source_and_port_range_check_tx, static) = {
+ .arc_name = "ip4-output",
.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,
-
+ .runs_before = VNET_FEATURES ("interface-output"),
};
/* Built-in ip4 tx feature path definition */
-VNET_IP4_TX_FEATURE_INIT (interface_output, static) = {
+VNET_FEATURE_INIT (ip4_interface_output, static) = {
+ .arc_name = "ip4-output",
.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;
- vnet_feature_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 = vnet_feature_arc_init (vm, vcm,
- feature_start_nodes,
- feature_start_len,
- im->next_feature[cast],
- &im->feature_nodes[cast])))
- return error;
- }
-
- return 0;
-}
static clib_error_t *
ip4_sw_interface_add_del (vnet_main_t * vnm,
u32 sw_if_index,
u32 is_add)
{
- vlib_main_t * vm = vnm->vlib_main;
ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- u32 ci, cast;
- u32 feature_index;
/* Fill in lookup tables with default table (0). */
vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
- for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
- {
- vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast];
- vnet_config_main_t * vcm = &cm->config_main;
+ vnet_feature_enable_disable ("ip4-unicast", "ip4-drop", sw_if_index,
+ is_add, 0, 0);
- 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];
+ vnet_feature_enable_disable ("ip4-multicast", "ip4-drop", sw_if_index,
+ is_add, 0, 0);
- if (cast == VNET_IP_RX_UNICAST_FEAT)
- feature_index = im->ip4_unicast_rx_feature_drop;
- else if (cast == VNET_IP_RX_MULTICAST_FEAT)
- feature_index = im->ip4_multicast_rx_feature_drop;
- else
- feature_index = im->ip4_tx_feature_interface_output;
-
- if (is_add)
- ci = vnet_config_add_feature (vm, vcm,
- ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- {
- ci = vnet_config_del_feature (vm, vcm, ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- if (vec_len(im->ip_enabled_by_sw_if_index) > sw_if_index)
- im->ip_enabled_by_sw_if_index[sw_if_index] = 0;
- }
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
- /*
- * note: do not update the tx feature count here.
- */
- }
+ vnet_feature_enable_disable ("ip4-output", "interface-output", sw_if_index,
+ is_add, 0, 0);
return /* no error */ 0;
}
@@ -1066,6 +978,9 @@ ip4_lookup_init (vlib_main_t * vm)
clib_error_t * error;
uword i;
+ if ((error = vlib_call_init_function (vm, vnet_feature_init)))
+ return error;
+
for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
{
u32 m;
@@ -1114,8 +1029,6 @@ ip4_lookup_init (vlib_main_t * vm)
"ip4 arp");
}
- error = ip4_feature_init (vm, im);
-
return error;
}
@@ -2184,7 +2097,6 @@ 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;
- vnet_feature_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,18 +2274,8 @@ ip4_rewrite_inline (vlib_main_t * vm,
vnet_buffer (p0)->sw_if_index[VLIB_TX] =
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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index0, &next0, p0);
}
if (PREDICT_TRUE(error1 == IP4_ERROR_NONE))
{
@@ -2384,18 +2286,8 @@ ip4_rewrite_inline (vlib_main_t * vm,
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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index1, &next1, p1);
}
/* Guess we are only writing on simple Ethernet header. */
@@ -2525,18 +2417,9 @@ ip4_rewrite_inline (vlib_main_t * vm,
adj0->sub_type.midchain.fixup_func(vm, adj0, p0);
}
- 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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index0, &next0, p0);
+
}
if (rewrite_for_locally_received_packets)
diff --git a/vnet/vnet/ip/ip4_input.c b/vnet/vnet/ip/ip4_input.c
index 268f7afa828..a3620de8b42 100644
--- a/vnet/vnet/ip/ip4_input.c
+++ b/vnet/vnet/ip/ip4_input.c
@@ -108,11 +108,10 @@ ip4_input_inline (vlib_main_t * vm,
{
vlib_buffer_t * p0, * p1;
ip4_header_t * ip0, * ip1;
- vnet_feature_config_main_t * cm0, * cm1;
- u32 sw_if_index0, pi0, ip_len0, cur_len0, next0;
- u32 sw_if_index1, pi1, ip_len1, cur_len1, next1;
+ u32 sw_if_index0, pi0, ip_len0, cur_len0, next0 = 0;
+ u32 sw_if_index1, pi1, ip_len1, cur_len1, next1 = 0;
i32 len_diff0, len_diff1;
- u8 error0, error1, cast0, cast1;
+ u8 error0, error1, arc0, arc1;
/* Prefetch next iteration. */
{
@@ -144,26 +143,14 @@ 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_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->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);
+ arc0 = ip4_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
+ arc1 = ip4_address_is_multicast (&ip1->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
- vnet_get_config_data (&cm0->config_main,
- &p0->current_config_index,
- &next0,
- /* # bytes of config data */ 0);
- vnet_get_config_data (&cm1->config_main,
- &p1->current_config_index,
- &next1,
- /* # bytes of config data */ 0);
+ vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
+ vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1);
@@ -195,8 +182,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_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0;
- error1 = (ip1->ttl < 1 && cast1 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error1;
+ error0 = (ip0->ttl < 1 && arc0 == lm->ucast_feature_arc_index) ? IP4_ERROR_TIME_EXPIRED : error0;
+ error1 = (ip1->ttl < 1 && arc1 == lm->ucast_feature_arc_index) ? IP4_ERROR_TIME_EXPIRED : error1;
/* Verify lengths. */
ip_len0 = clib_net_to_host_u16 (ip0->length);
@@ -245,10 +232,9 @@ ip4_input_inline (vlib_main_t * vm,
{
vlib_buffer_t * p0;
ip4_header_t * ip0;
- vnet_feature_config_main_t * cm0;
- u32 sw_if_index0, pi0, ip_len0, cur_len0, next0;
+ u32 sw_if_index0, pi0, ip_len0, cur_len0, next0 = 0;
i32 len_diff0;
- u8 error0, cast0;
+ u8 error0, arc0;
pi0 = from[0];
to_next[0] = pi0;
@@ -262,14 +248,9 @@ 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_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);
+ arc0 = ip4_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
- vnet_get_config_data (&cm0->config_main,
- &p0->current_config_index,
- &next0,
- /* # bytes of config data */ 0);
+ vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
@@ -294,7 +275,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_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0;
+ error0 = (ip0->ttl < 1 && arc0 == lm->ucast_feature_arc_index) ? 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 8b69522aebe..28dabeb3f41 100644
--- a/vnet/vnet/ip/ip4_source_and_port_range_check.c
+++ b/vnet/vnet/ip/ip4_source_and_port_range_check.c
@@ -155,11 +155,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
vlib_frame_t * frame, int is_tx)
{
ip4_main_t *im = &ip4_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_config_main_t *rx_cm =
- &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_feature_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;
@@ -434,6 +429,7 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
udp_header_t *udp0;
const protocol_port_range_dpo_t *ppr_dpo0 = NULL;
const dpo_id_t *dpo;
+ u32 sw_if_index0;
bi0 = from[0];
to_next[0] = bi0;
@@ -443,28 +439,17 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- fib_index0 =
- vec_elt (im->fib_index_by_sw_if_index,
- vnet_buffer (b0)->sw_if_index[VLIB_RX]);
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
if (is_tx)
vlib_buffer_advance (b0, sizeof (ethernet_header_t));
ip0 = vlib_buffer_get_current (b0);
- 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]));
- }
+ c0 = vnet_feature_next_with_data (sw_if_index0, &next0,
+ b0, sizeof (c0[0]));
/* we can't use the default VRF here... */
for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
@@ -570,7 +555,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm,
IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK,
good_packets);
return frame->n_vectors;
- return 0;
}
static uword
@@ -639,15 +623,7 @@ set_ip_source_and_port_range_check (vlib_main_t * vm,
u32 * fib_index,
u32 sw_if_index, u32 is_add)
{
- ip4_main_t *im = &ip4_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_config_main_t *rx_cm =
- &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_feature_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;
int rv = 0;
int i;
@@ -660,36 +636,20 @@ set_ip_source_and_port_range_check (vlib_main_t * vm,
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;
+ vnet_feature_enable_disable ("ip4-unicast",
+ "ip4-source-and-port-range-check-rx",
+ sw_if_index, is_add, &config,
+ sizeof (config));
}
/* 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 (tx_cm->config_index_by_sw_if_index, sw_if_index);
-
- 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);
+ vnet_feature_enable_disable ("ip4-output",
+ "ip4-source-and-port-range-check-tx",
+ sw_if_index, is_add, &config,
+ sizeof (config));
}
return rv;
}
diff --git a/vnet/vnet/ip/ip4_source_check.c b/vnet/vnet/ip/ip4_source_check.c
index 62ebcb7268a..f7900d304c2 100644
--- a/vnet/vnet/ip/ip4_source_check.c
+++ b/vnet/vnet/ip/ip4_source_check.c
@@ -88,9 +88,6 @@ ip4_source_check_inline (vlib_main_t * vm,
vlib_frame_t * frame,
ip4_source_check_type_t source_check_type)
{
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- vnet_feature_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);
@@ -149,14 +146,8 @@ ip4_source_check_inline (vlib_main_t * vm,
ip0 = vlib_buffer_get_current (p0);
ip1 = vlib_buffer_get_current (p1);
- c0 = vnet_get_config_data (&cm->config_main,
- &p0->current_config_index,
- &next0,
- sizeof (c0[0]));
- c1 = vnet_get_config_data (&cm->config_main,
- &p1->current_config_index,
- &next1,
- sizeof (c1[0]));
+ c0 = vnet_feature_next_with_data(vnet_buffer (p0)->sw_if_index[VLIB_RX] , &next0, p0, sizeof (c0[0]));
+ c1 = vnet_feature_next_with_data(vnet_buffer (p1)->sw_if_index[VLIB_RX] , &next1, p1, sizeof (c1[0]));
mtrie0 = &ip4_fib_get (c0->fib_index)->mtrie;
mtrie1 = &ip4_fib_get (c1->fib_index)->mtrie;
@@ -228,10 +219,7 @@ ip4_source_check_inline (vlib_main_t * vm,
p0 = vlib_get_buffer (vm, pi0);
ip0 = vlib_buffer_get_current (p0);
- c0 = vnet_get_config_data (&cm->config_main,
- &p0->current_config_index,
- &next0,
- sizeof (c0[0]));
+ c0 = vnet_feature_next_with_data(vnet_buffer (p0)->sw_if_index[VLIB_RX] , &next0, p0, sizeof (c0[0]));
mtrie0 = &ip4_fib_get (c0->fib_index)->mtrie;
@@ -334,16 +322,13 @@ set_ip_source_check (vlib_main_t * vm,
unformat_input_t _line_input, * line_input = &_line_input;
vnet_main_t * vnm = vnet_get_main();
ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- vnet_feature_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;
+ u32 sw_if_index, is_del;
ip4_source_check_config_t config;
- u32 feature_index;
+ char * feature_name = "ip4-source-check-via-rx";
sw_if_index = ~0;
is_del = 0;
- feature_index = im->ip4_unicast_rx_feature_source_reachable_via_rx;
if (! unformat_user (input, unformat_line_input, line_input))
return 0;
@@ -354,10 +339,8 @@ set_ip_source_check (vlib_main_t * vm,
;
else if (unformat (line_input, "del"))
is_del = 1;
- else if (unformat (line_input, "strict"))
- feature_index = im->ip4_unicast_rx_feature_source_reachable_via_rx;
else if (unformat (line_input, "loose"))
- feature_index = im->ip4_unicast_rx_feature_source_reachable_via_any;
+ feature_name = "ip4-source-check-via-any";
else
{
error = unformat_parse_error (line_input);
@@ -373,17 +356,8 @@ set_ip_source_check (vlib_main_t * vm,
}
config.fib_index = im->fib_index_by_sw_if_index[sw_if_index];
- ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
- ci = (is_del
- ? vnet_config_del_feature
- : vnet_config_add_feature)
- (vm, &rx_cm->config_main,
- ci,
- feature_index,
- &config,
- sizeof (config));
- rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
-
+ vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index,
+ is_del == 0, &config, sizeof (config));
done:
return error;
}
diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h
index 8b3b9973bf4..428a16f60aa 100644
--- a/vnet/vnet/ip/ip6.h
+++ b/vnet/vnet/ip/ip6.h
@@ -46,7 +46,6 @@
#include <vnet/ip/ip6_packet.h>
#include <vnet/ip/ip6_hop_by_hop_packet.h>
#include <vnet/ip/lookup.h>
-#include <vnet/feature/feature.h>
#include <stdbool.h>
#include <vppinfra/bihash_24_8.h>
#include <vppinfra/bihash_template.h>
@@ -160,30 +159,6 @@ typedef struct ip6_main_t {
u32 lookup_table_nbuckets;
uword lookup_table_size;
- /* feature path configuration lists */
- vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT];
-
- /* Built-in unicast feature path indices, see vnet_feature_arc_init(...) */
- u32 ip6_unicast_rx_feature_check_access;
- u32 ip6_unicast_rx_feature_policer_classify;
- u32 ip6_unicast_rx_feature_flow_classify;
- u32 ip6_unicast_rx_feature_ipsec;
- u32 ip6_unicast_rx_feature_l2tp_decap;
- u32 ip6_unicast_rx_feature_vpath;
- u32 ip6_unicast_rx_feature_lookup;
- u32 ip6_unicast_rx_feature_drop;
-
- /* Built-in multicast feature path indices */
- u32 ip6_multicast_rx_feature_drop;
- 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_IP_FEAT];
-
/* Seed for Jenkins hash used to compute ip6 flow hash. */
u32 flow_hash_seed;
@@ -201,43 +176,6 @@ typedef struct ip6_main_t {
/* Global ip6 main structure. */
extern ip6_main_t ip6_main;
-#define VNET_IP6_UNICAST_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_feature_registration_t uc_##x; \
-static void __vnet_add_feature_registration_uc_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vnet_add_feature_registration_uc_##x (void) \
-{ \
- ip6_main_t * im = &ip6_main; \
- uc_##x.next = im->next_feature[VNET_IP_RX_UNICAST_FEAT]; \
- im->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t uc_##x
-
-#define VNET_IP6_MULTICAST_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_feature_registration_t mc_##x; \
-static void __vnet_add_feature_registration_mc_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vnet_add_feature_registration_mc_##x (void) \
-{ \
- ip6_main_t * im = &ip6_main; \
- mc_##x.next = im->next_feature[VNET_IP_RX_MULTICAST_FEAT]; \
- im->next_feature[VNET_IP_RX_MULTICAST_FEAT] = &mc_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t mc_##x
-
-#define VNET_IP6_TX_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_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_feature[VNET_IP_TX_FEAT]; \
- im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \
-} \
-__VA_ARGS__ vnet_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 53d13db2be3..899203c84b3 100644
--- a/vnet/vnet/ip/ip6_forward.c
+++ b/vnet/vnet/ip/ip6_forward.c
@@ -412,11 +412,7 @@ void
ip6_sw_interface_enable_disable (u32 sw_if_index,
u32 is_enable)
{
- vlib_main_t * vm = vlib_get_main();
ip6_main_t * im = &ip6_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- u32 ci, cast;
- u32 lookup_feature_index;
vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0);
@@ -435,34 +431,12 @@ ip6_sw_interface_enable_disable (u32 sw_if_index,
return;
}
- for (cast = 0; cast <= VNET_IP_RX_MULTICAST_FEAT; cast++)
- {
- vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast];
- vnet_config_main_t * vcm = &cm->config_main;
+ vnet_feature_enable_disable ("ip6-unicast", "ip6-lookup", sw_if_index,
+ is_enable, 0, 0);
- 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_IP_RX_UNICAST_FEAT)
- lookup_feature_index = im->ip6_unicast_rx_feature_lookup;
- else
- lookup_feature_index = im->ip6_multicast_rx_feature_lookup;
-
- if (is_enable)
- ci = vnet_config_add_feature (vm, vcm,
- ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- ci = vnet_config_del_feature (vm, vcm,
- ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
+ vnet_feature_enable_disable ("ip6-multicast", "ip6-lookup", sw_if_index,
+ is_enable, 0, 0);
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
- }
}
/* get first interface address */
@@ -584,172 +558,115 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm,
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_flow_classify, static) = {
+VNET_FEATURE_ARC_INIT (ip6_unicast, static) =
+{
+ .arc_name = "ip6-unicast",
+ .start_nodes = VNET_FEATURES ("ip6-input"),
+ .arc_index_ptr = &ip6_main.lookup_main.ucast_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (ip6_flow_classify, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ip6-flow-classify",
- .runs_before = ORDER_CONSTRAINTS {"ip6-inacl", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_flow_classify,
+ .runs_before = VNET_FEATURES ("ip6-inacl"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_inacl, static) = {
+VNET_FEATURE_INIT (ip6_inacl, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ip6-inacl",
- .runs_before = ORDER_CONSTRAINTS {"ip6-policer-classify", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_check_access,
+ .runs_before = VNET_FEATURES ("ip6-policer-classify"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_policer_classify, static) = {
+VNET_FEATURE_INIT (ip6_policer_classify, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ip6-policer-classify",
- .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip6", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_policer_classify,
+ .runs_before = VNET_FEATURES ("ipsec-input-ip6"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_ipsec, static) = {
+VNET_FEATURE_INIT (ip6_ipsec, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ipsec-input-ip6",
- .runs_before = ORDER_CONSTRAINTS {"l2tp-decap", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_ipsec,
+ .runs_before = VNET_FEATURES ("l2tp-decap"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_l2tp, static) = {
+VNET_FEATURE_INIT (ip6_l2tp, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "l2tp-decap",
- .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip6", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_l2tp_decap,
+ .runs_before = VNET_FEATURES ("vpath-input-ip6"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_vpath, static) = {
+VNET_FEATURE_INIT (ip6_vpath, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "vpath-input-ip6",
- .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_vpath,
+ .runs_before = VNET_FEATURES ("ip6-lookup"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_lookup, static) = {
+VNET_FEATURE_INIT (ip6_lookup, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ip6-lookup",
- .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0},
- .feature_index = &ip6_main.ip6_unicast_rx_feature_lookup,
+ .runs_before = VNET_FEATURES ("ip6-drop"),
};
-VNET_IP6_UNICAST_FEATURE_INIT (ip6_drop, static) = {
+VNET_FEATURE_INIT (ip6_drop, static) = {
+ .arc_name = "ip6-unicast",
.node_name = "ip6-drop",
.runs_before = 0, /*last feature*/
- .feature_index = &ip6_main.ip6_unicast_rx_feature_drop,
};
/* Built-in ip6 multicast rx feature path definition (none now) */
-VNET_IP6_MULTICAST_FEATURE_INIT (ip6_vpath_mc, static) = {
+VNET_FEATURE_ARC_INIT (ip6_multicast, static) =
+{
+ .arc_name = "ip6-multicast",
+ .start_nodes = VNET_FEATURES ("ip6-input"),
+ .arc_index_ptr = &ip6_main.lookup_main.mcast_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (ip6_vpath_mc, static) = {
+ .arc_name = "ip6-multicast",
.node_name = "vpath-input-ip6",
- .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0},
- .feature_index = &ip6_main.ip6_multicast_rx_feature_vpath,
+ .runs_before = VNET_FEATURES ("ip6-lookup"),
};
-VNET_IP6_MULTICAST_FEATURE_INIT (ip6_lookup, static) = {
+VNET_FEATURE_INIT (ip6_mc_lookup, static) = {
+ .arc_name = "ip6-multicast",
.node_name = "ip6-lookup",
- .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0},
- .feature_index = &ip6_main.ip6_multicast_rx_feature_lookup,
+ .runs_before = VNET_FEATURES ("ip6-drop"),
};
-VNET_IP6_MULTICAST_FEATURE_INIT (ip6_drop_mc, static) = {
+VNET_FEATURE_INIT (ip6_drop_mc, static) = {
+ .arc_name = "ip6-multicast",
.node_name = "ip6-drop",
.runs_before = 0, /* last feature */
- .feature_index = &ip6_main.ip6_multicast_rx_feature_drop,
};
-static char * rx_feature_start_nodes[] =
- {"ip6-input"};
-
-static char * tx_feature_start_nodes[] =
+/* Built-in ip4 tx feature path definition */
+VNET_FEATURE_ARC_INIT (ip6_output, static) =
{
- "ip6-rewrite",
- "ip6-midchain",
+ .arc_name = "ip6-output",
+ .start_nodes = VNET_FEATURES ("ip6-rewrite", "ip6-midchain"),
+ .arc_index_ptr = &ip6_main.lookup_main.output_feature_arc_index,
};
-/* Built-in ip4 tx feature path definition */
-VNET_IP6_TX_FEATURE_INIT (interface_output, static) = {
+VNET_FEATURE_INIT (ip6_interface_output, static) = {
+ .arc_name = "ip6-output",
.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;
- vnet_feature_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 = vnet_feature_arc_init (vm, vcm,
- feature_start_nodes,
- feature_start_len,
- im->next_feature[cast],
- &im->feature_nodes[cast])))
- return error;
- }
- return 0;
-}
-
clib_error_t *
ip6_sw_interface_add_del (vnet_main_t * vnm,
u32 sw_if_index,
u32 is_add)
{
- vlib_main_t * vm = vnm->vlib_main;
- ip6_main_t * im = &ip6_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- u32 ci, cast;
- u32 feature_index;
+ vnet_feature_enable_disable ("ip6-unicast", "ip6-drop", sw_if_index,
+ is_add, 0, 0);
- for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
- {
- vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast];
- vnet_config_main_t * vcm = &cm->config_main;
+ vnet_feature_enable_disable ("ip6-multicast", "ip6-drop", sw_if_index,
+ is_add, 0, 0);
- 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];
+ vnet_feature_enable_disable ("ip6-output", "interface-output", sw_if_index,
+ is_add, 0, 0);
- if (cast == VNET_IP_RX_UNICAST_FEAT)
- feature_index = im->ip6_unicast_rx_feature_drop;
- else if (cast == VNET_IP_RX_MULTICAST_FEAT)
- feature_index = im->ip6_multicast_rx_feature_drop;
- else
- feature_index = im->ip6_tx_feature_interface_output;
-
- if (is_add)
- ci = vnet_config_add_feature (vm, vcm,
- ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- {
- ci = vnet_config_del_feature (vm, vcm, ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- if (vec_len(im->ip_enabled_by_sw_if_index) > sw_if_index)
- im->ip_enabled_by_sw_if_index[sw_if_index] = 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;
}
@@ -1835,7 +1752,6 @@ 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;
- vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT];
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
@@ -1969,18 +1885,8 @@ ip6_rewrite_inline (vlib_main_t * vm,
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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index0, &next0, p0);
}
if (PREDICT_TRUE(error1 == IP6_ERROR_NONE))
{
@@ -1992,18 +1898,8 @@ ip6_rewrite_inline (vlib_main_t * vm,
tx_sw_if_index1;
next1 = adj1[0].rewrite_header.next_index;
- 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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index1, &next1, p1);
}
/* Guess we are only writing on simple Ethernet header. */
@@ -2102,18 +1998,8 @@ ip6_rewrite_inline (vlib_main_t * vm,
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);
- }
+ vnet_feature_arc_start(lm->output_feature_arc_index,
+ tx_sw_if_index0, &next0, p0);
}
if (is_midchain)
@@ -2661,6 +2547,9 @@ ip6_lookup_init (vlib_main_t * vm)
clib_error_t * error;
uword i;
+ if ((error = vlib_call_init_function (vm, vnet_feature_init)))
+ return error;
+
for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
{
u32 j, i0, i1;
@@ -2730,8 +2619,6 @@ ip6_lookup_init (vlib_main_t * vm)
"ip6 neighbor discovery");
}
- error = ip6_feature_init (vm, im);
-
return error;
}
@@ -3209,58 +3096,3 @@ 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;
-}
-
-/*?
- * Enable or disable the output feature on an interface.
- *
- * @todo Need a more detailed description.
- *
- * @cliexpar
- * Example of how to enable the output feature on an interface:
- * @cliexcmd{set interface ip6 output feature GigabitEthernet2/0/0}
- * Example of how to disable the output feature on an interface:
- * @cliexcmd{set interface ip6 output feature GigabitEthernet2/0/0 del}
-?*/
-/* *INDENT-OFF* */
-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 ip6 output feature <interface> [del]",
-};
-/* *INDENT-ON* */
-
-#endif /* TEST_CODE */
diff --git a/vnet/vnet/ip/ip6_input.c b/vnet/vnet/ip/ip6_input.c
index a355abfdb39..f6d56be2829 100644
--- a/vnet/vnet/ip/ip6_input.c
+++ b/vnet/vnet/ip/ip6_input.c
@@ -105,10 +105,9 @@ ip6_input (vlib_main_t * vm,
{
vlib_buffer_t * p0, * p1;
ip6_header_t * ip0, * ip1;
- vnet_feature_config_main_t * cm0, * cm1;
- u32 pi0, sw_if_index0, next0;
- u32 pi1, sw_if_index1, next1;
- u8 error0, error1, cast0, cast1;
+ u32 pi0, sw_if_index0, next0 = 0;
+ u32 pi1, sw_if_index1, next1 = 0;
+ u8 error0, error1, arc0, arc1;
/* Prefetch next iteration. */
{
@@ -143,26 +142,14 @@ 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_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->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);
+ arc0 = ip6_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
+ arc1 = ip6_address_is_multicast (&ip1->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0;
- vnet_get_config_data (&cm0->config_main,
- &p0->current_config_index,
- &next0,
- /* # bytes of config data */ 0);
- vnet_get_config_data (&cm1->config_main,
- &p1->current_config_index,
- &next1,
- /* # bytes of config data */ 0);
+ vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
+ vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1);
@@ -217,9 +204,8 @@ ip6_input (vlib_main_t * vm,
{
vlib_buffer_t * p0;
ip6_header_t * ip0;
- vnet_feature_config_main_t * cm0;
- u32 pi0, sw_if_index0, next0;
- u8 error0, cast0;
+ u32 pi0, sw_if_index0, next0 = 0;
+ u8 error0, arc0;
pi0 = from[0];
to_next[0] = pi0;
@@ -232,15 +218,9 @@ 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_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);
+ arc0 = ip6_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index;
vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0;
-
- vnet_get_config_data (&cm0->config_main,
- &p0->current_config_index,
- &next0,
- /* # bytes of config data */ 0);
+ vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
error0 = IP6_ERROR_NONE;
diff --git a/vnet/vnet/ip/ip_init.c b/vnet/vnet/ip/ip_init.c
index c89f60c09d7..d87a92efdc6 100644
--- a/vnet/vnet/ip/ip_init.c
+++ b/vnet/vnet/ip/ip_init.c
@@ -144,24 +144,3 @@ do { \
VLIB_INIT_FUNCTION (ip_main_init);
-void
-vnet_config_update_tx_feature_count (ip_lookup_main_t * lm,
- vnet_feature_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 239ca6818be..7f9b9846cd9 100644
--- a/vnet/vnet/ip/lookup.h
+++ b/vnet/vnet/ip/lookup.h
@@ -337,12 +337,6 @@ typedef struct ip_lookup_main_t {
/** load-balance packet/byte counters indexed by LB index. */
vlib_combined_counter_main_t load_balance_counters;
- /** 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;
-
/** Pool of addresses that are assigned to interfaces. */
ip_interface_address_t * if_address_pool;
@@ -356,8 +350,10 @@ 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 unicast, multicast, tx interface/feature configuration. */
- vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT];
+ /** Feature arc indices */
+ u8 mcast_feature_arc_index;
+ u8 ucast_feature_arc_index;
+ u8 output_feature_arc_index;
/** 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 3f2bad9fc1f..7d459f6b1ab 100644
--- a/vnet/vnet/ipsec/ipsec.c
+++ b/vnet/vnet/ipsec/ipsec.c
@@ -40,11 +40,9 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id,
int is_add)
{
ipsec_main_t *im = &ipsec_main;
- ip_lookup_main_t *lm;
- vnet_feature_config_main_t *rx_cm;
ip4_ipsec_config_t config;
- u32 spd_index, ci;
+ u32 spd_index;
uword *p;
p = hash_get (im->spd_index_by_spd_id, spd_id);
@@ -74,29 +72,10 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id,
INTF_OUTPUT_FEAT_IPSEC, is_add);
/* enable IPsec on RX */
- config.spd_index = spd_index;
-
- /* IPv4 */
- lm = &ip4_main.lookup_main;
- rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
-
- 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, ip4_main.ip4_unicast_rx_feature_ipsec, &config, sizeof (config));
- rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
-
- /* IPv6 */
- lm = &ip6_main.lookup_main;
- rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
-
- 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, ip6_main.ip6_unicast_rx_feature_ipsec, &config, sizeof (config));
- rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ vnet_feature_enable_disable ("ip4-unicast", "ipsec-input-ip4", sw_if_index,
+ is_add, &config, sizeof (config));
+ vnet_feature_enable_disable ("ip6-unicast", "ipsec-input-ip6", sw_if_index,
+ is_add, &config, sizeof (config));
return 0;
}
diff --git a/vnet/vnet/ipsec/ipsec_input.c b/vnet/vnet/ipsec/ipsec_input.c
index 8b75c1255a7..809fe6da65d 100644
--- a/vnet/vnet/ipsec/ipsec_input.c
+++ b/vnet/vnet/ipsec/ipsec_input.c
@@ -18,6 +18,7 @@
#include <vnet/vnet.h>
#include <vnet/api_errno.h>
#include <vnet/ip/ip.h>
+#include <vnet/feature/feature.h>
#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/esp.h>
@@ -187,10 +188,6 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
{
- ip4_main_t *i4m = &ip4_main;
- ip_lookup_main_t *lm = &i4m->lookup_main;
- vnet_feature_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;
@@ -222,9 +219,10 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
- c0 = vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0, sizeof (c0[0]));
+ c0 =
+ vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index
+ [VLIB_RX], &next0, b0,
+ sizeof (c0[0]));
spd0 = pool_elt_at_index (im->spds, c0->spd_index);
@@ -323,10 +321,6 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn)
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
{
- ip6_main_t *i6m = &ip6_main;
- ip_lookup_main_t *lm = &i6m->lookup_main;
- vnet_feature_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;
@@ -359,9 +353,10 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn)
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
- c0 = vnet_get_config_data (&cm->config_main,
- &b0->current_config_index,
- &next0, sizeof (c0[0]));
+ c0 =
+ vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index
+ [VLIB_RX], &next0, b0,
+ sizeof (c0[0]));
spd0 = pool_elt_at_index (im->spds, c0->spd_index);
diff --git a/vnet/vnet/l2tp/decap.c b/vnet/vnet/l2tp/decap.c
index e041fdf2cd4..e91e6fbb96f 100644
--- a/vnet/vnet/l2tp/decap.c
+++ b/vnet/vnet/l2tp/decap.c
@@ -218,15 +218,7 @@ done:
else
{
/* Go to next node on the ip6 configuration chain */
- ip6_main_t *im = &ip6_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_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,
- &b->current_config_index,
- &next_index, sizeof (c0[0]));
+ vnet_feature_next (session->sw_if_index, &next_index, b);
}
}
diff --git a/vnet/vnet/l2tp/l2tp.c b/vnet/vnet/l2tp/l2tp.c
index c6da86607e3..a4531dab85c 100644
--- a/vnet/vnet/l2tp/l2tp.c
+++ b/vnet/vnet/l2tp/l2tp.c
@@ -600,26 +600,12 @@ int
l2tpv3_interface_enable_disable (vnet_main_t * vnm,
u32 sw_if_index, int enable_disable)
{
- ip6_main_t *im = &ip6_main;
- ip_lookup_main_t *lm = &im->lookup_main;
- vnet_feature_config_main_t *rx_cm =
- &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- u32 ci;
- ip6_l2tpv3_config_t config;
- u32 feature_index;
if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
- feature_index = im->ip6_unicast_rx_feature_l2tp_decap;
-
- ci = rx_cm->config_index_by_sw_if_index[sw_if_index];
- ci = (enable_disable
- ? vnet_config_add_feature
- : vnet_config_del_feature)
- (vlib_get_main (), &rx_cm->config_main,
- ci, feature_index, &config, sizeof (config));
- rx_cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ vnet_feature_enable_disable ("ip6-unicast", "l2tp-decap", sw_if_index,
+ enable_disable, 0, 0);
return 0;
}
diff --git a/vnet/vnet/mpls/interface.c b/vnet/vnet/mpls/interface.c
index 9fd93ff8701..a0f6f2f2474 100644
--- a/vnet/vnet/mpls/interface.c
+++ b/vnet/vnet/mpls/interface.c
@@ -276,12 +276,7 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
u32 sw_if_index,
u8 is_enable)
{
- vlib_main_t * vm = vlib_get_main();
- vnet_feature_config_main_t * cm = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_config_main_t * vcm = &cm->config_main;
- u32 lookup_feature_index;
fib_node_index_t lfib_index;
- u32 ci;
vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
@@ -308,24 +303,9 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
FIB_PROTOCOL_MPLS);
}
- 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];
+ vnet_feature_enable_disable ("mpls-input", "mpls-lookup", sw_if_index,
+ is_enable, 0, 0);
- lookup_feature_index = mm->mpls_rx_feature_lookup;
-
- if (is_enable)
- ci = vnet_config_add_feature (vm, vcm,
- ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- ci = vnet_config_del_feature (vm, vcm, ci,
- lookup_feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
-
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
}
u8 * format_mpls_encap_index (u8 * s, va_list * args)
diff --git a/vnet/vnet/mpls/mpls.h b/vnet/vnet/mpls/mpls.h
index 85973d862dc..59fc761ea2c 100644
--- a/vnet/vnet/mpls/mpls.h
+++ b/vnet/vnet/mpls/mpls.h
@@ -94,14 +94,6 @@ typedef struct {
/** A hash table to lookup the mpls_fib by table ID */
uword *fib_index_by_table_id;
- /* rx/tx interface/feature configuration. */
- vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT];
-
- /* Built-in unicast feature path indices, see vnet_feature_arc_init(...) */
- u32 mpls_rx_feature_lookup;
- u32 mpls_rx_feature_not_enabled;
- u32 mpls_tx_feature_interface_output;
-
/* pool of ethernet tunnel instances */
mpls_eth_tunnel_t *eth_tunnels;
u32 * free_eth_sw_if_indices;
@@ -114,11 +106,9 @@ typedef struct {
u32 ip4_classify_mpls_policy_encap_next_index;
u32 ip6_classify_mpls_policy_encap_next_index;
- /* feature path configuration lists */
- vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT];
-
- /* Save feature results for show command */
- char **feature_nodes[VNET_N_IP_FEAT];
+ /* Feature arc indices */
+ u8 input_feature_arc_index;
+ u8 output_feature_arc_index;
/* IP4 enabled count by software interface */
u8 * mpls_enabled_by_sw_if_index;
@@ -130,30 +120,6 @@ typedef struct {
extern mpls_main_t mpls_main;
-#define VNET_MPLS_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_feature_registration_t uc_##x; \
-static void __vnet_add_feature_registration_uc_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vnet_add_feature_registration_uc_##x (void) \
-{ \
- mpls_main_t * mm = &mpls_main; \
- uc_##x.next = mm->next_feature[VNET_IP_RX_UNICAST_FEAT]; \
- mm->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t uc_##x
-
-#define VNET_MPLS_TX_FEATURE_INIT(x,...) \
- __VA_ARGS__ vnet_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) \
-{ \
- mpls_main_t * mm = &mpls_main; \
- tx_##x.next = mm->next_feature[VNET_IP_TX_FEAT]; \
- mm->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \
-} \
-__VA_ARGS__ vnet_feature_registration_t tx_##x
-
extern clib_error_t * mpls_feature_init(vlib_main_t * vm);
format_function_t format_mpls_protocol;
diff --git a/vnet/vnet/mpls/mpls_features.c b/vnet/vnet/mpls/mpls_features.c
index 2f98867cf90..a7593c55b09 100644
--- a/vnet/vnet/mpls/mpls_features.c
+++ b/vnet/vnet/mpls/mpls_features.c
@@ -100,116 +100,57 @@ VLIB_REGISTER_NODE (mpls_not_enabled_node) = {
VLIB_NODE_FUNCTION_MULTIARCH (mpls_not_enabled_node, mpls_not_enabled)
-VNET_MPLS_FEATURE_INIT (mpls_lookup, static) = {
+VNET_FEATURE_ARC_INIT (mpls_input, static) =
+{
+ .arc_name = "mpls-input",
+ .start_nodes = VNET_FEATURES ("mpls-input"),
+ .arc_index_ptr = &mpls_main.input_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (mpls_lookup, static) = {
+ .arc_name = "mpls-input",
.node_name = "mpls-lookup",
- .runs_before = ORDER_CONSTRAINTS {"mpls-not-enabled", 0},
- .feature_index = &mpls_main.mpls_rx_feature_lookup,
+ .runs_before = VNET_FEATURES ("mpls-not-enabled"),
};
-VNET_MPLS_FEATURE_INIT (mpls_not_enabled, static) = {
+VNET_FEATURE_INIT (mpls_not_enabled, static) = {
+ .arc_name = "mpls-input",
.node_name = "mpls-not-enabled",
- .runs_before = ORDER_CONSTRAINTS {0}, /* not before any other features */
- .feature_index = &mpls_main.mpls_rx_feature_not_enabled,
+ .runs_before = VNET_FEATURES (0), /* not before any other features */
+};
+
+VNET_FEATURE_ARC_INIT (mpls_output, static) =
+{
+ .arc_name = "mpls-output",
+ .start_nodes = VNET_FEATURES ("mpls-output", "mpls-midchain"),
+ .arc_index_ptr = &mpls_main.output_feature_arc_index,
};
/* Built-in ip4 tx feature path definition */
-VNET_MPLS_TX_FEATURE_INIT (interface_output, static) = {
+VNET_FEATURE_INIT (mpls_interface_output, static) = {
+ .arc_name = "mpls-output",
.node_name = "interface-output",
.runs_before = 0, /* not before any other features */
- .feature_index = &mpls_main.mpls_tx_feature_interface_output,
};
-
-static char * rx_feature_start_nodes[] =
-{
- "mpls-input",
-};
-static char * tx_feature_start_nodes[] =
-{
- "mpls-output",
- "mpls-midchain",
-};
-
-clib_error_t *
-mpls_feature_init (vlib_main_t * vm)
-{
- vnet_feature_config_main_t * cm = &mpls_main.feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_config_main_t * vcm = &cm->config_main;
- clib_error_t *error;
-
- error = vnet_feature_arc_init
- (vm, vcm, rx_feature_start_nodes,
- ARRAY_LEN(rx_feature_start_nodes),
- mpls_main.next_feature[VNET_IP_RX_UNICAST_FEAT],
- &mpls_main.feature_nodes[VNET_IP_RX_UNICAST_FEAT]);
-
- if (error)
- return error;
-
- cm = &mpls_main.feature_config_mains[VNET_IP_TX_FEAT];
- vcm = &cm->config_main;
-
- error = vnet_feature_arc_init
- (vm, vcm,
- tx_feature_start_nodes,
- ARRAY_LEN(tx_feature_start_nodes),
- mpls_main.next_feature[VNET_IP_TX_FEAT],
- &mpls_main.feature_nodes[VNET_IP_TX_FEAT]);
-
- return error;
-}
-
static clib_error_t *
mpls_sw_interface_add_del (vnet_main_t * vnm,
u32 sw_if_index,
u32 is_add)
{
- vlib_main_t * vm = vnm->vlib_main;
mpls_main_t * mm = &mpls_main;
- u32 feature_index;
- u32 ci, cast;
-
- for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
- {
- vnet_feature_config_main_t * cm = &mm->feature_config_mains[cast];
- vnet_config_main_t * vcm = &cm->config_main;
-
- if (VNET_IP_RX_MULTICAST_FEAT == cast)
- continue;
-
- vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
- vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
- 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_IP_RX_UNICAST_FEAT)
- feature_index = mm->mpls_rx_feature_not_enabled;
- else
- feature_index = mm->mpls_tx_feature_interface_output;
-
-
- if (is_add)
- ci = vnet_config_add_feature (vm, vcm, ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- else
- {
- ci = vnet_config_del_feature (vm, vcm, ci,
- feature_index,
- /* config data */ 0,
- /* # bytes of config data */ 0);
- mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;;
- }
- cm->config_index_by_sw_if_index[sw_if_index] = ci;
- }
+
+ vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
+ vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
+
+ vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled", sw_if_index,
+ is_add, 0, 0);
+ vnet_feature_enable_disable ("mpls-output", "interface-output", sw_if_index,
+ is_add, 0, 0);
return /* no error */ 0;
}
VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del);
-#define foreach_af_cast \
-_(VNET_IP_RX_UNICAST_FEAT, "mpls input") \
-_(VNET_IP_TX_FEAT, "mpls output") \
diff --git a/vnet/vnet/mpls/node.c b/vnet/vnet/mpls/node.c
index c98b98e733b..2b0461f751e 100644
--- a/vnet/vnet/mpls/node.c
+++ b/vnet/vnet/mpls/node.c
@@ -96,8 +96,7 @@ mpls_input_inline (vlib_main_t * vm,
vlib_buffer_t * b0;
mpls_unicast_header_t * h0;
u32 label0;
- u32 next0;
- vnet_feature_config_main_t * cm0;
+ u32 next0 = 0;
u32 sw_if_index0;
bi0 = from[0];
@@ -111,10 +110,6 @@ mpls_input_inline (vlib_main_t * vm,
h0 = vlib_buffer_get_current (b0);
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- cm0 = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- b0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index,
- sw_if_index0);
-
label0 = clib_net_to_host_u32 (h0->label_exp_s_ttl);
/* TTL expired? */
if (PREDICT_FALSE(vnet_mpls_uc_get_ttl (label0) == 0))
@@ -124,10 +119,7 @@ mpls_input_inline (vlib_main_t * vm,
}
else
{
- vnet_get_config_data (&cm0->config_main,
- &b0->current_config_index,
- &next0,
- /* # bytes of config data */ 0);
+ vnet_feature_arc_start(mm->input_feature_arc_index, sw_if_index0, &next0, b0);
vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1);
}
@@ -218,7 +210,7 @@ static clib_error_t * mpls_input_init (vlib_main_t * vm)
mpls_setup_nodes (vm);
- return (mpls_feature_init(vm));
+ return 0;
}
VLIB_INIT_FUNCTION (mpls_input_init);
diff --git a/vnet/vnet/vnet.h b/vnet/vnet/vnet.h
index a3cbd37903c..98b29e9c0d3 100644
--- a/vnet/vnet/vnet.h
+++ b/vnet/vnet/vnet.h
@@ -42,21 +42,6 @@
#include <vppinfra/types.h>
-typedef enum
-{
- VNET_IP_RX_UNICAST_FEAT,
- VNET_IP_RX_MULTICAST_FEAT,
- VNET_IP_TX_FEAT,
- VNET_N_IP_FEAT,
-} vnet_cast_t;
-
-#define VNET_CAST_NAMES { \
- [VNET_IP_RX_UNICAST_FEAT] = "rx-unicast", \
- [VNET_IP_RX_MULTICAST_FEAT] = "rx-multicast", \
- [VNET_IP_TX_FEAT] = "tx", \
-}
-
-
#include <vnet/unix/pcap.h>
#include <vnet/buffer.h>
#include <vnet/config.h>
diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c
index e606673234b..6852e02a5d6 100644
--- a/vpp/vpp-api/api.c
+++ b/vpp/vpp-api/api.c
@@ -1571,79 +1571,21 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
static void
vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
{
- vlib_main_t *vm = vlib_get_main ();
- ip4_main_t *im4 = &ip4_main;
- ip6_main_t *im6 = &ip6_main;
vl_api_sw_interface_set_vpath_reply_t *rmp;
int rv = 0;
- u32 ci;
u32 sw_if_index = ntohl (mp->sw_if_index);
- ip4_main_t *ip4m = &ip4_main;
- ip6_main_t *ip6m = &ip6_main;
- ip_lookup_main_t *ip4lm = &ip4m->lookup_main;
- ip_lookup_main_t *ip6lm = &ip6m->lookup_main;
- vnet_feature_config_main_t *rx_cm4u =
- &ip4lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_feature_config_main_t *rx_cm4m =
- &ip4lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT];
- vnet_feature_config_main_t *rx_cm6u =
- &ip6lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
- vnet_feature_config_main_t *rx_cm6m =
- &ip6lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT];
VALIDATE_SW_IF_INDEX (mp);
l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
- if (mp->enable)
- {
- ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
- ci = vnet_config_add_feature (vm, &rx_cm4u->config_main,
- ci,
- im4->ip4_unicast_rx_feature_vpath, 0, 0);
- rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
- ci = vnet_config_add_feature (vm, &rx_cm4m->config_main,
- ci,
- im4->ip4_multicast_rx_feature_vpath,
- 0, 0);
- rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
- ci = vnet_config_add_feature (vm, &rx_cm6u->config_main,
- ci,
- im6->ip6_unicast_rx_feature_vpath, 0, 0);
- rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
- ci = vnet_config_add_feature (vm, &rx_cm6m->config_main,
- ci,
- im6->ip6_multicast_rx_feature_vpath,
- 0, 0);
- rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
- }
- else
- {
- ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
- ci = vnet_config_del_feature (vm, &rx_cm4u->config_main,
- ci,
- im4->ip4_unicast_rx_feature_vpath, 0, 0);
- rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
- ci = vnet_config_del_feature (vm, &rx_cm4m->config_main,
- ci,
- im4->ip4_multicast_rx_feature_vpath,
- 0, 0);
- rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
- ci = vnet_config_del_feature (vm, &rx_cm6u->config_main,
- ci,
- im6->ip6_unicast_rx_feature_vpath, 0, 0);
- rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
- ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
- ci = vnet_config_del_feature (vm, &rx_cm6m->config_main,
- ci,
- im6->ip6_multicast_rx_feature_vpath,
- 0, 0);
- rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
- }
+ vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
+ sw_if_index, mp->enable, 0, 0);
+ vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
+ sw_if_index, mp->enable, 0, 0);
+ vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
+ sw_if_index, mp->enable, 0, 0);
+ vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
+ sw_if_index, mp->enable, 0, 0);
BAD_SW_IF_INDEX_LABEL;