Support IETF routing Yang models (VPP-503).
[vpp.git] / vnet / vnet / fib / fib_path.c
index 03cc7be..e92e233 100644 (file)
 
 #include <vnet/adj/adj.h>
 
-#include "fib_path.h"
-#include "fib_node.h"
-#include "fib_table.h"
-#include "fib_entry.h"
-#include "fib_path_list.h"
-#include "fib_internal.h"
+#include <vnet/fib/fib_path.h>
+#include <vnet/fib/fib_node.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/fib_entry.h>
+#include <vnet/fib/fib_path_list.h>
+#include <vnet/fib/fib_internal.h>
+#include <vnet/fib/fib_urpf_list.h>
 
 /**
  * Enurmeration of path types
@@ -500,7 +501,7 @@ fib_path_last_lock_gone (fib_node_t *node)
 
 static const adj_index_t
 fib_path_attached_next_hop_get_adj (fib_path_t *path,
-                                   fib_link_t link)
+                                   vnet_link_t link)
 {
     if (vnet_sw_interface_is_p2p(vnet_get_main(),
                                 path->attached_next_hop.fp_interface))
@@ -562,7 +563,7 @@ fib_path_recursive_adj_update (fib_path_t *path,
                               fib_forward_chain_type_t fct,
                               dpo_id_t *dpo)
 {
-    dpo_id_t via_dpo = DPO_NULL;
+    dpo_id_t via_dpo = DPO_INVALID;
 
     /*
      * get the DPO to resolve through from the via-entry
@@ -756,6 +757,20 @@ fib_path_back_walk_notify (fib_node_t *node,
                fib_path_proto_to_chain_type(path->fp_nh_proto),
                &path->fp_dpo);
        }
+       if (FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason)
+       {
+           /*
+            * ADJ updates (complete<->incomplete) do not need to propagate to
+            * recursive entries.
+            * The only reason its needed as far back as here, is that the adj
+            * and the incomplete adj are a different DPO type, so the LBs need
+            * to re-stack.
+            * If this walk was quashed in the fib_entry, then any non-fib_path
+            * children (like tunnels that collapse out the LB when they stack)
+            * would not see the update.
+            */
+           return (FIB_NODE_BACK_WALK_CONTINUE);
+       }
        break;
     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
        /*
@@ -1551,6 +1566,62 @@ fib_path_get_weight (fib_node_index_t path_index)
     return (path->fp_weight);
 }
 
+/**
+ * @brief Contribute the path's adjacency to the list passed.
+ * By calling this function over all paths, recursively, a child
+ * can construct its full set of forwarding adjacencies, and hence its
+ * uRPF list.
+ */
+void
+fib_path_contribute_urpf (fib_node_index_t path_index,
+                         index_t urpf)
+{
+    fib_path_t *path;
+
+    if (!fib_path_is_resolved(path_index))
+       return;
+
+    path = fib_path_get(path_index);
+
+    switch (path->fp_type)
+    {
+    case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
+       fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
+       break;
+
+    case FIB_PATH_TYPE_ATTACHED:
+       fib_urpf_list_append(urpf, path->attached.fp_interface);
+       break;
+
+    case FIB_PATH_TYPE_RECURSIVE:
+       fib_entry_contribute_urpf(path->fp_via_fib, urpf);
+       break;
+
+    case FIB_PATH_TYPE_EXCLUSIVE:
+    case FIB_PATH_TYPE_SPECIAL:
+       /*
+        * these path types may link to an adj, if that's what
+        * the clinet gave
+        */
+       if (dpo_is_adj(&path->fp_dpo))
+       {
+           ip_adjacency_t *adj;
+
+           adj = adj_get(path->fp_dpo.dpoi_index);
+
+           fib_urpf_list_append(urpf, adj->rewrite_header.sw_if_index);
+       }
+       break;
+
+    case FIB_PATH_TYPE_DEAG:
+    case FIB_PATH_TYPE_RECEIVE:
+       /*
+        * these path types don't link to an adj
+        */
+       break;
+    }
+}
+
 void
 fib_path_contribute_forwarding (fib_node_index_t path_index,
                                fib_forward_chain_type_t fct,
@@ -1744,13 +1815,36 @@ show_fib_path_command (vlib_main_t * vm,
                        unformat_input_t * input,
                        vlib_cli_command_t * cmd)
 {
+    fib_node_index_t pi;
     fib_path_t *path;
 
-    vlib_cli_output (vm, "FIB Path Lists");
-    pool_foreach(path, fib_path_pool,
-    ({
-       vlib_cli_output (vm, "%U", format_fib_path, path);
-    }));
+    if (unformat (input, "%d", &pi))
+    {
+       /*
+        * show one in detail
+        */
+       if (!pool_is_free_index(fib_path_pool, pi))
+       {
+           path = fib_path_get(pi);
+           u8 *s = fib_path_format(pi, NULL);
+           s = format(s, "children:");
+           s = fib_node_children_format(path->fp_node.fn_children, s);
+           vlib_cli_output (vm, "%s", s);
+           vec_free(s);
+       }
+       else
+       {
+           vlib_cli_output (vm, "path %d invalid", pi);
+       }
+    }
+    else
+    {
+       vlib_cli_output (vm, "FIB Paths");
+       pool_foreach(path, fib_path_pool,
+       ({
+           vlib_cli_output (vm, "%U", format_fib_path, path);
+       }));
+    }
 
     return (NULL);
 }