aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/adj
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/adj')
-rw-r--r--src/vnet/adj/adj.c19
-rw-r--r--src/vnet/adj/adj.h10
-rw-r--r--src/vnet/adj/adj_bfd.c53
-rw-r--r--src/vnet/adj/adj_dp.h42
-rw-r--r--src/vnet/adj/adj_glean.c121
-rw-r--r--src/vnet/adj/adj_internal.h19
-rw-r--r--src/vnet/adj/adj_mcast.c4
-rw-r--r--src/vnet/adj/adj_midchain.c82
-rw-r--r--src/vnet/adj/adj_midchain.h7
-rw-r--r--src/vnet/adj/adj_midchain_delegate.c25
-rw-r--r--src/vnet/adj/adj_midchain_node.c35
-rw-r--r--src/vnet/adj/adj_nbr.c60
-rw-r--r--src/vnet/adj/adj_nsh.c2
-rw-r--r--src/vnet/adj/rewrite.h6
14 files changed, 294 insertions, 191 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index 8808294f7a6..201561fe485 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -34,6 +34,11 @@ vlib_combined_counter_main_t adjacency_counters = {
ip_adjacency_t *adj_pool;
/**
+ * The adjacency logger
+ */
+vlib_log_class_t adj_logger;
+
+/**
* @brief Global Config for enabling per-adjacency counters.
* By default these are disabled.
*/
@@ -64,14 +69,12 @@ ip_adjacency_t *
adj_alloc (fib_protocol_t proto)
{
ip_adjacency_t *adj;
- u8 need_barrier_sync = 0;
+ u8 need_barrier_sync = pool_get_will_expand (adj_pool);
vlib_main_t *vm;
vm = vlib_get_main();
ASSERT (vm->thread_index == 0);
- pool_get_aligned_will_expand (adj_pool, need_barrier_sync,
- CLIB_CACHE_LINE_BYTES);
/* If the adj_pool will expand, stop the parade. */
if (need_barrier_sync)
vlib_worker_thread_barrier_sync (vm);
@@ -309,12 +312,12 @@ adj_last_lock_gone (ip_adjacency_t *adj)
break;
}
- vlib_worker_thread_barrier_release(vm);
fib_node_deinit(&adj->ia_node);
ASSERT(0 == vec_len(adj->ia_delegates));
vec_free(adj->ia_delegates);
pool_put(adj_pool, adj);
+ vlib_worker_thread_barrier_release(vm);
}
u32
@@ -350,7 +353,6 @@ adj_lock (adj_index_t adj_index)
adj = adj_get(adj_index);
ASSERT(adj);
- ADJ_DBG(adj, "lock");
fib_node_lock(&adj->ia_node);
}
@@ -367,9 +369,6 @@ adj_unlock (adj_index_t adj_index)
adj = adj_get(adj_index);
ASSERT(adj);
- ADJ_DBG(adj, "unlock");
- ASSERT(adj);
-
fib_node_unlock(&adj->ia_node);
}
@@ -650,6 +649,8 @@ adj_module_init (vlib_main_t * vm)
vnet_feature_register(adj_feature_update, NULL);
+ adj_logger = vlib_log_register_class("adj", "adj");
+
return (NULL);
}
@@ -703,7 +704,6 @@ adj_show (vlib_main_t * vm,
}
else
{
- /* *INDENT-OFF* */
pool_foreach_index (ai, adj_pool)
{
if (~0 != sw_if_index &&
@@ -718,7 +718,6 @@ adj_show (vlib_main_t * vm,
FORMAT_IP_ADJACENCY_NONE);
}
}
- /* *INDENT-ON* */
}
}
return 0;
diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h
index c1922c755ec..860193c04ad 100644
--- a/src/vnet/adj/adj.h
+++ b/src/vnet/adj/adj.h
@@ -165,14 +165,6 @@ typedef enum adj_attr_t_
ADJ_ATTR_SYNC_WALK_ACTIVE = 0,
/**
- * Packets TX through the midchain do not increment the interface
- * counters. This should be used when the adj is associated with an L2
- * interface and that L2 interface is in a bridge domain. In that case
- * the packet will have traversed the interface's TX node, and hence have
- * been counted, before it traverses ths midchain
- */
- ADJ_ATTR_MIDCHAIN_NO_COUNT,
- /**
* When stacking midchains on a fib-entry extract the choice from the
* load-balance returned based on an IP hash of the adj's rewrite
*/
@@ -195,7 +187,6 @@ typedef enum adj_attr_t_
#define ADJ_ATTR_NAMES { \
[ADJ_ATTR_SYNC_WALK_ACTIVE] = "walk-active", \
- [ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count", \
[ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack", \
[ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped", \
[ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup", \
@@ -214,7 +205,6 @@ typedef enum adj_flags_t_
{
ADJ_FLAG_NONE = 0,
ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << ADJ_ATTR_SYNC_WALK_ACTIVE),
- ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << ADJ_ATTR_MIDCHAIN_NO_COUNT),
ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR),
diff --git a/src/vnet/adj/adj_bfd.c b/src/vnet/adj/adj_bfd.c
index 2d787d41ab6..e54ba6d74ae 100644
--- a/src/vnet/adj/adj_bfd.c
+++ b/src/vnet/adj/adj_bfd.c
@@ -114,9 +114,7 @@ void
adj_bfd_notify (bfd_listen_event_e event,
const bfd_session_t *session)
{
- const bfd_udp_key_t *key;
adj_bfd_delegate_t *abd;
- fib_protocol_t fproto;
adj_delegate_t *aed;
adj_index_t ai;
@@ -129,19 +127,28 @@ adj_bfd_notify (bfd_listen_event_e event,
return;
}
- key = &session->udp.key;
-
- fproto = (ip46_address_is_ip4 (&key->peer_addr) ?
- FIB_PROTOCOL_IP4:
- FIB_PROTOCOL_IP6);
+ switch (session->transport)
+ {
+ case BFD_TRANSPORT_UDP4:
+ case BFD_TRANSPORT_UDP6:
+ /*
+ * pick up the same adjacency that the BFD session is using
+ * to send. The BFD session is holding a lock on this adj.
+ */
+ ai = session->udp.adj_index;
+ break;
+ default:
+ /*
+ * Don't know what adj this session uses
+ */
+ return;
+ }
- /*
- * find the adj that corresponds to the BFD session.
- */
- ai = adj_nbr_add_or_lock(fproto,
- fib_proto_to_link(fproto),
- &key->peer_addr,
- key->sw_if_index);
+ if (INDEX_INVALID == ai)
+ {
+ /* No associated Adjacency with the session */
+ return;
+ }
switch (event)
{
@@ -160,13 +167,6 @@ adj_bfd_notify (bfd_listen_event_e event,
else
{
/*
- * lock the adj. add the delegate.
- * Locking the adj prevents it being removed and thus maintains
- * the BFD derived states
- */
- adj_lock(ai);
-
- /*
* allocate and init a new delegate struct
*/
pool_get(abd_pool, abd);
@@ -213,14 +213,12 @@ adj_bfd_notify (bfd_listen_event_e event,
{
/*
* has an associated BFD tracking delegate
- * remove the BFD tracking delegate, update children, then
- * unlock the adj
+ * remove the BFD tracking delegate, update children
*/
adj_delegate_remove(ai, ADJ_DELEGATE_BFD);
pool_put(abd_pool, abd);
adj_bfd_update_walk(ai);
- adj_unlock(ai);
}
/*
* else
@@ -228,11 +226,6 @@ adj_bfd_notify (bfd_listen_event_e event,
*/
break;
}
-
- /*
- * unlock match of the add-or-lock at the start
- */
- adj_unlock(ai);
}
int
@@ -287,9 +280,7 @@ adj_bfd_main_init (vlib_main_t * vm)
return (0);
}
-/* *INDENT-OFF* */
VLIB_INIT_FUNCTION (adj_bfd_main_init)=
{
.runs_after = VLIB_INITS("bfd_main_init"),
};
-/* *INDENT-ON* */
diff --git a/src/vnet/adj/adj_dp.h b/src/vnet/adj/adj_dp.h
index aff1a2b1f43..186044b90ad 100644
--- a/src/vnet/adj/adj_dp.h
+++ b/src/vnet/adj/adj_dp.h
@@ -36,22 +36,36 @@ adj_midchain_ipip44_fixup (vlib_main_t * vm,
ip4->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b));
if (PREDICT_TRUE(TUNNEL_ENCAP_DECAP_FLAG_NONE == flags))
- {
- ip_csum_t sum;
- u16 old,new;
-
- old = 0;
- new = ip4->length;
-
- sum = ip4->checksum;
- sum = ip_csum_update (sum, old, new, ip4_header_t, length);
- ip4->checksum = ip_csum_fold (sum);
- }
+ {
+ if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_GSO))
+ {
+ vnet_buffer2 (b)->outer_l3_hdr_offset = (u8 *) ip4 - b->data;
+ vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_TNL_IPIP |
+ VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM);
+ }
+ else
+ {
+ ip_csum_t sum;
+ u16 old,new;
+ old = 0;
+ new = ip4->length;
+ sum = ip4->checksum;
+ sum = ip_csum_update (sum, old, new, ip4_header_t, length);
+ ip4->checksum = ip_csum_fold (sum);
+ }
+ }
else
- {
+ {
tunnel_encap_fixup_4o4 (flags, ip4 + 1, ip4);
- ip4->checksum = ip4_header_checksum (ip4);
- }
+ if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_GSO))
+ {
+ vnet_buffer2 (b)->outer_l3_hdr_offset = (u8 *) ip4 - b->data;
+ vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_TNL_IPIP |
+ VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM);
+ }
+ else
+ ip4->checksum = ip4_header_checksum (ip4);
+ }
}
static_always_inline void
diff --git a/src/vnet/adj/adj_glean.c b/src/vnet/adj/adj_glean.c
index e8ca043662f..ceece0d74ed 100644
--- a/src/vnet/adj/adj_glean.c
+++ b/src/vnet/adj/adj_glean.c
@@ -45,7 +45,7 @@ adj_glean_db_lookup (fib_protocol_t proto,
{
uword *p;
- if (vec_len(adj_gleans[proto]) <= sw_if_index)
+ if ((proto >= FIB_PROTOCOL_IP_MAX) || vec_len(adj_gleans[proto]) <= sw_if_index)
return (ADJ_INDEX_INVALID);
p = hash_get_mem (adj_gleans[proto][sw_if_index], nh_addr);
@@ -66,6 +66,7 @@ adj_glean_db_insert (fib_protocol_t proto,
vlib_worker_thread_barrier_sync(vm);
+ ASSERT(proto < FIB_PROTOCOL_IP_MAX);
vec_validate(adj_gleans[proto], sw_if_index);
if (NULL == adj_gleans[proto][sw_if_index])
@@ -186,6 +187,38 @@ adj_glean_update_rewrite_walk (adj_index_t ai,
return (ADJ_WALK_RC_CONTINUE);
}
+static void
+adj_glean_walk_proto (fib_protocol_t proto,
+ u32 sw_if_index,
+ adj_walk_cb_t cb,
+ void *data)
+{
+ adj_index_t ai, *aip, *ais = NULL;
+ ip46_address_t *conn;
+
+ ASSERT(proto < FIB_PROTOCOL_IP_MAX);
+ if (vec_len(adj_gleans[proto]) <= sw_if_index ||
+ NULL == adj_gleans[proto][sw_if_index])
+ return;
+
+ /*
+ * Walk first to collect the indices
+ * then walk the collection. This is safe
+ * to modifications of the hash table
+ */
+ hash_foreach_mem(conn, ai, adj_gleans[proto][sw_if_index],
+ ({
+ vec_add1(ais, ai);
+ }));
+
+ vec_foreach(aip, ais)
+ {
+ if (ADJ_WALK_RC_STOP == cb(*aip, data))
+ break;
+ }
+ vec_free(ais);
+}
+
void
adj_glean_walk (u32 sw_if_index,
adj_walk_cb_t cb,
@@ -195,29 +228,7 @@ adj_glean_walk (u32 sw_if_index,
FOR_EACH_FIB_IP_PROTOCOL(proto)
{
- adj_index_t ai, *aip, *ais = NULL;
- ip46_address_t *conn;
-
- if (vec_len(adj_gleans[proto]) <= sw_if_index ||
- NULL == adj_gleans[proto][sw_if_index])
- continue;
-
- /*
- * Walk first to collect the indices
- * then walk the collection. This is safe
- * to modifications of the hash table
- */
- hash_foreach_mem(conn, ai, adj_gleans[proto][sw_if_index],
- ({
- vec_add1(ais, ai);
- }));
-
- vec_foreach(aip, ais)
- {
- if (ADJ_WALK_RC_STOP == cb(*aip, data))
- break;
- }
- vec_free(ais);
+ adj_glean_walk_proto (proto, sw_if_index, cb, data);
}
}
@@ -235,6 +246,7 @@ adj_glean_get (fib_protocol_t proto,
ip46_address_t *conn;
adj_index_t ai;
+ ASSERT(proto < FIB_PROTOCOL_IP_MAX);
if (vec_len(adj_gleans[proto]) <= sw_if_index ||
NULL == adj_gleans[proto][sw_if_index])
return (ADJ_INDEX_INVALID);
@@ -256,6 +268,7 @@ adj_glean_get_src (fib_protocol_t proto,
const ip_adjacency_t *adj;
adj_index_t ai;
+ ASSERT(proto < FIB_PROTOCOL_IP_MAX);
if (vec_len(adj_gleans[proto]) <= sw_if_index ||
NULL == adj_gleans[proto][sw_if_index])
return (NULL);
@@ -424,11 +437,59 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION(adj_glean_interface_delete);
*/
static void
adj_glean_ethernet_change_mac (ethernet_main_t * em,
- u32 sw_if_index, uword opaque)
+ u32 sw_if_index,
+ uword opaque)
{
adj_glean_walk (sw_if_index, adj_glean_update_rewrite_walk, NULL);
}
+static void
+adj_glean_table_bind (fib_protocol_t fproto,
+ u32 sw_if_index,
+ u32 itf_fib_index)
+{
+ /*
+ * for each glean on the interface trigger a walk back to the children
+ */
+ fib_node_back_walk_ctx_t bw_ctx = {
+ .fnbw_reason = FIB_NODE_BW_REASON_FLAG_INTERFACE_BIND,
+ .interface_bind = {
+ .fnbw_to_fib_index = itf_fib_index,
+ },
+ };
+
+ adj_glean_walk_proto (fproto, sw_if_index, adj_glean_start_backwalk, &bw_ctx);
+}
+
+
+/**
+ * Callback function invoked when an interface's IPv6 Table
+ * binding changes
+ */
+static void
+adj_glean_ip6_table_bind (ip6_main_t * im,
+ uword opaque,
+ u32 sw_if_index,
+ u32 new_fib_index,
+ u32 old_fib_index)
+{
+ adj_glean_table_bind (FIB_PROTOCOL_IP6, sw_if_index, new_fib_index);
+}
+
+/**
+ * Callback function invoked when an interface's IPv4 Table
+ * binding changes
+ */
+static void
+adj_glean_ip4_table_bind (ip4_main_t * im,
+ uword opaque,
+ u32 sw_if_index,
+ u32 new_fib_index,
+ u32 old_fib_index)
+{
+ adj_glean_table_bind (FIB_PROTOCOL_IP4, sw_if_index, new_fib_index);
+}
+
u8*
format_adj_glean (u8* s, va_list *ap)
{
@@ -519,4 +580,14 @@ adj_glean_module_init (void)
.function_opaque = 0,
};
vec_add1 (ethernet_main.address_change_callbacks, ctx);
+
+ ip6_table_bind_callback_t cbt6 = {
+ .function = adj_glean_ip6_table_bind,
+ };
+ vec_add1 (ip6_main.table_bind_callbacks, cbt6);
+
+ ip4_table_bind_callback_t cbt4 = {
+ .function = adj_glean_ip4_table_bind,
+ };
+ vec_add1 (ip4_main.table_bind_callbacks, cbt4);
}
diff --git a/src/vnet/adj/adj_internal.h b/src/vnet/adj/adj_internal.h
index 3dbf7e2a371..380af46e22a 100644
--- a/src/vnet/adj/adj_internal.h
+++ b/src/vnet/adj/adj_internal.h
@@ -31,24 +31,20 @@
/*
* Debug macro
*/
-#ifdef ADJ_DEBUG
-#define ADJ_DBG(_adj, _fmt, _args...) \
-{ \
- clib_warning("adj:[%d:%p]:" _fmt, \
- _adj - adj_pool, _adj, \
- ##_args); \
+extern vlib_log_class_t adj_logger;
+#define ADJ_DBG(_adj, _fmt, _args...) \
+{ \
+ vlib_log_debug(adj_logger, "adj:[%d:%p]:" _fmt, \
+ _adj - adj_pool, _adj, \
+ ##_args); \
}
-#else
-#define ADJ_DBG(_e, _fmt, _args...)
-#endif
/*
* Vlib nodes
*/
extern vlib_node_registration_t adj_nsh_midchain_node;
extern vlib_node_registration_t adj_nsh_rewrite_node;
-extern vlib_node_registration_t adj_midchain_tx_no_count_node;
-extern vlib_node_registration_t adj_midchain_tx_node;
+extern vlib_node_registration_t adj_midchain_tx;
static inline u32
adj_get_rewrite_node (vnet_link_t linkt)
@@ -128,6 +124,7 @@ extern void adj_nbr_remove(adj_index_t ai,
vnet_link_t link_type,
const ip46_address_t *nh_addr,
u32 sw_if_index);
+extern u32 adj_nbr_get_n_adjs(vnet_link_t link_type, u32 sw_if_index);
extern void adj_glean_remove(ip_adjacency_t *adj);
extern void adj_mcast_remove(fib_protocol_t proto,
u32 sw_if_index);
diff --git a/src/vnet/adj/adj_mcast.c b/src/vnet/adj/adj_mcast.c
index a20f61f6f6b..573105b7228 100644
--- a/src/vnet/adj/adj_mcast.c
+++ b/src/vnet/adj/adj_mcast.c
@@ -82,6 +82,8 @@ adj_mcast_add_or_lock (fib_protocol_t proto,
*/
vnet_update_adjacency_for_sw_interface(vnm, sw_if_index,
adj_get_index(adj));
+
+ adj_delegate_adj_created(adj);
}
else
{
@@ -89,8 +91,6 @@ adj_mcast_add_or_lock (fib_protocol_t proto,
adj_lock(adj_get_index(adj));
}
- adj_delegate_adj_created(adj);
-
return (adj_get_index(adj));
}
diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c
index 9f709ad13be..8e6a940befa 100644
--- a/src/vnet/adj/adj_midchain.c
+++ b/src/vnet/adj/adj_midchain.c
@@ -75,52 +75,37 @@ adj_get_midchain_node (vnet_link_t link)
}
static u8
-adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj)
+adj_midchain_get_feature_arc_index (const ip_adjacency_t *adj)
{
- u8 arc = (u8) ~0;
switch (adj->ia_link)
{
case VNET_LINK_IP4:
- {
- arc = ip4_main.lookup_main.output_feature_arc_index;
- break;
- }
+ return ip4_main.lookup_main.output_feature_arc_index;
case VNET_LINK_IP6:
- {
- arc = ip6_main.lookup_main.output_feature_arc_index;
- break;
- }
+ return ip6_main.lookup_main.output_feature_arc_index;
case VNET_LINK_MPLS:
- {
- arc = mpls_main.output_feature_arc_index;
- break;
- }
+ return mpls_main.output_feature_arc_index;
case VNET_LINK_ETHERNET:
- {
- arc = ethernet_main.output_feature_arc_index;
- break;
- }
+ return ethernet_main.output_feature_arc_index;
case VNET_LINK_NSH:
- {
- arc = nsh_main_placeholder.output_feature_arc_index;
- break;
- }
case VNET_LINK_ARP:
- ASSERT(0);
break;
}
-
- ASSERT (arc != (u8) ~0);
-
- return (arc);
+ ASSERT (0);
+ return (0);
}
static u32
adj_nbr_midchain_get_tx_node (ip_adjacency_t *adj)
{
- return ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_NO_COUNT) ?
- adj_midchain_tx_no_count_node.index :
- adj_midchain_tx_node.index);
+ return (adj_midchain_tx.index);
+}
+
+static u32
+adj_nbr_midchain_get_next_node (ip_adjacency_t *adj)
+{
+ return (vnet_feature_get_end_node(adj_midchain_get_feature_arc_index(adj),
+ adj->rewrite_header.sw_if_index));
}
/**
@@ -131,17 +116,7 @@ adj_nbr_midchain_get_tx_node (ip_adjacency_t *adj)
void
adj_midchain_teardown (ip_adjacency_t *adj)
{
- vlib_main_t *vm = vlib_get_main();
-
dpo_reset(&adj->sub_type.midchain.next_dpo);
-
- vlib_worker_thread_barrier_sync(vm);
- adj->ia_cfg_index = vnet_feature_modify_end_node(
- adj_midchain_get_feature_arc_index_for_link_type (adj),
- adj->rewrite_header.sw_if_index,
- vlib_get_node_by_name (vlib_get_main(),
- (u8*) "interface-output")->index);
- vlib_worker_thread_barrier_release(vm);
}
/**
@@ -155,9 +130,7 @@ adj_midchain_setup (adj_index_t adj_index,
const void *data,
adj_flags_t flags)
{
- vlib_main_t *vm = vlib_get_main();
ip_adjacency_t *adj;
- u32 tx_node;
ASSERT(ADJ_INDEX_INVALID != adj_index);
@@ -181,15 +154,6 @@ adj_midchain_setup (adj_index_t adj_index,
adj->rewrite_header.flags &= ~VNET_REWRITE_FIXUP_FLOW_HASH;
}
- tx_node = adj_nbr_midchain_get_tx_node(adj);
-
- vlib_worker_thread_barrier_sync(vm);
- adj->ia_cfg_index = vnet_feature_modify_end_node(
- adj_midchain_get_feature_arc_index_for_link_type (adj),
- adj->rewrite_header.sw_if_index,
- tx_node);
- vlib_worker_thread_barrier_release(vm);
-
/*
* stack the midchain on the drop so it's ready to forward in the adj-midchain-tx.
* The graph arc used/created here is from the midchain-tx node to the
@@ -197,7 +161,7 @@ adj_midchain_setup (adj_index_t adj_index,
* node are any output features, then the midchain-tx. from there we
* need to get to the stacked child's node.
*/
- dpo_stack_from_node(tx_node,
+ dpo_stack_from_node(adj_nbr_midchain_get_tx_node(adj),
&adj->sub_type.midchain.next_dpo,
drop_dpo_get(vnet_link_to_dpo_proto(adj->ia_link)));
}
@@ -238,7 +202,7 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index,
adj_nbr_update_rewrite_internal(adj,
IP_LOOKUP_NEXT_MIDCHAIN,
adj_get_midchain_node(adj->ia_link),
- adj_nbr_midchain_get_tx_node(adj),
+ adj_nbr_midchain_get_next_node(adj),
rewrite);
}
@@ -260,11 +224,6 @@ adj_nbr_midchain_update_next_node (adj_index_t adj_index,
adj->ia_node_index,
next_node);
- adj->ia_cfg_index = vnet_feature_modify_end_node(
- adj_midchain_get_feature_arc_index_for_link_type (adj),
- adj->rewrite_header.sw_if_index,
- next_node);
-
vlib_worker_thread_barrier_release(vm);
}
@@ -284,12 +243,7 @@ adj_nbr_midchain_reset_next_node (adj_index_t adj_index)
adj->rewrite_header.next_index =
vlib_node_add_next(vlib_get_main(),
adj->ia_node_index,
- adj_nbr_midchain_get_tx_node(adj));
-
- adj->ia_cfg_index = vnet_feature_modify_end_node(
- adj_midchain_get_feature_arc_index_for_link_type (adj),
- adj->rewrite_header.sw_if_index,
- adj_nbr_midchain_get_tx_node(adj));
+ adj_nbr_midchain_get_next_node(adj));
vlib_worker_thread_barrier_release(vm);
}
diff --git a/src/vnet/adj/adj_midchain.h b/src/vnet/adj/adj_midchain.h
index 5fb0ee8efb3..eee8c99ae40 100644
--- a/src/vnet/adj/adj_midchain.h
+++ b/src/vnet/adj/adj_midchain.h
@@ -99,7 +99,7 @@ extern void adj_nbr_midchain_stack(adj_index_t adj_index,
* The FIB entry to stack on
*
* @param fct
- * The chain type to use from the fib entry fowarding
+ * The chain type to use from the fib entry forwarding
*/
extern void adj_nbr_midchain_stack_on_fib_entry(adj_index_t adj_index,
fib_node_index_t fei,
@@ -160,6 +160,11 @@ extern void adj_midchain_delegate_restack(adj_index_t ai);
*/
extern void adj_midchain_delegate_unstack(adj_index_t ai);
+/**
+ * @brief remove a midchain delegate (this stacks it on a drop)
+ */
+extern void adj_midchain_delegate_remove (adj_index_t ai);
+
extern u8 adj_is_midchain (adj_index_t ai);
#endif
diff --git a/src/vnet/adj/adj_midchain_delegate.c b/src/vnet/adj/adj_midchain_delegate.c
index 9e788432640..16129ff86ac 100644
--- a/src/vnet/adj/adj_midchain_delegate.c
+++ b/src/vnet/adj/adj_midchain_delegate.c
@@ -132,6 +132,31 @@ adj_midchain_delegate_stack (adj_index_t ai,
}
void
+adj_midchain_delegate_remove (adj_index_t ai)
+{
+ adj_midchain_delegate_t *amd;
+ ip_adjacency_t *adj;
+ adj_delegate_t *ad;
+
+ /*
+ * if there's a delegate, it can be removed
+ */
+ adj = adj_get(ai);
+ ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN);
+
+ if (NULL != ad)
+ {
+ adj_nbr_midchain_unstack(ai);
+
+ amd = pool_elt_at_index(amd_pool, ad->ad_index);
+ fib_entry_untrack(amd->amd_fei, amd->amd_sibling);
+ pool_put(amd_pool, amd);
+
+ adj_delegate_remove (ai, ADJ_DELEGATE_MIDCHAIN);
+ }
+}
+
+void
adj_midchain_delegate_unstack (adj_index_t ai)
{
adj_nbr_midchain_unstack(ai);
diff --git a/src/vnet/adj/adj_midchain_node.c b/src/vnet/adj/adj_midchain_node.c
index 170ed19855e..fcc2c6c7647 100644
--- a/src/vnet/adj/adj_midchain_node.c
+++ b/src/vnet/adj/adj_midchain_node.c
@@ -202,16 +202,20 @@ format_adj_midchain_tx_trace (u8 * s, va_list * args)
return (s);
}
-static uword
-adj_midchain_tx (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+VLIB_NODE_FN (adj_midchain_tx) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return (adj_midchain_tx_inline(vm, node, frame, 1));
+}
+VLIB_NODE_FN (tunnel_output) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
return (adj_midchain_tx_inline(vm, node, frame, 1));
}
-VLIB_REGISTER_NODE (adj_midchain_tx_node) = {
- .function = adj_midchain_tx,
+VLIB_REGISTER_NODE (adj_midchain_tx) = {
.name = "adj-midchain-tx",
.vector_size = sizeof (u32),
@@ -222,20 +226,23 @@ VLIB_REGISTER_NODE (adj_midchain_tx_node) = {
[0] = "error-drop",
},
};
+VLIB_REGISTER_NODE (tunnel_output) = {
+ .name = "tunnel-output",
+ .vector_size = sizeof (u32),
+ .format_trace = format_adj_midchain_tx_trace,
+ .sibling_of = "adj-midchain-tx",
+};
-static uword
-adj_midchain_tx_no_count (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+VLIB_NODE_FN (tunnel_output_no_count) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
{
return (adj_midchain_tx_inline(vm, node, frame, 0));
}
-VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node) = {
- .function = adj_midchain_tx_no_count,
- .name = "adj-midchain-tx-no-count",
+VLIB_REGISTER_NODE (tunnel_output_no_count) = {
+ .name = "tunnel-output-no-count",
.vector_size = sizeof (u32),
-
.format_trace = format_adj_midchain_tx_trace,
.sibling_of = "adj-midchain-tx",
};
diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c
index 8524c6c83ae..b3a027b7af4 100644
--- a/src/vnet/adj/adj_nbr.c
+++ b/src/vnet/adj/adj_nbr.c
@@ -105,6 +105,46 @@ adj_nbr_remove (adj_index_t ai,
}
}
+typedef struct adj_nbr_get_n_adjs_walk_ctx_t_
+{
+ vnet_link_t linkt;
+ u32 count;
+} adj_nbr_get_n_adjs_walk_ctx_t;
+
+static adj_walk_rc_t
+adj_nbr_get_n_adjs_walk (adj_index_t ai,
+ void *data)
+{
+ adj_nbr_get_n_adjs_walk_ctx_t *ctx = data;
+ const ip_adjacency_t *adj;
+
+ adj = adj_get(ai);
+
+ if (ctx->linkt == adj->ia_link)
+ ctx->count++;
+
+ return (ADJ_WALK_RC_CONTINUE);
+}
+
+u32
+adj_nbr_get_n_adjs (vnet_link_t link_type, u32 sw_if_index)
+{
+ adj_nbr_get_n_adjs_walk_ctx_t ctx = {
+ .linkt = link_type,
+ };
+ fib_protocol_t fproto;
+
+ FOR_EACH_FIB_IP_PROTOCOL(fproto)
+ {
+ adj_nbr_walk (sw_if_index,
+ fproto,
+ adj_nbr_get_n_adjs_walk,
+ &ctx);
+ }
+
+ return (ctx.count);
+}
+
adj_index_t
adj_nbr_find (fib_protocol_t nh_proto,
vnet_link_t link_type,
@@ -492,7 +532,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
fib_walk_sync(FIB_NODE_TYPE_ADJ, walk_ai, &bw_ctx);
/*
- * fib_walk_sync may allocate a new adjacency and potentially cuase a
+ * fib_walk_sync may allocate a new adjacency and potentially cause a
* realloc for adj_pool. When that happens, adj pointer is no longer
* valid here. We refresh the adj pointer accordingly.
*/
@@ -560,7 +600,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
}
- adj_delegate_adj_modified(adj);
+ adj_delegate_adj_modified(adj_get(ai));
adj_unlock(ai);
adj_unlock(walk_ai);
}
@@ -753,9 +793,15 @@ adj_nbr_interface_state_change_one (adj_index_t ai,
adj_lock (ai);
adj = adj_get(ai);
-
adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE;
fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
+
+ /*
+ * fib_walk_sync may allocate a new adjacency and potentially cause a
+ * realloc for adj_pool. When that happens, adj pointer is no longer
+ * valid here. We refresh the adj pointer accordingly.
+ */
+ adj = adj_get(ai);
adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
adj_unlock (ai);
@@ -863,9 +909,15 @@ adj_nbr_interface_delete_one (adj_index_t ai,
adj_lock(ai);
adj = adj_get(ai);
-
adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE;
fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
+
+ /*
+ * fib_walk_sync may allocate a new adjacency and potentially cause a
+ * realloc for adj_pool. When that happens, adj pointer is no longer
+ * valid here. We refresh the adj pointer accordingly.
+ */
+ adj = adj_get(ai);
adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
adj_unlock(ai);
diff --git a/src/vnet/adj/adj_nsh.c b/src/vnet/adj/adj_nsh.c
index 00d945729d8..1b4fa6c15b9 100644
--- a/src/vnet/adj/adj_nsh.c
+++ b/src/vnet/adj/adj_nsh.c
@@ -190,7 +190,6 @@ VLIB_REGISTER_NODE (adj_nsh_midchain_node) = {
};
/* Built-in ip4 tx feature path definition */
-/* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (nsh_output, static) =
{
.arc_name = "nsh-output",
@@ -204,4 +203,3 @@ VNET_FEATURE_INIT (nsh_tx_drop, static) =
.node_name = "error-drop",
.runs_before = 0, /* not before any other features */
};
-/* *INDENT-ON* */
diff --git a/src/vnet/adj/rewrite.h b/src/vnet/adj/rewrite.h
index 4234986dc37..06b1b00882e 100644
--- a/src/vnet/adj/rewrite.h
+++ b/src/vnet/adj/rewrite.h
@@ -136,7 +136,7 @@ always_inline void
vnet_rewrite_clear_data_internal (vnet_rewrite_header_t * rw, int max_size)
{
/* Sanity check values carefully for this clib_memset operation */
- ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE));
+ ASSERT ((max_size > 0) && (max_size < VNET_REWRITE_TOTAL_BYTES));
rw->data_bytes = 0;
clib_memset (rw->data, 0xfe, max_size);
@@ -147,8 +147,8 @@ vnet_rewrite_set_data_internal (vnet_rewrite_header_t * rw,
int max_size, void *data, int data_bytes)
{
/* Sanity check values carefully for this clib_memset operation */
- ASSERT ((max_size > 0) && (max_size < VLIB_BUFFER_PRE_DATA_SIZE));
- ASSERT ((data_bytes >= 0) && (data_bytes < max_size));
+ ASSERT ((max_size > 0) && (max_size <= VNET_REWRITE_TOTAL_BYTES));
+ ASSERT ((data_bytes >= 0) && (data_bytes <= max_size));
rw->data_bytes = data_bytes;
clib_memcpy_fast (rw->data, data, data_bytes);