aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-05-23 03:43:47 -0700
committerNeale Ranns <nranns@cisco.com>2017-05-23 03:44:33 -0700
commit8c4611b39162da9753caaf654741faa115eaf612 (patch)
tree058a123261fd66922d21bb784d08f6436d49f5fb
parent5c89c420861ab938151f0bb0a298bb04d590ff2b (diff)
Labelled attached paths via an MPLS tunnel
Change-Id: Ic86617c9c3217122043656ce2ea70bb106df5b2d Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/vnet/adj/adj.c1
-rw-r--r--src/vnet/dpo/dpo.c3
-rw-r--r--src/vnet/fib/fib_path.c70
-rw-r--r--src/vnet/fib/fib_walk.c31
-rw-r--r--src/vnet/mpls/mpls_tunnel.c4
-rw-r--r--test/test_mpls.py27
6 files changed, 94 insertions, 42 deletions
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index bf44383fd5f..f84969136c9 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -64,6 +64,7 @@ adj_alloc (fib_protocol_t proto)
adj->ia_nh_proto = proto;
adj->ia_flags = 0;
adj->rewrite_header.sw_if_index = ~0;
+ adj->rewrite_header.flags = 0;
adj->lookup_next_index = 0;
adj->ia_delegates = NULL;
diff --git a/src/vnet/dpo/dpo.c b/src/vnet/dpo/dpo.c
index dfc2bd923ce..28aa0c23351 100644
--- a/src/vnet/dpo/dpo.c
+++ b/src/vnet/dpo/dpo.c
@@ -189,6 +189,9 @@ dpo_set (dpo_id_t *dpo,
break;
case IP_LOOKUP_NEXT_MCAST:
dpo->dpoi_type = DPO_ADJACENCY_MCAST;
+ break;
+ case IP_LOOKUP_NEXT_GLEAN:
+ dpo->dpoi_type = DPO_ADJACENCY_GLEAN;
break;
default:
break;
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index 255f0dd18c6..274b0ef4bf1 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -588,6 +588,30 @@ fib_path_attached_next_hop_set (fib_path_t *path)
}
}
+static const adj_index_t
+fib_path_attached_get_adj (fib_path_t *path,
+ vnet_link_t link)
+{
+ if (vnet_sw_interface_is_p2p(vnet_get_main(),
+ path->attached.fp_interface))
+ {
+ /*
+ * point-2-point interfaces do not require a glean, since
+ * there is nothing to ARP. Install a rewrite/nbr adj instead
+ */
+ return (adj_nbr_add_or_lock(path->fp_nh_proto,
+ link,
+ &zero_addr,
+ path->attached.fp_interface));
+ }
+ else
+ {
+ return (adj_glean_add_or_lock(path->fp_nh_proto,
+ path->attached.fp_interface,
+ NULL));
+ }
+}
+
/*
* create of update the paths recursive adj
*/
@@ -1559,31 +1583,12 @@ fib_path_resolve (fib_node_index_t path_index)
{
path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
}
- if (vnet_sw_interface_is_p2p(vnet_get_main(),
- path->attached.fp_interface))
- {
- /*
- * point-2-point interfaces do not require a glean, since
- * there is nothing to ARP. Install a rewrite/nbr adj instead
- */
- dpo_set(&path->fp_dpo,
- DPO_ADJACENCY,
- fib_proto_to_dpo(path->fp_nh_proto),
- adj_nbr_add_or_lock(
- path->fp_nh_proto,
- fib_proto_to_link(path->fp_nh_proto),
- &zero_addr,
- path->attached.fp_interface));
- }
- else
- {
- dpo_set(&path->fp_dpo,
- DPO_ADJACENCY_GLEAN,
- fib_proto_to_dpo(path->fp_nh_proto),
- adj_glean_add_or_lock(path->fp_nh_proto,
- path->attached.fp_interface,
- NULL));
- }
+ dpo_set(&path->fp_dpo,
+ DPO_ADJACENCY,
+ fib_proto_to_dpo(path->fp_nh_proto),
+ fib_path_attached_get_adj(path,
+ fib_proto_to_link(path->fp_nh_proto)));
+
/*
* become a child of the adjacency so we receive updates
* when the interface state changes
@@ -1969,7 +1974,20 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
case FIB_FORW_CHAIN_TYPE_ETHERNET:
case FIB_FORW_CHAIN_TYPE_NSH:
- break;
+ {
+ adj_index_t ai;
+
+ /*
+ * get a appropriate link type adj.
+ */
+ ai = fib_path_attached_get_adj(
+ path,
+ fib_forw_chain_type_to_link_type(fct));
+ dpo_set(dpo, DPO_ADJACENCY,
+ fib_forw_chain_type_to_dpo_proto(fct), ai);
+ adj_unlock(ai);
+ break;
+ }
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
{
diff --git a/src/vnet/fib/fib_walk.c b/src/vnet/fib/fib_walk.c
index c570476d130..701801370b1 100644
--- a/src/vnet/fib/fib_walk.c
+++ b/src/vnet/fib/fib_walk.c
@@ -322,10 +322,10 @@ typedef enum fib_walk_advance_rc_t_
static fib_walk_advance_rc_t
fib_walk_advance (fib_node_index_t fwi)
{
- fib_node_back_walk_ctx_t *ctx, *old;
fib_node_back_walk_rc_t wrc;
fib_node_ptr_t sibling;
fib_walk_t *fwalk;
+ uint n_ctxs, ii;
int more_elts;
/*
@@ -339,12 +339,20 @@ fib_walk_advance (fib_node_index_t fwi)
if (more_elts)
{
- old = fwalk->fw_ctx;
- vec_foreach(ctx, fwalk->fw_ctx)
- {
- wrc = fib_node_back_walk_one(&sibling, ctx);
+ /*
+ * loop through the backwalk contexts. This can grow in length
+ * as walks on the same object meet each other. Order is preserved so the
+ * most recently started walk as at the back of the vector.
+ */
+ ii = 0;
+ n_ctxs = vec_len(fwalk->fw_ctx);
+
+ while (ii < n_ctxs)
+ {
+ wrc = fib_node_back_walk_one(&sibling, &fwalk->fw_ctx[ii]);
+ ii++;
fwalk = fib_walk_get(fwi);
fwalk->fw_n_visits++;
@@ -356,14 +364,11 @@ fib_walk_advance (fib_node_index_t fwi)
*/
return (FIB_WALK_ADVANCE_MERGE);
}
- if (old != fwalk->fw_ctx)
- {
- /*
- * nasty re-entrant addition of a walk has realloc'd the vector
- * break out
- */
- return (FIB_WALK_ADVANCE_MERGE);
- }
+
+ /*
+ * re-evaluate the number of backwalk contexts we need to process.
+ */
+ n_ctxs = vec_len(fwalk->fw_ctx);
}
/*
* move foward to the next node to visit
diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c
index d6e85e70b44..776b23baf87 100644
--- a/src/vnet/mpls/mpls_tunnel.c
+++ b/src/vnet/mpls/mpls_tunnel.c
@@ -273,7 +273,9 @@ mpls_tunnel_stack (adj_index_t ai)
mpls_tunnel_mk_lb(mt,
adj->ia_link,
- FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ (VNET_LINK_MPLS == adj_get_link_type(ai) ?
+ FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS),
&dpo);
adj_nbr_midchain_stack(ai, &dpo);
diff --git a/test/test_mpls.py b/test/test_mpls.py
index 0ad1ee6977e..d0c9e249a05 100644
--- a/test/test_mpls.py
+++ b/test/test_mpls.py
@@ -203,7 +203,10 @@ class TestMPLS(VppTestCase):
except:
raise
- def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels):
+ def verify_capture_tunneled_ip4(self, src_if, capture, sent, mpls_labels,
+ ttl=255, top=None):
+ if top is None:
+ top = len(mpls_labels) - 1
try:
capture = self.verify_filter(capture, sent)
@@ -217,7 +220,7 @@ class TestMPLS(VppTestCase):
# the MPLS TTL is 255 since it enters a new tunnel
self.verify_mpls_stack(
- rx, mpls_labels, 255, len(mpls_labels) - 1)
+ rx, mpls_labels, ttl, top)
self.assertEqual(rx_ip.src, tx_ip.src)
self.assertEqual(rx_ip.dst, tx_ip.dst)
@@ -617,6 +620,26 @@ class TestMPLS(VppTestCase):
rx = self.pg0.get_capture()
self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46])
+ #
+ # add a labelled route through the new tunnel
+ #
+ route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32,
+ [VppRoutePath("0.0.0.0",
+ mpls_tun._sw_if_index,
+ labels=[33])])
+ route_10_0_0_4.add_vpp_config()
+
+ self.vapi.cli("clear trace")
+ tx = self.create_stream_ip4(self.pg0, "10.0.0.4")
+ self.pg0.add_stream(tx)
+
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg0.get_capture()
+ self.verify_capture_tunneled_ip4(self.pg0, rx, tx, [44, 46, 33],
+ ttl=63, top=2)
+
def test_v4_exp_null(self):
""" MPLS V4 Explicit NULL test """