fib: Source Address Selection
[vpp.git] / src / vnet / fib / fib_entry_src.c
index c6c2a04..7f4db6a 100644 (file)
 #include <vnet/fib/fib_table.h>
 #include <vnet/fib/fib_path_ext.h>
 #include <vnet/fib/fib_urpf_list.h>
+#include <vnet/fib/fib_entry_delegate.h>
 
 /*
  * per-source type vft
  */
-static fib_entry_src_vft_t fib_entry_src_vft[FIB_SOURCE_MAX];
+static fib_entry_src_vft_t fib_entry_src_bh_vft[FIB_SOURCE_BH_MAX];
 
 /**
  * Get the VFT for a given source. This is a combination of the source
@@ -36,12 +37,16 @@ static fib_entry_src_vft_t fib_entry_src_vft[FIB_SOURCE_MAX];
 const fib_entry_src_vft_t*
 fib_entry_src_get_vft (const fib_entry_src_t *esrc)
 {
+    fib_source_behaviour_t bh;
+
+    bh = fib_source_get_behaviour(esrc->fes_src);
+
     if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_INTERPOSE)
     {
-        return (&fib_entry_src_vft[FIB_SOURCE_INTERPOSE]);
+        return (&fib_entry_src_bh_vft[FIB_SOURCE_BH_INTERPOSE]);
     }
 
-    return (&fib_entry_src_vft[esrc->fes_src]);
+    return (&fib_entry_src_bh_vft[bh]);
 }
 
 static void
@@ -53,14 +58,14 @@ fib_entry_src_copy_default (const fib_entry_src_t *orig_src,
 }
 
 void
-fib_entry_src_register (fib_source_t source,
-                       const fib_entry_src_vft_t *vft)
+fib_entry_src_behaviour_register (fib_source_behaviour_t bh,
+                                  const fib_entry_src_vft_t *vft)
 {
-    fib_entry_src_vft[source] = *vft;
+    fib_entry_src_bh_vft[bh] = *vft;
 
-    if (NULL == fib_entry_src_vft[source].fesv_copy)
+    if (NULL == fib_entry_src_bh_vft[bh].fesv_copy)
     {
-        fib_entry_src_vft[source].fesv_copy = fib_entry_src_copy_default;
+        fib_entry_src_bh_vft[bh].fesv_copy = fib_entry_src_copy_default;
     }
 }
 
@@ -70,7 +75,8 @@ fib_entry_src_cmp_for_sort (void * v1,
 {
     fib_entry_src_t *esrc1 = v1, *esrc2 = v2;
 
-    return (esrc1->fes_src - esrc2->fes_src);
+    return (fib_source_get_prio(esrc1->fes_src) -
+            fib_source_get_prio(esrc2->fes_src));
 }
 
 static void
@@ -85,7 +91,7 @@ fib_entry_src_action_init (fib_entry_t *fib_entry,
         .fes_entry_flags = flags,
     };
 
-    FIB_ENTRY_SRC_VFT_INVOKE(&esrc, fesv_init, (&esrc));
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, &esrc, fesv_init, (&esrc));
 
     vec_add1(fib_entry->fe_srcs, esrc);
     vec_sort_with_function(fib_entry->fe_srcs,
@@ -121,7 +127,7 @@ fib_entry_src_find_i (const fib_entry_t *fib_entry,
     return (NULL);
 }
 
-static fib_entry_src_t *
+fib_entry_src_t *
 fib_entry_src_find (const fib_entry_t *fib_entry,
                    fib_source_t source)
 
@@ -140,6 +146,44 @@ fib_entry_is_sourced (fib_node_index_t fib_entry_index,
     return (NULL != fib_entry_src_find(fib_entry, source));
 }
 
+int
+fib_entry_is_marked (fib_node_index_t fib_entry_index,
+                      fib_source_t source)
+{
+    fib_entry_t *fib_entry;
+    fib_entry_src_t *esrc;
+
+    fib_entry = fib_entry_get(fib_entry_index);
+
+    esrc = fib_entry_src_find(fib_entry, source);
+
+    if (NULL == esrc)
+    {
+        return (0);
+    }
+    else
+    {
+        return (!!(esrc->fes_flags & FIB_ENTRY_SRC_FLAG_STALE));
+    }
+}
+
+void
+fib_entry_mark (fib_node_index_t fib_entry_index,
+                fib_source_t source)
+{
+    fib_entry_t *fib_entry;
+    fib_entry_src_t *esrc;
+
+    fib_entry = fib_entry_get(fib_entry_index);
+
+    esrc = fib_entry_src_find(fib_entry, source);
+
+    if (NULL != esrc)
+    {
+        esrc->fes_flags |= FIB_ENTRY_SRC_FLAG_STALE;
+    }
+}
+
 static fib_entry_src_t *
 fib_entry_src_find_or_create (fib_entry_t *fib_entry,
                              fib_source_t source,
@@ -169,7 +213,7 @@ fib_entry_src_action_deinit (fib_entry_t *fib_entry,
 
     ASSERT(NULL != esrc);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_deinit, (esrc));
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_deinit, (esrc));
 
     fib_path_ext_list_flush(&esrc->fes_path_exts);
     vec_del1(fib_entry->fe_srcs, index);
@@ -732,7 +776,7 @@ fib_entry_src_action_copy (fib_entry_t *fib_entry,
                                         orig_src->fes_src,
                                         orig_src->fes_entry_flags);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_copy,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_copy,
                              (orig_src, fib_entry, esrc));
 
     fib_path_list_unlock(esrc->fes_pl);
@@ -1051,7 +1095,7 @@ fib_entry_src_action_deactivate (fib_entry_t *fib_entry,
 
     ASSERT(esrc->fes_flags & FIB_ENTRY_SRC_FLAG_ACTIVE);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_deactivate,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_deactivate,
                              (esrc, fib_entry));
 
     esrc->fes_flags &= ~(FIB_ENTRY_SRC_FLAG_ACTIVE |
@@ -1090,7 +1134,7 @@ fib_entry_src_action_fwd_update (const fib_entry_t *fib_entry,
 
     vec_foreach(esrc, fib_entry->fe_srcs)
     {
-       FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_fwd_update,
+       FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_fwd_update,
                                  (esrc, fib_entry, source));
     }
 }
@@ -1179,18 +1223,20 @@ fib_entry_src_action_reactivate (fib_entry_t *fib_entry,
     fib_entry_src_action_fwd_update(fib_entry, source);
 }
 
-void
-fib_entry_src_action_installed (const fib_entry_t *fib_entry,
+fib_entry_t *
+fib_entry_src_action_installed (fib_entry_t *fib_entry,
                                fib_source_t source)
 {
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find(fib_entry, source);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_installed,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_installed,
                              (esrc, fib_entry));
 
     fib_entry_src_action_fwd_update(fib_entry, source);
+
+    return (fib_entry);
 }
 
 /*
@@ -1207,7 +1253,6 @@ fib_entry_src_action_add (fib_entry_t *fib_entry,
                          fib_entry_flag_t flags,
                          const dpo_id_t *dpo)
 {
-    fib_node_index_t fib_entry_index;
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find_or_create(fib_entry, source, flags);
@@ -1217,7 +1262,7 @@ fib_entry_src_action_add (fib_entry_t *fib_entry,
 
     if (flags != esrc->fes_entry_flags)
     {
-        FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_flags_change,
+        FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_flags_change,
                                  (esrc, fib_entry, flags));
     }
     esrc->fes_entry_flags = flags;
@@ -1230,20 +1275,13 @@ fib_entry_src_action_add (fib_entry_t *fib_entry,
         return (fib_entry);
     }
 
-    /*
-     * save variable so we can recover from a fib_entry realloc.
-     */
-    fib_entry_index = fib_entry_get_index(fib_entry);
-
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_add,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_add,
                              (esrc,
                               fib_entry,
                               flags,
                               fib_entry_get_dpo_proto(fib_entry),
                               dpo));
 
