static u32 adj_midchain_tx_feature_node[VNET_LINK_NUM];
static u32 adj_midchain_tx_no_count_feature_node[VNET_LINK_NUM];
+static u32 *adj_midchain_feat_count_per_sw_if_index[VNET_LINK_NUM];
+
/**
* @brief Trace data for packets traversing the midchain tx node
*/
while (n_left_from >= 8 && n_left_to_next > 4)
{
+ const ip_adjacency_t *adj0, *adj1, *adj2, *adj3;
+ const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
+ vlib_buffer_t * b0, *b1, *b2, *b3;
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;
u32 bi2, adj_index2, next2;
- const ip_adjacency_t * adj2;
- const dpo_id_t *dpo2;
- vlib_buffer_t * b2;
u32 bi3, adj_index3, next3;
- const ip_adjacency_t * adj3;
- const dpo_id_t *dpo3;
- vlib_buffer_t * b3;
/* Prefetch next iteration. */
{
return (adj_midchain_tx_feature_node[adj->ia_link]);
}
+/**
+ * adj_midchain_setup
+ *
+ * Setup the adj as a mid-chain
+ */
+void
+adj_midchain_teardown (ip_adjacency_t *adj)
+{
+ u32 feature_index;
+ u8 arc_index;
+
+ dpo_reset(&adj->sub_type.midchain.next_dpo);
+
+ arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj);
+ feature_index = adj_nbr_midchain_get_feature_node(adj);
+
+ if (0 == --adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_index])
+ {
+ vnet_feature_enable_disable_with_index (arc_index, feature_index,
+ adj->rewrite_header.sw_if_index,
+ 0, 0, 0);
+ }
+}
+
/**
* adj_midchain_setup
*
feature_index = adj_nbr_midchain_get_feature_node(adj);
tx_node = adj_nbr_midchain_get_tx_node(adj);
- vnet_feature_enable_disable_with_index (arc_index, feature_index,
- adj->rewrite_header.sw_if_index,
- 1 /* enable */, 0, 0);
+ vec_validate (adj_midchain_feat_count_per_sw_if_index[adj->ia_link],
+ adj->rewrite_header.sw_if_index);
+
+ if (0 == adj_midchain_feat_count_per_sw_if_index[adj->ia_link][adj->rewrite_header.sw_if_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.
* adj_nbr_midchain_update_rewrite
*
* Update the adjacency's rewrite string. A NULL string implies the
- * rewrite is reset (i.e. when ARP/ND etnry is gone).
+ * rewrite is reset (i.e. when ARP/ND entry is gone).
* NB: the adj being updated may be handling traffic in the DP.
*/
void
adj = adj_get(adj_index);
/*
- * one time only update. since we don't support chainging the tunnel
+ * one time only update. since we don't support changing the tunnel
* src,dst, this is all we need.
*/
- ASSERT((adj->lookup_next_index == IP_LOOKUP_NEXT_ARP) ||
- (adj->lookup_next_index == IP_LOOKUP_NEXT_GLEAN) ||
- (adj->lookup_next_index == IP_LOOKUP_NEXT_BCAST));
-
- /*
- * tunnels can always provide a rewrite.
- */
- ASSERT(NULL != rewrite);
-
- adj_midchain_setup(adj_index, fixup, fixup_data, flags);
+ if (adj->lookup_next_index != IP_LOOKUP_NEXT_MIDCHAIN &&
+ adj->lookup_next_index != IP_LOOKUP_NEXT_MCAST_MIDCHAIN)
+ {
+ adj_midchain_setup(adj_index, fixup, fixup_data, flags);
+ }
/*
- * update the rewirte with the workers paused.
+ * update the rewrite with the workers paused.
*/
adj_nbr_update_rewrite_internal(adj,
IP_LOOKUP_NEXT_MIDCHAIN,
{
/*
* The entry this midchain links to is already in the set
- * of visisted entries, this is a loop
+ * of visited entries, this is a loop
*/
adj->ia_flags |= ADJ_FLAG_MIDCHAIN_LOOPED;
return (1);
ip_adjacency_t * adj = adj_get(index);
s = format (s, "%U", format_vnet_link, adj->ia_link);
+ if (adj->rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)
+ s = format(s, " [features]");
s = format (s, " via %U",
format_ip46_address, &adj->sub_type.nbr.next_hop,
adj_proto_to_46(adj->ia_nh_proto));