Labelled attached paths via an MPLS tunnel 37/6837/1
authorNeale Ranns <nranns@cisco.com>
Tue, 23 May 2017 10:43:47 +0000 (03:43 -0700)
committerNeale Ranns <nranns@cisco.com>
Tue, 23 May 2017 10:44:33 +0000 (03:44 -0700)
Change-Id: Ic86617c9c3217122043656ce2ea70bb106df5b2d
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet/adj/adj.c
src/vnet/dpo/dpo.c
src/vnet/fib/fib_path.c
src/vnet/fib/fib_walk.c
src/vnet/mpls/mpls_tunnel.c
test/test_mpls.py

index bf44383..f849691 100644 (file)
@@ -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;
 
index dfc2bd9..28aa0c2 100644 (file)
@@ -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;
index 255f0dd..274b0ef 100644 (file)
@@ -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:
                 {
index c570476..7018013 100644 (file)
@@ -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
index d6e85e7..776b23b 100644 (file)
@@ -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);
index 0ad1ee6..d0c9e24 100644 (file)
@@ -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 """