/**
* The two midchain tx feature node indices
*/
-static u32 adj_midchain_tx_feature_node[FIB_LINK_NUM];
-static u32 adj_midchain_tx_no_count_feature_node[FIB_LINK_NUM];
+static u32 adj_midchain_tx_feature_node[VNET_LINK_NUM];
+static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM];
/**
* @brief Trace data for packets traversing the midchain tx node
} adj_midchain_tx_trace_t;
always_inline uword
-adj_mdichain_tx_inline (vlib_main_t * vm,
+adj_midchain_tx_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * frame,
int interface_count)
/* set up to enqueue to our disposition with index = next_index */
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
- /*
- * FIXME DUAL LOOP
- */
+ while (n_left_from >= 4 && n_left_to_next > 2)
+ {
+ u32 bi0, adj_index0, next0;
+ const ip_adjacency_t * adj0;
+ const dpo_id_t *dpo0;
+ vlib_buffer_t * b0;
+ u32 bi1, adj_index1, next1;
+ const ip_adjacency_t * adj1;
+ const dpo_id_t *dpo1;
+ vlib_buffer_t * b1;
+
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t * p2, * p3;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
+
+ vlib_prefetch_buffer_header (p2, LOAD);
+ vlib_prefetch_buffer_header (p3, LOAD);
+
+ CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
+ CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
+ }
+
+ bi0 = from[0];
+ to_next[0] = bi0;
+ bi1 = from[1];
+ to_next[1] = bi1;
+
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+
+ b0 = vlib_get_buffer(vm, bi0);
+ b1 = vlib_get_buffer(vm, bi1);
+
+ /* Follow the DPO on which the midchain is stacked */
+ adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
+ adj_index1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
+
+ adj0 = adj_get(adj_index0);
+ adj1 = adj_get(adj_index1);
+
+ dpo0 = &adj0->sub_type.midchain.next_dpo;
+ dpo1 = &adj1->sub_type.midchain.next_dpo;
+
+ next0 = dpo0->dpoi_next_node;
+ next1 = dpo1->dpoi_next_node;
+
+ vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
+ vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
+
+ if (interface_count)
+ {
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ cpu_index,
+ adj0->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ cpu_index,
+ adj1->rewrite_header.sw_if_index,
+ 1,
+ vlib_buffer_length_in_chain (vm, b1));
+ }
+
+ if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b0, sizeof (*tr));
+ tr->ai = adj_index0;
+ }
+ if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ adj_midchain_tx_trace_t *tr = vlib_add_trace (vm, node,
+ b1, sizeof (*tr));
+ tr->ai = adj_index1;
+ }
+
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, bi1,
+ next0, next1);
+ }
while (n_left_from > 0 && n_left_to_next > 0)
{
u32 bi0, adj_index0, next0;
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
- vlib_node_increment_counter (vm, gre_input_node.index,
- GRE_ERROR_PKTS_ENCAP, frame->n_vectors);
-
return frame->n_vectors;
}
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return (adj_mdichain_tx_inline(vm, node, frame, 1));
+ return (adj_midchain_tx_inline(vm, node, frame, 1));
}
VLIB_REGISTER_NODE (adj_midchain_tx_node, static) = {
vlib_node_runtime_t * node,
vlib_frame_t * frame)
{
- return (adj_mdichain_tx_inline(vm, node, frame, 0));
+ return (adj_midchain_tx_inline(vm, node, frame, 0));
}
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"},
- .feature_index = &adj_midchain_tx_feature_node[FIB_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"},
- .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_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"},
- .feature_index = &adj_midchain_tx_feature_node[FIB_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"},
- .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_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) = {
- .node_name = "adj-midchain-txs",
- .runs_before = ORDER_CONSTRAINTS {"interface-output"},
- .feature_index = &adj_midchain_tx_feature_node[FIB_LINK_MPLS],
+VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = {
+ .arc_name = "mpls-output",
+ .node_name = "adj-midchain-tx",
+ .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"},
- .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_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"},
- .feature_index = &adj_midchain_tx_feature_node[FIB_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"},
- .feature_index = &adj_midchain_tx_no_count_feature_node[FIB_LINK_ETHERNET],
+ .runs_before = VNET_FEATURES ("error-drop"),
+ .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET],
};
static inline u32
-adj_get_midchain_node (fib_link_t link)
+adj_get_midchain_node (vnet_link_t link)
{
switch (link) {
- case FIB_LINK_IP4:
+ case VNET_LINK_IP4:
return (ip4_midchain_node.index);
- case FIB_LINK_IP6:
+ case VNET_LINK_IP6:
return (ip6_midchain_node.index);
- case FIB_LINK_MPLS:
+ case VNET_LINK_MPLS:
return (mpls_midchain_node.index);
- case FIB_LINK_ETHERNET:
+ case VNET_LINK_ETHERNET:
return (adj_l2_midchain_node.index);
+ case VNET_LINK_ARP:
+ break;
}
ASSERT(0);
return (0);
}
-static ip_config_main_t *
-adj_midchain_get_cofing_for_link_type (const ip_adjacency_t *adj)
+static u8
+adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj)
{
- ip_config_main_t *cm = NULL;
-
+ u8 arc = (u8) ~0;
switch (adj->ia_link)
{
- case FIB_LINK_IP4:
+ 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 FIB_LINK_IP6:
+ 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 FIB_LINK_MPLS:
+ 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 FIB_LINK_ETHERNET:
+ case VNET_LINK_ETHERNET:
{
- cm = ðernet_main.feature_config_mains[VNET_IP_TX_FEAT];
+ arc = ethernet_main.output_feature_arc_index;
break;
}
+ case VNET_LINK_ARP:
+ ASSERT(0);
+ break;
}
- return (cm);
+ ASSERT (arc != (u8) ~0);
+
+ return (arc);
}
/**
adj_midchain_flag_t flags,
u8 *rewrite)
{
- vnet_config_main_t * vcm;
- ip_config_main_t *cm;
ip_adjacency_t *adj;
- u32 ci;
+ u8 arc_index;
+ u32 feature_index;
ASSERT(ADJ_INDEX_INVALID != adj_index);
adj->sub_type.midchain.fixup_func = fixup;
- cm = adj_midchain_get_cofing_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];
+ 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];
- /*
- * 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);
- }
-
- 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.
*/
dpo_stack_from_node(adj->sub_type.midchain.tx_function_node,
&adj->sub_type.midchain.next_dpo,
- drop_dpo_get(fib_link_to_dpo_proto(adj->ia_link)));
+ drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
/*
* update the rewirte with the workers paused.
adj_get_midchain_node(adj->ia_link),
adj->sub_type.midchain.tx_function_node,
rewrite);
-
- /*
- * time for walkies fido.
- */
- fib_node_back_walk_ctx_t bw_ctx = {
- .fnbw_reason = FIB_NODE_BW_REASON_ADJ_UPDATE,
- };
-
- fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx);
}
/**
* stack on the drop
*/
dpo_stack(DPO_ADJACENCY_MIDCHAIN,
- fib_link_to_dpo_proto(adj->ia_link),
+ vnet_link_to_dpo_proto(adj->ia_link),
&adj->sub_type.midchain.next_dpo,
- drop_dpo_get(fib_link_to_dpo_proto(adj->ia_link)));
+ drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
CLIB_MEMORY_BARRIER();
}
vnet_main_t * vnm = vnet_get_main();
ip_adjacency_t * adj = adj_get(index);
- s = format (s, "%U", format_fib_link, adj->ia_link);
+ s = format (s, "%U", format_vnet_link, adj->ia_link);
s = format (s, " via %U ",
format_ip46_address, &adj->sub_type.nbr.next_hop);
s = format (s, " %U",