BV(clib_bihash_add_del) (adj_nbr_tables[nh_proto][sw_if_index], &kv, 0);
}
-static adj_index_t
+adj_index_t
adj_nbr_find (fib_protocol_t nh_proto,
vnet_link_t link_type,
const ip46_address_t *nh_addr,
return (ip4_arp_node.index);
}
+/**
+ * @brief Check and set feature flags if o/p interface has any o/p features.
+ */
+static void
+adj_nbr_evaluate_feature (adj_index_t ai)
+{
+ ip_adjacency_t *adj;
+ vnet_feature_main_t *fm = &feature_main;
+ i16 feature_count;
+ u8 arc_index;
+ u32 sw_if_index;
+
+ adj = adj_get(ai);
+
+ switch (adj->ia_link)
+ {
+ case VNET_LINK_IP4:
+ arc_index = ip4_main.lookup_main.output_feature_arc_index;
+ break;
+ case VNET_LINK_IP6:
+ arc_index = ip6_main.lookup_main.output_feature_arc_index;
+ break;
+ case VNET_LINK_MPLS:
+ arc_index = mpls_main.output_feature_arc_index;
+ break;
+ default:
+ return;
+ }
+
+ sw_if_index = adj->rewrite_header.sw_if_index;
+ if (vec_len(fm->feature_count_by_sw_if_index[arc_index]) > sw_if_index)
+ {
+ feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
+ if (feature_count > 0)
+ adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES;
+ }
+
+ return;
+}
+
static ip_adjacency_t*
adj_nbr_alloc (fib_protocol_t nh_proto,
vnet_link_t link_type,
adj->ia_link = link_type;
adj->ia_nh_proto = nh_proto;
adj->rewrite_header.sw_if_index = sw_if_index;
- memset(&adj->sub_type.midchain.next_dpo, 0,
- sizeof(adj->sub_type.midchain.next_dpo));
+ adj_nbr_evaluate_feature (adj_get_index(adj));
return (adj);
}
*/
void
adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
- u32 adj_next_index,
+ ip_lookup_next_t adj_next_index,
u32 this_node,
u32 next_node,
u8 *rewrite)
if (ADJ_INDEX_INVALID != walk_ai)
{
walk_adj = adj_get(walk_ai);
- if (IP_ADJ_SYNC_WALK_ACTIVE & walk_adj->ia_flags)
+ if (ADJ_FLAG_SYNC_WALK_ACTIVE & walk_adj->ia_flags)
{
do_walk = 0;
}
/*
* Prevent re-entrant walk of the same adj
*/
- walk_adj->ia_flags |= IP_ADJ_SYNC_WALK_ACTIVE;
+ walk_adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE;
do_walk = 1;
}
}
vnet_rewrite_clear_data_internal(&adj->rewrite_header,
sizeof(adj->rewrite_data));
}
- adj->rewrite_header.node_index = this_node;
adj->rewrite_header.next_index = vlib_node_add_next(vlib_get_main(),
this_node,
next_node);
*/
if (do_walk)
{
- walk_adj->ia_flags &= ~IP_ADJ_SYNC_WALK_ACTIVE;
+ walk_adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
}
adj_unlock(adj_get_index(adj));
&awc);
}
-/**
- * @brief Context for a walk of the adjacency neighbour DB
- */
-typedef struct adj_walk_nh_ctx_t_
-{
- adj_walk_cb_t awc_cb;
- void *awc_ctx;
- const ip46_address_t *awc_nh;
-} adj_walk_nh_ctx_t;
-
-static void
-adj_nbr_walk_nh_cb (BVT(clib_bihash_kv) * kvp,
- void *arg)
-{
- ip_adjacency_t *adj;
- adj_walk_nh_ctx_t *ctx = arg;
-
- adj = adj_get(kvp->value);
-
- if (!ip46_address_cmp(&adj->sub_type.nbr.next_hop, ctx->awc_nh))
- ctx->awc_cb(kvp->value, ctx->awc_ctx);
-}
-
/**
* @brief Walk adjacencies on a link with a given v4 next-hop.
* that is visit the adjacencies with different link types.
ip46_address_t nh = {
.ip4 = *addr,
};
+ vnet_link_t linkt;
+ adj_index_t ai;
- adj_walk_nh_ctx_t awc = {
- .awc_ctx = ctx,
- .awc_cb = cb,
- .awc_nh = &nh,
- };
+ FOR_EACH_VNET_LINK(linkt)
+ {
+ ai = adj_nbr_find (FIB_PROTOCOL_IP4, linkt, &nh, sw_if_index);
- BV(clib_bihash_foreach_key_value_pair) (
- adj_nbr_tables[FIB_PROTOCOL_IP4][sw_if_index],
- adj_nbr_walk_nh_cb,
- &awc);
+ if (INDEX_INVALID != ai)
+ cb(ai, ctx);
+ }
}
/**
ip46_address_t nh = {
.ip6 = *addr,
};
+ vnet_link_t linkt;
+ adj_index_t ai;
- adj_walk_nh_ctx_t awc = {
- .awc_ctx = ctx,
- .awc_cb = cb,
- .awc_nh = &nh,
- };
+ FOR_EACH_VNET_LINK(linkt)
+ {
+ ai = adj_nbr_find (FIB_PROTOCOL_IP6, linkt, &nh, sw_if_index);
- BV(clib_bihash_foreach_key_value_pair) (
- adj_nbr_tables[FIB_PROTOCOL_IP6][sw_if_index],
- adj_nbr_walk_nh_cb,
- &awc);
+ if (INDEX_INVALID != ai)
+ cb(ai, ctx);
+ }
}
/**
if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
return;
- adj_walk_nh_ctx_t awc = {
- .awc_ctx = ctx,
- .awc_cb = cb,
- .awc_nh = nh,
- };
+ vnet_link_t linkt;
+ adj_index_t ai;
- BV(clib_bihash_foreach_key_value_pair) (
- adj_nbr_tables[adj_nh_proto][sw_if_index],
- adj_nbr_walk_nh_cb,
- &awc);
+ FOR_EACH_VNET_LINK(linkt)
+ {
+ ai = adj_nbr_find (FIB_PROTOCOL_IP4, linkt, nh, sw_if_index);
+
+ if (INDEX_INVALID != ai)
+ cb(ai, ctx);
+ }
}
/**
* @brief Invoked on each SW interface of a HW interface when the
* HW interface state changes
*/
-static void
+static walk_rc_t
adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
u32 sw_if_index,
void *arg)
adj_nbr_interface_state_change_one,
ctx);
}
+ return (WALK_CONTINUE);
}
/**
.function = adj_nbr_show,
};
-static ip46_type_t
-adj_proto_to_46 (fib_protocol_t proto)
-{
- switch (proto)
- {
- case FIB_PROTOCOL_IP4:
- return (IP46_TYPE_IP4);
- case FIB_PROTOCOL_IP6:
- return (IP46_TYPE_IP6);
- default:
- return (IP46_TYPE_IP4);
- }
- return (IP46_TYPE_IP4);
-}
-
u8*
format_adj_nbr_incomplete (u8* s, va_list *ap)
{
format_ip46_address, &adj->sub_type.nbr.next_hop,
adj_proto_to_46(adj->ia_nh_proto));
s = format (s, " %U",
- format_vnet_sw_interface_name,
- vnm,
- vnet_get_sw_interface(vnm,
- adj->rewrite_header.sw_if_index));
+ format_vnet_sw_if_index_name,
+ vnm, adj->rewrite_header.sw_if_index);
return (s);
}
{
index_t index = va_arg(*ap, index_t);
CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
- vnet_main_t * vnm = vnet_get_main();
ip_adjacency_t * adj = adj_get(index);
s = format (s, "%U", format_vnet_link, adj->ia_link);
adj_proto_to_46(adj->ia_nh_proto));
s = format (s, "%U",
format_vnet_rewrite,
- vnm->vlib_main, &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
+ &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
return (s);
}
.dv_unlock = adj_dpo_unlock,
.dv_format = format_adj_nbr,
.dv_mem_show = adj_mem_show,
+ .dv_get_urpf = adj_dpo_get_urpf,
};
const static dpo_vft_t adj_nbr_incompl_dpo_vft = {
.dv_lock = adj_dpo_lock,
.dv_unlock = adj_dpo_unlock,
.dv_format = format_adj_nbr_incomplete,
+ .dv_get_urpf = adj_dpo_get_urpf,
};
/**