Labelled attached paths via an MPLS tunnel
[vpp.git] / src / vnet / mpls / mpls_tunnel.c
index 1254dd9..776b23b 100644 (file)
@@ -24,6 +24,7 @@
 #include <vnet/adj/adj_midchain.h>
 #include <vnet/adj/adj_mcast.h>
 #include <vnet/dpo/replicate_dpo.h>
+#include <vnet/fib/mpls_fib.h>
 
 /**
  * @brief pool of tunnel instances
@@ -98,14 +99,13 @@ typedef struct mpls_tunnel_collect_forwarding_ctx_t_
     fib_forward_chain_type_t fct;
 } mpls_tunnel_collect_forwarding_ctx_t;
 
-static int
+static fib_path_list_walk_rc_t
 mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
                                 fib_node_index_t path_index,
                                 void *arg)
 {
     mpls_tunnel_collect_forwarding_ctx_t *ctx;
     fib_path_ext_t *path_ext;
-    int have_path_ext;
 
     ctx = arg;
 
@@ -114,23 +114,16 @@ mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
      */
     if (!fib_path_is_resolved(path_index))
     {
-        return (!0);
+        return (FIB_PATH_LIST_WALK_CONTINUE);
     }
 
     /*
      * get the matching path-extension for the path being visited.
      */
-    have_path_ext = 0;
-    vec_foreach(path_ext, ctx->mt->mt_path_exts)
-    {
-        if (path_ext->fpe_path_index == path_index)
-        {
-            have_path_ext = 1;
-            break;
-        }
-    }
+    path_ext = fib_path_ext_list_find_by_path_index(&ctx->mt->mt_path_exts,
+                                                    path_index);
 
-    if (have_path_ext)
+    if (NULL != path_ext)
     {
         /*
          * found a matching extension. stack it to obtain the forwarding
@@ -148,7 +141,7 @@ mpls_tunnel_collect_forwarding (fib_node_index_t pl_index,
      *   There should be a path-extenios associated with each path
      */
 
-    return (!0);
+    return (FIB_PATH_LIST_WALK_CONTINUE);
 }
 
 static void