-    fib_entry = fib_entry_get(fib_entry_index);
-
     esrc->fes_flags |= FIB_ENTRY_SRC_FLAG_ADDED;
 
     fib_path_list_lock(esrc->fes_pl);
@@ -1270,7 +1308,7 @@ fib_entry_src_action_update (fib_entry_t *fib_entry,
                             fib_entry_flag_t flags,
                             const dpo_id_t *dpo)
 {
-    fib_node_index_t fib_entry_index, old_path_list_index;
+    fib_node_index_t old_path_list_index;
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find_or_create(fib_entry, source, flags);
@@ -1283,20 +1321,13 @@ fib_entry_src_action_update (fib_entry_t *fib_entry,
     old_path_list_index = esrc->fes_pl;
     esrc->fes_entry_flags = flags;
 
-    /*
-     * save variable so we can recover from a fib_entry realloc.
-     */
-    fib_entry_index = fib_entry_get_index(fib_entry);
-
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_add,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_add,
                              (esrc,
                               fib_entry,
                               flags,
                               fib_entry_get_dpo_proto(fib_entry),
                               dpo));
 
-    fib_entry = fib_entry_get(fib_entry_index);
-
     esrc->fes_flags |= FIB_ENTRY_SRC_FLAG_ADDED;
 
     fib_path_list_lock(esrc->fes_pl);
@@ -1391,14 +1422,14 @@ fib_entry_src_action_remove (fib_entry_t *fib_entry,
     }
     else if (esrc->fes_flags & FIB_ENTRY_SRC_FLAG_CONTRIBUTING)
     {
-        FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_deactivate,
+        FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_deactivate,
                                  (esrc, fib_entry));
         esrc->fes_flags &= ~FIB_ENTRY_SRC_FLAG_CONTRIBUTING;
     }
 
     old_path_list = esrc->fes_pl;
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_remove, (esrc));
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_remove, (esrc));
 
     fib_path_list_unlock(old_path_list);
     fib_entry_unlock(fib_entry_get_index(fib_entry));
