summaryrefslogtreecommitdiffstats
path: root/src/vnet/adj
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/adj')
-rw-r--r--src/vnet/adj/adj.c6
-rw-r--r--src/vnet/adj/adj_internal.h1
-rw-r--r--src/vnet/adj/adj_midchain.c38
3 files changed, 40 insertions, 5 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index c758ebeae3a..3a2b2dd3925 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -249,7 +249,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
switch (adj->lookup_next_index)
{
case IP_LOOKUP_NEXT_MIDCHAIN:
- dpo_reset(&adj->sub_type.midchain.next_dpo);
+ adj_midchain_teardown(adj);
/* FALL THROUGH */
case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_REWRITE:
@@ -267,8 +267,10 @@ adj_last_lock_gone (ip_adjacency_t *adj)
adj_glean_remove(adj->ia_nh_proto,
adj->rewrite_header.sw_if_index);
break;
- case IP_LOOKUP_NEXT_MCAST:
case IP_LOOKUP_NEXT_MCAST_MIDCHAIN:
+ adj_midchain_teardown(adj);
+ /* FALL THROUGH */
+ case IP_LOOKUP_NEXT_MCAST:
adj_mcast_remove(adj->ia_nh_proto,
adj->rewrite_header.sw_if_index);
break;
diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h
index adb7a32375d..c4dda51324c 100644
--- a/src/vnet/adj/adj_internal.h
+++ b/src/vnet/adj/adj_internal.h
@@ -124,6 +124,7 @@ extern void adj_glean_remove(fib_protocol_t proto,
u32 sw_if_index);
extern void adj_mcast_remove(fib_protocol_t proto,
u32 sw_if_index);
+extern void adj_midchain_teardown(ip_adjacency_t *adj);
extern u32 adj_dpo_get_urpf(const dpo_id_t *dpo);
diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c
index fcd6993586e..88648fea0a9 100644
--- a/src/vnet/adj/adj_midchain.c
+++ b/src/vnet/adj/adj_midchain.c
@@ -30,6 +30,8 @@
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
*/
@@ -451,6 +453,30 @@ adj_nbr_midchain_get_feature_node (ip_adjacency_t *adj)
* 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
+ *
+ * Setup the adj as a mid-chain
+ */
+void
adj_midchain_setup (adj_index_t adj_index,
adj_midchain_fixup_t fixup,
const void *data,
@@ -473,9 +499,15 @@ adj_midchain_setup (adj_index_t adj_index,
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.