ip: Protocol Independent IP Neighbors
[vpp.git] / src / vnet / adj / adj_nbr.c
index 3888509..f769c56 100644 (file)
@@ -18,6 +18,8 @@
 #include <vnet/ethernet/arp_packet.h>
 #include <vnet/fib/fib_walk.h>
 
+#include <vppinfra/bihash_24_8.h>
+
 /*
  * Vector Hash tables of neighbour (traditional) adjacencies
  *  Key: interface(for the vector index), address (and its proto),
@@ -219,12 +221,12 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto,
                     u32 sw_if_index)
 {
     adj_index_t adj_index;
-    ip_adjacency_t *adj;
 
     adj_index = adj_nbr_find(nh_proto, link_type, nh_addr, sw_if_index);
 
     if (ADJ_INDEX_INVALID == adj_index)
     {
+        ip_adjacency_t *adj;
        vnet_main_t *vnm;
 
        vnm = vnet_get_main();
@@ -254,6 +256,7 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto,
        adj_lock(adj_index);
     }
 
+    adj_delegate_adj_created(adj_get(adj_index));
     return (adj_index);
 }
 
@@ -282,6 +285,8 @@ adj_nbr_add_or_lock_w_rewrite (fib_protocol_t nh_proto,
                           ADJ_NBR_REWRITE_FLAG_COMPLETE,
                           rewrite);
 
+    adj_delegate_adj_created(adj_get(adj_index));
+
     return (adj_index);
 }
 
@@ -289,7 +294,7 @@ adj_nbr_add_or_lock_w_rewrite (fib_protocol_t nh_proto,
  * adj_nbr_update_rewrite
  *
  * Update the adjacency's rewrite string. A NULL string implies the
- * rewirte is reset (i.e. when ARP/ND etnry is gone).
+ * rewrite is reset (i.e. when ARP/ND entry is gone).
  * NB: the adj being updated may be handling traffic in the DP.
  */
 void
@@ -331,7 +336,7 @@ adj_nbr_update_rewrite (adj_index_t adj_index,
  * adj_nbr_update_rewrite_internal
  *
  * Update the adjacency's rewrite string. A NULL string implies the
- * rewirte is reset (i.e. when ARP/ND etnry is gone).
+ * rewrite is reset (i.e. when ARP/ND entry is gone).
  * NB: the adj being updated may be handling traffic in the DP.
  */
 void
@@ -355,7 +360,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
     {
         /*
          * The link type MPLS has no children in the control plane graph, it only
-         * has children in the data-palne graph. The backwalk is up the former.
+         * has children in the data-plane graph. The backwalk is up the former.
          * So we need to walk from its IP cousin.
          */
         walk_ai = adj_nbr_find(adj->ia_nh_proto,
@@ -392,7 +397,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
      * lock the adjacencies that are affected by updates this walk will provoke.
      * Since the aim of the walk is to update children to link to a different
      * DPO, this adj will no longer be in use and its lock count will drop to 0.
-     * We don't want it to be deleted as part of this endevour.
+     * We don't want it to be deleted as part of this endeavour.
      */
     adj_lock(adj_get_index(adj));
     adj_lock(walk_ai);
@@ -405,7 +410,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
      * ideally we would only want to suspend forwarding via this adj whilst we
      * do this, but we do not have that level of granularity - it's suspend all
      * worker threads or nothing.
-     * The other chioces are:
+     * The other choices are:
      *  - to mark the adj down and back walk so child load-balances drop this adj
      *    from the set.
      *  - update the next_node index of this adj to point to error-drop
@@ -416,7 +421,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
      * node. So from the options above, updating the next_node of the adj to
      * be drop will work, but it relies on each graph node v4/v6/mpls, rewrite/
      * arp/midchain always be valid w.r.t. a mis-match of adj type and node type
-     * (i.e. a rewrite adj in the arp node). This is not enforcable. Getting it
+     * (i.e. a rewrite adj in the arp node). This is not enforceable. Getting it
      * wrong will lead to hard to find bugs since its a race condition. So we
      * choose the more reliable method of updating the children to use the drop,
      * then switching adj's type, then updating the children again. Did I mention
@@ -438,7 +443,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
        fib_node_back_walk_ctx_t bw_ctx = {
            .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_DOWN,
             /*
-             * force this walk to be synchrous. if we don't and a node in the graph
+             * force this walk to be synchronous. if we don't and a node in the graph
              * (a heavily shared path-list) chooses to back-ground the walk (make it
              * async) then it will pause and we will do the adj update below, before
              * all the children are updated. not good.
@@ -459,6 +464,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
     vlib_worker_thread_barrier_sync(vm);
 
     adj->lookup_next_index = adj_next_index;
+    adj->ia_node_index = this_node;
 
     if (NULL != rewrite)
     {
@@ -482,7 +488,7 @@ adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
                                                         next_node);
 
     /*
-     * done with the rewirte update - let the workers loose.
+     * done with the rewrite update - let the workers loose.
      */
     vlib_worker_thread_barrier_release(vm);
 
@@ -516,12 +522,13 @@ typedef struct adj_db_count_ctx_t_ {
     u64 count;
 } adj_db_count_ctx_t;
 
-static void
+static int
 adj_db_count (BVT(clib_bihash_kv) * kvp,
              void *arg)
 {
     adj_db_count_ctx_t * ctx = arg;
     ctx->count++;
+    return (BIHASH_WALK_CONTINUE);
 }
 
 u32
@@ -558,14 +565,16 @@ typedef struct adj_walk_ctx_t_
     void *awc_ctx;
 } adj_walk_ctx_t;
 
-static void
+static int
 adj_nbr_walk_cb (BVT(clib_bihash_kv) * kvp,
                 void *arg)
 {
     adj_walk_ctx_t *ctx = arg;
 
     // FIXME: can't stop early...
-    ctx->awc_cb(kvp->value, ctx->awc_ctx);
+    if (ADJ_WALK_RC_STOP == ctx->awc_cb(kvp->value, ctx->awc_ctx))
+        return (BIHASH_WALK_STOP);
+    return (BIHASH_WALK_CONTINUE);
 }
 
 void
@@ -658,15 +667,17 @@ adj_nbr_walk_nh (u32 sw_if_index,
     if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
        return;
 
-    vnet_link_t linkt;
-    adj_index_t ai;
-
-    FOR_EACH_VNET_LINK(linkt)
+    switch (adj_nh_proto)
     {
-        ai = adj_nbr_find (FIB_PROTOCOL_IP4, linkt, nh, sw_if_index);
-
-        if (INDEX_INVALID != ai)
-            cb(ai, ctx);
+    case FIB_PROTOCOL_IP4:
+        adj_nbr_walk_nh4(sw_if_index, &nh->ip4, cb, ctx);
+        break; 
+    case FIB_PROTOCOL_IP6:
+        adj_nbr_walk_nh6(sw_if_index, &nh->ip6, cb, ctx);
+        break;
+    case FIB_PROTOCOL_MPLS:
+        ASSERT(0);
+        break;
     }
 }
 
@@ -821,12 +832,15 @@ adj_nbr_interface_delete_one (adj_index_t ai,
     };
     ip_adjacency_t *adj;
 
+    adj_lock(ai);
+
     adj = adj_get(ai);
 
     adj->ia_flags |= ADJ_FLAG_SYNC_WALK_ACTIVE;
     fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
     adj->ia_flags &= ~ADJ_FLAG_SYNC_WALK_ACTIVE;
 
+    adj_unlock(ai);
     return (ADJ_WALK_RC_CONTINUE);
 }