+/*
+ * Context for the walk to update the cached feture flags.
+ */
+typedef struct adj_feature_update_t_
+{
+ u8 arc;
+ u8 enable;
+} adj_feature_update_ctx_t;
+
+static adj_walk_rc_t
+adj_feature_update_walk_cb (adj_index_t ai,
+ void *arg)
+{
+ adj_feature_update_ctx_t *ctx = arg;
+ ip_adjacency_t *adj;
+
+ adj = adj_get(ai);
+
+ /*
+ * this ugly mess matches the feature arc that is changing with affected
+ * adjacencies
+ */
+ if (((ctx->arc == ip6_main.lookup_main.output_feature_arc_index) &&
+ (VNET_LINK_IP6 == adj->ia_link)) ||
+ ((ctx->arc == ip4_main.lookup_main.output_feature_arc_index) &&
+ (VNET_LINK_IP4 == adj->ia_link)) ||
+ ((ctx->arc == mpls_main.output_feature_arc_index) &&
+ (VNET_LINK_MPLS == adj->ia_link)))
+ {
+ if (ctx->enable)
+ adj->rewrite_header.flags |= VNET_REWRITE_HAS_FEATURES;
+ else
+ adj->rewrite_header.flags &= ~VNET_REWRITE_HAS_FEATURES;
+ }
+ return (ADJ_WALK_RC_CONTINUE);
+}
+
+void
+adj_feature_update (u32 sw_if_index,
+ u8 arc_index,
+ u8 is_enable)
+{
+ /*
+ * Walk all the adjacencies on the interface to update the cached
+ * 'has-features' flag
+ */
+ adj_feature_update_ctx_t ctx = {
+ .arc = arc_index,
+ .enable = is_enable,
+ };
+ adj_walk (sw_if_index, adj_feature_update_walk_cb, &ctx);
+}
+
+/**
+ * @brief Walk the Adjacencies on a given interface
+ */
+void
+adj_walk (u32 sw_if_index,
+ adj_walk_cb_t cb,
+ void *ctx)
+{
+ /*
+ * walk all the neighbor adjacencies
+ */
+ fib_protocol_t proto;
+
+ FOR_EACH_FIB_IP_PROTOCOL(proto)
+ {
+ adj_nbr_walk(sw_if_index, proto, cb, ctx);
+ adj_mcast_walk(sw_if_index, proto, cb, ctx);
+ }
+}
+