@@ -1460,7 +1491,8 @@ fib_path_is_attached (const fib_route_path_t *rpath)
     {
        return (!0);
     }
-    else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
+    else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED ||
+             rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
     {
         return (!0);
     }
@@ -1490,34 +1522,39 @@ fib_entry_src_flags_2_path_list_flags (fib_entry_flag_t eflags)
 
 static void
 fib_entry_flags_update (const fib_entry_t *fib_entry,
-                       const fib_route_path_t *rpath,
+                       const fib_route_path_t *rpaths,
                        fib_path_list_flags_t *pl_flags,
                        fib_entry_src_t *esrc)
 {
-    if ((esrc->fes_src == FIB_SOURCE_API) ||
-       (esrc->fes_src == FIB_SOURCE_CLI))
-    {
-       if (fib_path_is_attached(rpath))
-       {
-           esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED;
-       }
-       else
-       {
-           esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_ATTACHED;
-       }
-       if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG)
-       {
-           esrc->fes_entry_flags |= FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT;
-       }
-    }
-    if (fib_route_attached_cross_table(fib_entry, rpath) &&
-        !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_NO_ATTACHED_EXPORT))
-    {
-       esrc->fes_entry_flags |= FIB_ENTRY_FLAG_IMPORT;
-    }
-    else
+    const fib_route_path_t *rpath;
+
+    vec_foreach(rpath, rpaths)
     {
-       esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_IMPORT;
+        if ((esrc->fes_src == FIB_SOURCE_API) ||
+            (esrc->fes_src == FIB_SOURCE_CLI))
+        {
+            if (fib_path_is_attached(rpath))
+            {
+                esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED;
+            }
+            else
+            {
+                esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_ATTACHED;
+            }
+            if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG)
+            {
+                esrc->fes_entry_flags |= FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT;
+            }
+        }
+        if (fib_route_attached_cross_table(fib_entry, rpath) &&
+            !(esrc->fes_entry_flags & FIB_ENTRY_FLAG_NO_ATTACHED_EXPORT))
+        {
+            esrc->fes_entry_flags |= FIB_ENTRY_FLAG_IMPORT;
+        }
+        else
+        {
+            esrc->fes_entry_flags &= ~FIB_ENTRY_FLAG_IMPORT;
+        }
     }
 }
 
@@ -1533,24 +1570,19 @@ fib_entry_t*
 fib_entry_src_action_path_add (fib_entry_t *fib_entry,
                               fib_source_t source,
                               fib_entry_flag_t flags,
-                              const fib_route_path_t *rpath)
+                              const fib_route_path_t *rpaths)
 {
-    fib_node_index_t old_path_list, fib_entry_index;
+    fib_node_index_t old_path_list;
     fib_path_list_flags_t pl_flags;
     fib_entry_src_t *esrc;
 
-    /*
-     * save variable so we can recover from a fib_entry realloc.
-     */
-    fib_entry_index = fib_entry_get_index(fib_entry);
-
     esrc = fib_entry_src_find(fib_entry, source);
     if (NULL == esrc)
     {
        const dpo_id_t *dpo;
 
        if (flags == FIB_ENTRY_FLAG_EXCLUSIVE) {
-           dpo = &rpath->dpo;
+           dpo = &rpaths->dpo;
        } else {
            dpo = drop_dpo_get(fib_entry_get_dpo_proto(fib_entry));
        }
@@ -1574,11 +1606,10 @@ fib_entry_src_action_path_add (fib_entry_t *fib_entry,
     ASSERT(FIB_ENTRY_SRC_VFT_EXISTS(esrc, fesv_path_add));
 
     pl_flags = fib_entry_src_flags_2_path_list_flags(fib_entry_get_flags_i(fib_entry));
-    fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc);
+    fib_entry_flags_update(fib_entry, rpaths, &pl_flags, esrc);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_path_add,
-                             (esrc, fib_entry, pl_flags, rpath));
-    fib_entry = fib_entry_get(fib_entry_index);
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_path_add,
+                             (esrc, fib_entry, pl_flags, rpaths));
 
     fib_path_list_lock(esrc->fes_pl);
     fib_path_list_unlock(old_path_list);
