IP-Punt-redirect: allow the use of a FIB path to describe how to
redirect
Change-Id: I2a3ba2a3d73ea8511e3a511855b041432328f0a8
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/ip/ip_punt_drop.h b/src/vnet/ip/ip_punt_drop.h
index ccf88e5..3e2796e 100644
--- a/src/vnet/ip/ip_punt_drop.h
+++ b/src/vnet/ip/ip_punt_drop.h
@@ -194,19 +194,19 @@
typedef struct ip_punt_redirect_rx_t_
{
/**
- * The next-hop to send redirected packets to
+ * Node linkage into the FIB graph
*/
- ip46_address_t nh;
+ fib_node_t node;
+
+ fib_protocol_t fproto;
+ fib_forward_chain_type_t payload_type;
+ fib_node_index_t pl;
+ u32 sibling;
/**
- * the TX interface to send redirected packets
+ * redirect forwarding
*/
- u32 tx_sw_if_index;
-
- /**
- * redirect forwarding adjacency
- */
- adj_index_t adj_index;
+ dpo_id_t dpo;
} ip_punt_redirect_rx_t;
/**
@@ -214,16 +214,17 @@
*/
typedef struct ip_punt_redirect_t_
{
- /**
- * any RX interface redirect
- */
- ip_punt_redirect_rx_t any_rx_sw_if_index;
+ ip_punt_redirect_rx_t *pool;
- /**
- * per-RX interface configuration
- */
- ip_punt_redirect_rx_t *redirect_by_rx_sw_if_index;
-} ip_punt_redirect_t;
+ /**
+ * per-RX interface configuration.
+ * sw_if_index = 0 (from which packets are never received) is used to
+ * indicate 'from-any'
+ */
+ index_t *redirect_by_rx_sw_if_index[FIB_PROTOCOL_IP_MAX];
+} ip_punt_redirect_cfg_t;
+
+extern ip_punt_redirect_cfg_t ip_punt_redirect_cfg;
/**
* IP punt redirect next nodes
@@ -241,75 +242,51 @@
*/
typedef struct ip4_punt_redirect_trace_t_
{
- ip_punt_redirect_rx_t redirect;
+ index_t rrxi;
u32 next;
} ip_punt_redirect_trace_t;
-typedef struct ip_punt_redirect_detail_t_
-{
- /**
- * the RX interface
- */
- u32 rx_sw_if_index;
- /**
- * IP punt redirect configuration
- */
- ip_punt_redirect_rx_t punt_redirect;
-} ip_punt_redirect_detail_t;
-
/**
* Add a punt redirect entry
*/
-extern void ip_punt_redirect_add (ip_punt_redirect_t * cfg,
+extern void ip_punt_redirect_add (fib_protocol_t fproto,
u32 rx_sw_if_index,
- ip_punt_redirect_rx_t * redirect,
- fib_protocol_t fproto, vnet_link_t linkt);
-extern void ip_punt_redirect_del (ip_punt_redirect_t * cfg,
- u32 rx_sw_if_index);
+ fib_forward_chain_type_t ct,
+ fib_route_path_t * rpaths);
+
+extern void ip_punt_redirect_del (fib_protocol_t fproto, u32 rx_sw_if_index);
+extern index_t ip_punt_redirect_find (fib_protocol_t fproto,
+ u32 rx_sw_if_index);
extern u8 *format_ip_punt_redirect (u8 * s, va_list * args);
extern u8 *format_ip_punt_redirect_trace (u8 * s, va_list * args);
-extern ip_punt_redirect_detail_t *ip4_punt_redirect_entries (u32 sw_if_index);
-extern ip_punt_redirect_detail_t *ip6_punt_redirect_entries (u32 sw_if_index);
+typedef walk_rc_t (*ip_punt_redirect_walk_cb_t) (u32 rx_sw_if_index,
+ const ip_punt_redirect_rx_t *
+ redirect, void *arg);
+extern void ip_punt_redirect_walk (fib_protocol_t fproto,
+ ip_punt_redirect_walk_cb_t cb, void *ctx);
-always_inline u32
-ip_punt_redirect_tx_via_adj (vlib_buffer_t * b0, adj_index_t ai)
+static_always_inline ip_punt_redirect_rx_t *
+ip_punt_redirect_get (index_t rrxi)
{
- ip_adjacency_t *adj = adj_get (ai);
- u32 next0;
-
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ai;
-
- switch (adj->lookup_next_index)
- {
- case IP_LOOKUP_NEXT_ARP:
- next0 = IP_PUNT_REDIRECT_NEXT_ARP;
- break;
- case IP_LOOKUP_NEXT_REWRITE:
- next0 = IP_PUNT_REDIRECT_NEXT_TX;
- break;
- default:
- next0 = IP_PUNT_REDIRECT_NEXT_DROP;
- break;
- }
-
- return (next0);
+ return (pool_elt_at_index (ip_punt_redirect_cfg.pool, rrxi));
}
always_inline uword
ip_punt_redirect (vlib_main_t * vm,
vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- u8 arc_index, ip_punt_redirect_t * redirect)
+ vlib_frame_t * frame, u8 arc_index, fib_protocol_t fproto)
{
u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
vnet_feature_main_t *fm = &feature_main;
vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc_index];
+ index_t *redirects;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
+ redirects = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
while (n_left_from > 0)
{
@@ -317,13 +294,13 @@
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 rx_sw_if_index0;
+ u32 rx_sw_if_index0, rrxi0;
ip_punt_redirect_rx_t *rrx0;
vlib_buffer_t *b0;
u32 next0;
u32 bi0;
- rrx0 = NULL;
+ rrxi0 = INDEX_INVALID;
next0 = 0;
bi0 = to_next[0] = from[0];
@@ -339,24 +316,24 @@
rx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- if (vec_len (redirect->redirect_by_rx_sw_if_index) >
- rx_sw_if_index0)
+ /*
+ * If config exists for this particular RX interface use it,
+ * else use the default (at RX = 0)
+ */
+ if (vec_len (redirects) > rx_sw_if_index0)
{
- rrx0 = &redirect->redirect_by_rx_sw_if_index[rx_sw_if_index0];
- if (~0 != rrx0->tx_sw_if_index)
- {
- next0 = ip_punt_redirect_tx_via_adj (b0, rrx0->adj_index);
- }
- else if (~0 != redirect->any_rx_sw_if_index.tx_sw_if_index)
- {
- rrx0 = &redirect->any_rx_sw_if_index;
- next0 = ip_punt_redirect_tx_via_adj (b0, rrx0->adj_index);
- }
+ rrxi0 = redirects[rx_sw_if_index0];
+ if (INDEX_INVALID == rrxi0)
+ rrxi0 = redirects[0];
}
- else if (~0 != redirect->any_rx_sw_if_index.tx_sw_if_index)
+ else if (vec_len (redirects) >= 1)
+ rrxi0 = redirects[0];
+
+ if (PREDICT_TRUE (INDEX_INVALID != rrxi0))
{
- rrx0 = &redirect->any_rx_sw_if_index;
- next0 = ip_punt_redirect_tx_via_adj (b0, rrx0->adj_index);
+ rrx0 = ip_punt_redirect_get (rrxi0);
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] = rrx0->dpo.dpoi_index;
+ next0 = rrx0->dpo.dpoi_next_node;
}
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -364,8 +341,7 @@
ip_punt_redirect_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
t->next = next0;
- if (rrx0)
- t->redirect = *rrx0;
+ t->rrxi = rrxi0;
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,