@@ -200,9 +193,20 @@ mpls_tunnel_mk_lb (mpls_tunnel_t *mt,
         {
             flow_hash_config_t fhc;
 
-            fhc = 0; // FIXME
-            /* fhc = fib_table_get_flow_hash_config(fib_entry->fe_fib_index, */
-            /*                                      dpo_proto_to_fib(lb_proto)); */
+            switch (linkt)
+            {
+            case VNET_LINK_MPLS:
+                fhc = MPLS_FLOW_HASH_DEFAULT;
+                break;
+            case VNET_LINK_IP4:
+            case VNET_LINK_IP6:
+                fhc = IP_FLOW_HASH_DEFAULT;
+                break;
+            default:
+                fhc = 0;
+                break;
+            }
+
             dpo_set(dpo_lb,
                     DPO_LOAD_BALANCE,
                     lb_proto,
@@ -269,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);
@@ -636,58 +642,6 @@ vnet_mpls_tunnel_create (u8 l2_only,
     return (mt->mt_sw_if_index);
 }
 
-/*
- * mpls_tunnel_path_ext_add
- *
- * append a path extension to the entry's list
- */
-static void
-mpls_tunnel_path_ext_append (mpls_tunnel_t *mt,
-                             const fib_route_path_t *rpath)
-{
-    if (NULL != rpath->frp_label_stack)
-    {
-        fib_path_ext_t *path_ext;
-
-        vec_add2(mt->mt_path_exts, path_ext, 1);
-
-        fib_path_ext_init(path_ext, mt->mt_path_list, rpath);
-    }
-}
-
-/*
- * mpls_tunnel_path_ext_insert
- *
- * insert, sorted, a path extension to the entry's list.
- * It's not strictly necessary in sort the path extensions, since each
- * extension has the path index to which it resolves. However, by being
- * sorted the load-balance produced has a deterministic order, not an order
- * based on the sequence of extension additions. this is a considerable benefit.
- */
-static void
-mpls_tunnel_path_ext_insert (mpls_tunnel_t *mt,
-                             const fib_route_path_t *rpath)
-{
-    if (0 == vec_len(mt->mt_path_exts))
-        return (mpls_tunnel_path_ext_append(mt, rpath));
-
-    if (NULL != rpath->frp_label_stack)
-    {
-        fib_path_ext_t path_ext;
-        int i = 0;
-
-        fib_path_ext_init(&path_ext, mt->mt_path_list, rpath);
-
-        while (i < vec_len(mt->mt_path_exts) &&
-               (fib_path_ext_cmp(&mt->mt_path_exts[i], rpath) < 0))
-        {
-            i++;
-        }
-
-        vec_insert_elts(mt->mt_path_exts, &path_ext, 1, i);
-    }
-}
-
 void
 vnet_mpls_tunnel_path_add (u32 sw_if_index,
                            fib_route_path_t *rpaths)
@@ -715,7 +669,6 @@ vnet_mpls_tunnel_path_add (u32 sw_if_index,
     else
     {
         fib_node_index_t old_pl_index;
-        fib_path_ext_t *path_ext;
 
         old_pl_index = mt->mt_path_list;
 
@@ -732,12 +685,12 @@ vnet_mpls_tunnel_path_add (u32 sw_if_index,
         /*
          * re-resolve all the path-extensions with the new path-list
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            fib_path_ext_resolve(path_ext, mt->mt_path_list);
-        }
+        fib_path_ext_list_resolve(&mt->mt_path_exts, mt->mt_path_list);
     }
-    mpls_tunnel_path_ext_insert(mt, rpaths);
+    fib_path_ext_list_insert(&mt->mt_path_exts,
+                             mt->mt_path_list,
+                             FIB_PATH_EXT_MPLS,
+                             rpaths);
     mpls_tunnel_restack(mt);
 }
 
@@ -766,7 +719,6 @@ vnet_mpls_tunnel_path_remove (u32 sw_if_index,
     else
     {
         fib_node_index_t old_pl_index;
-        fib_path_ext_t *path_ext;
 
         old_pl_index = mt->mt_path_list;
 
@@ -793,27 +745,15 @@ vnet_mpls_tunnel_path_remove (u32 sw_if_index,
         /*
          * find the matching path extension and remove it
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            if (!fib_path_ext_cmp(path_ext, rpaths))
-            {
-                /*
-                 * delete the element moving the remaining elements down 1 position.
-                 * this preserves the sorted order.
-                 */
-                vec_free(path_ext->fpe_label_stack);
-                vec_delete(mt->mt_path_exts, 1,
-                           (path_ext - mt->mt_path_exts));
-                break;
-            }
-        }
-       /*
+        fib_path_ext_list_remove(&mt->mt_path_exts,
+                                  FIB_PATH_EXT_MPLS,
+                                  rpaths);
+
+        /*
          * re-resolve all the path-extensions with the new path-list
          */
-        vec_foreach(path_ext, mt->mt_path_exts)
-        {
-            fib_path_ext_resolve(path_ext, mt->mt_path_list);
-        }
+        fib_path_ext_list_resolve(&mt->mt_path_exts,
+                                  mt->mt_path_list);
 
         mpls_tunnel_restack(mt);
    }
@@ -948,7 +888,6 @@ format_mpls_tunnel (u8 * s, va_list * args)
 {
     mpls_tunnel_t *mt = va_arg (*args, mpls_tunnel_t *);
     mpls_tunnel_attribute_t attr;
-    fib_path_ext_t *path_ext;
 
     s = format(s, "mpls_tunnel%d: sw_if_index:%d hw_if_index:%d",
                mt - mpls_tunnel_pool,
@@ -964,11 +903,7 @@ format_mpls_tunnel (u8 * s, va_list * args)
     }
     s = format(s, "\n via:\n");
     s = fib_path_list_format(mt->mt_path_list, s);
-    s = format(s, "    Extensions:");
-    vec_foreach(path_ext, mt->mt_path_exts)
-    {
-        s = format(s, "\n     %U", format_fib_path_ext, path_ext);
-    }
+    s = format(s, "%U", format_fib_path_ext_list, &mt->mt_path_exts);
     s = format(s, "\n");
 
     return (s);