@@ -1601,18 +1632,12 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
                                fib_entry_flag_t flags,
                                const fib_route_path_t *rpaths)
 {
-    fib_node_index_t old_path_list, fib_entry_index;
+    fib_node_index_t old_path_list;
     fib_path_list_flags_t pl_flags;
-    const fib_route_path_t *rpath;
     fib_entry_src_t *esrc;
 
     esrc = fib_entry_src_find(fib_entry, source);
 
-    /*
-     * save variable so we can recover from a fib_entry realloc.
-     */
-    fib_entry_index = fib_entry_get_index(fib_entry);
-
     if (NULL == esrc)
     {
        const dpo_id_t *dpo;
@@ -1633,7 +1658,7 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
     {
         if (flags != esrc->fes_entry_flags)
         {
-            FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_flags_change,
+            FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_flags_change,
                                      (esrc, fib_entry, flags));
         }
         esrc->fes_entry_flags = flags;
@@ -1650,17 +1675,12 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
 
     pl_flags = fib_entry_src_flags_2_path_list_flags(flags);
 
-    vec_foreach(rpath, rpaths)
-    {
-       fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc);
-    }
+    fib_entry_flags_update(fib_entry, rpaths, &pl_flags, esrc);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_path_swap,
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_path_swap,
                              (esrc, fib_entry,
                               pl_flags, rpaths));
 
-    fib_entry = fib_entry_get(fib_entry_index);
-
     fib_path_list_lock(esrc->fes_pl);
     fib_path_list_unlock(old_path_list);
 
@@ -1670,7 +1690,7 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry,
 fib_entry_src_flag_t
 fib_entry_src_action_path_remove (fib_entry_t *fib_entry,
                                  fib_source_t source,
-                                 const fib_route_path_t *rpath)
+                                 const fib_route_path_t *rpaths)
 {
     fib_path_list_flags_t pl_flags;
     fib_node_index_t old_path_list;
@@ -1692,10 +1712,10 @@ fib_entry_src_action_path_remove (fib_entry_t *fib_entry,
     ASSERT(FIB_ENTRY_SRC_VFT_EXISTS(esrc, fesv_path_remove));
 
     pl_flags = fib_entry_src_flags_2_path_list_flags(fib_entry_get_flags_i(fib_entry));
-    fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc);
+    fib_entry_flags_update(fib_entry, rpaths, &pl_flags, esrc);
 
-    FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_path_remove,
-                             (esrc, pl_flags, rpath));
+    FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_path_remove,
+                             (esrc, pl_flags, rpaths));
 
     /*
      * lock the new path-list, unlock the old if it had one
@@ -1825,27 +1845,22 @@ fib_entry_get_flags_for_source (fib_node_index_t entry_index,
     return (FIB_ENTRY_FLAG_NONE);
 }
 
+fib_source_t
+fib_entry_get_source_i (const fib_entry_t *fib_entry)
+{
+    /* the vector of sources is deliberately arranged in priority order */
+    if (0 == vec_len(fib_entry->fe_srcs))
+        return (FIB_SOURCE_INVALID);
+    return (vec_elt(fib_entry->fe_srcs, 0).fes_src);
+}
+
 fib_entry_flag_t
 fib_entry_get_flags_i (const fib_entry_t *fib_entry)
 {
-    fib_entry_flag_t flags;
-
-    /*
-     * the vector of sources is deliberately arranged in priority order
-     */
+    /* the vector of sources is deliberately arranged in priority order */
     if (0 == vec_len(fib_entry->fe_srcs))
-    {
-       flags = FIB_ENTRY_FLAG_NONE;
-    }
-    else
-    {
-       fib_entry_src_t *esrc;
-
-       esrc = vec_elt_at_index(fib_entry->fe_srcs, 0);
-       flags = esrc->fes_entry_flags;
-    }
-
-    return (flags);
+        return (FIB_ENTRY_FLAG_NONE);
+    return (vec_elt(fib_entry->fe_srcs, 0).fes_entry_flags);
 }
 
 void
@@ -1861,7 +1876,7 @@ fib_entry_set_source_data (fib_node_index_t fib_entry_index,
 
     if (NULL != esrc)
     {
-        FIB_ENTRY_SRC_VFT_INVOKE(esrc, fesv_set_data,
+        FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, esrc, fesv_set_data,
                                  (esrc, fib_entry, data));
     }
 }
@@ -1890,8 +1905,8 @@ fib_entry_src_module_init (void)
     fib_entry_src_rr_register();
     fib_entry_src_interface_register();
     fib_entry_src_interpose_register();
-    fib_entry_src_default_route_register();
-    fib_entry_src_special_register();
+    fib_entry_src_drop_register();
+    fib_entry_src_simple_register();
     fib_entry_src_api_register();
     fib_entry_src_adj_register();
     fib_entry_src_mpls_register();