diff options
author | Neale Ranns <nranns@cisco.com> | 2017-05-23 03:43:47 -0700 |
---|---|---|
committer | Neale Ranns <nranns@cisco.com> | 2017-05-23 03:44:33 -0700 |
commit | 8c4611b39162da9753caaf654741faa115eaf612 (patch) | |
tree | 058a123261fd66922d21bb784d08f6436d49f5fb | |
parent | 5c89c420861ab938151f0bb0a298bb04d590ff2b (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.c | 1 | ||||
-rw-r--r-- | src/vnet/dpo/dpo.c | 3 | ||||
-rw-r--r-- | src/vnet/fib/fib_path.c | 70 | ||||
-rw-r--r-- | src/vnet/fib/fib_walk.c | 31 | ||||
-rw-r--r-- | src/vnet/mpls/mpls_tunnel.c | 4 | ||||
-rw-r--r-- | test/test_mpls.py | 27 |
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 """ |