fib: contention with DP on deleting a route
[vpp.git] / src / vnet / fib / fib_entry_src.c
index 1285734..c79b745 100644 (file)
@@ -46,6 +46,7 @@ fib_entry_src_get_vft (const fib_entry_src_t *esrc)
         return (&fib_entry_src_bh_vft[FIB_SOURCE_BH_INTERPOSE]);
     }
 
+    ASSERT(bh < FIB_SOURCE_BH_MAX);
     return (&fib_entry_src_bh_vft[bh]);
 }
 
@@ -257,6 +258,7 @@ typedef struct fib_entry_src_collect_forwarding_ctx_t_
     fib_forward_chain_type_t fct;
     int n_recursive_constrained;
     u16 preference;
+    dpo_proto_t payload_proto;
 } fib_entry_src_collect_forwarding_ctx_t;
 
 /**
@@ -289,47 +291,6 @@ fib_entry_src_valid_out_label (mpls_label_t label)
              MPLS_IETF_IMPLICIT_NULL_LABEL == label));
 }
 
-/**
- * @brief Turn the chain type requested by the client into the one they
- * really wanted
- */
-fib_forward_chain_type_t
-fib_entry_chain_type_fixup (const fib_entry_t *entry,
-                           fib_forward_chain_type_t fct)
-{
-    /*
-     * The EOS chain is a tricky since one cannot know the adjacency
-     * to link to without knowing what the packets payload protocol
-     * will be once the label is popped.
-     */
-    fib_forward_chain_type_t dfct;
-
-    if (FIB_FORW_CHAIN_TYPE_MPLS_EOS != fct)
-    {
-        return (fct);
-    }
-
-    dfct = fib_entry_get_default_chain_type(entry);
-
-    if (FIB_FORW_CHAIN_TYPE_MPLS_EOS == dfct)
-    {
-        /*
-         * If the entry being asked is a eos-MPLS label entry,
-         * then use the payload-protocol field, that we stashed there
-         * for just this purpose
-         */
-        return (fib_forw_chain_type_from_dpo_proto(
-                    entry->fe_prefix.fp_payload_proto));
-    }
-    /*
-     * else give them what this entry would be by default. i.e. if it's a v6
-     * entry, then the label its local labelled should be carrying v6 traffic.
-     * If it's a non-EOS label entry, then there are more labels and we want
-     * a non-eos chain.
-     */
-    return (dfct);
-}
-
 static dpo_proto_t
 fib_prefix_get_payload_proto (const fib_prefix_t *pfx)
 {
@@ -371,7 +332,8 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index,
 
         nh->path_index = path_index;
         nh->path_weight = fib_path_get_weight(path_index);
-        fib_path_contribute_forwarding(path_index, ctx->fct, &nh->path_dpo);
+        fib_path_contribute_forwarding(path_index, ctx->fct,
+                                       ctx->payload_proto, &nh->path_dpo);
 
         break;
     case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
@@ -384,6 +346,7 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index,
             nh->path_weight = fib_path_get_weight(path_index);
             fib_path_contribute_forwarding(path_index,
                                            FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS,
+                                           ctx->payload_proto,
                                            &nh->path_dpo);
         }
         break;
@@ -397,11 +360,11 @@ fib_entry_src_get_path_forwarding (fib_node_index_t path_index,
             nh->path_index = path_index;
             nh->path_weight = fib_path_get_weight(path_index);
             fib_path_contribute_forwarding(path_index,
-                                           fib_entry_chain_type_fixup(ctx->fib_entry,
-                                                                      ctx->fct),
+                                           ctx->fct,
+                                           ctx->payload_proto,
                                            &nh->path_dpo);
             fib_path_stack_mpls_disp(path_index,
-                                     fib_prefix_get_payload_proto(&ctx->fib_entry->fe_prefix),
+                                     ctx->payload_proto,
                                      FIB_MPLS_LSP_MODE_PIPE,
                                      &nh->path_dpo);
 
@@ -480,9 +443,8 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
                  */
                 ctx->next_hops =
                     fib_path_ext_stack(path_ext,
+                                       ctx->payload_proto,
                                        ctx->fct,
-                                       fib_entry_chain_type_fixup(ctx->fib_entry,
-                                                                  ctx->fct),
                                        ctx->next_hops);
             }
             else
@@ -609,6 +571,7 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry,
         .preference = 0xffff,
         .start_source_index = start,
         .end_source_index = end,
+        .payload_proto = fib_prefix_get_payload_proto(&fib_entry->fe_prefix),
     };
 
     /*
@@ -794,6 +757,7 @@ fib_entry_src_action_uninstall (fib_entry_t *fib_entry)
            &fib_entry->fe_prefix,
            &fib_entry->fe_lb);
 
+       vlib_worker_wait_one_loop();
        dpo_reset(&fib_entry->fe_lb);
     }
 }
@@ -1493,56 +1457,38 @@ fib_entry_src_action_remove (fib_entry_t *fib_entry,
  * Return true the the route is attached via an interface that
  * is not in the same table as the route
  */
-static inline int
+static int
 fib_route_attached_cross_table (const fib_entry_t *fib_entry,
                                const fib_route_path_t *rpath)
 {
-    /*
-     * - All zeros next-hop
-     * - a valid interface
-     * - entry's fib index not equeal to interface's index
-     */
-    if (ip46_address_is_zero(&rpath->frp_addr) &&
-       (~0 != rpath->frp_sw_if_index) &&
-        !(rpath->frp_flags & (FIB_ROUTE_PATH_DVR | FIB_ROUTE_PATH_UDP_ENCAP)) &&
-       (fib_entry->fe_fib_index != 
-        fib_table_get_index_for_sw_if_index(fib_entry_get_proto(fib_entry),
-                                            rpath->frp_sw_if_index)))
-    {
-       return (!0);
-    }
-    return (0);
-}
+    const fib_prefix_t *pfx = &fib_entry->fe_prefix;
 
-/*
- * Return true if the path is attached
- */
-static inline int
-fib_path_is_attached (const fib_route_path_t *rpath)
-{
-    /*
-     * DVR paths are not attached, since we are not playing the
-     * L3 game with these
-     */
-    if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
+    switch (pfx->fp_proto)
     {
-        return (0);
+    case FIB_PROTOCOL_MPLS:
+        /* MPLS routes are never imported/exported */
+       return (0);
+    case FIB_PROTOCOL_IP6:
+        /* Ignore link local addresses these also can't be imported/exported */
+        if (ip6_address_is_link_local_unicast (&pfx->fp_addr.ip6))
+        {
+            return (0);
+        }
+        break;
+    case FIB_PROTOCOL_IP4:
+        break;
     }
 
     /*
-     * - All zeros next-hop
-     * - a valid interface
+     * an attached path and entry's fib index not equal to interface's index
      */
-    if (ip46_address_is_zero(&rpath->frp_addr) &&
-       (~0 != rpath->frp_sw_if_index))
+    if (fib_route_path_is_attached(rpath) &&
+       fib_entry->fe_fib_index !=
+        fib_table_get_index_for_sw_if_index(fib_entry_get_proto(fib_entry),
+                                            rpath->frp_sw_if_index))
     {
        return (!0);
     }
-    else if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED ||
-             rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
-    {
-        return (!0);
-    }
     return (0);
 }
 
@@ -1580,7 +1526,7 @@ fib_entry_flags_update (const fib_entry_t *fib_entry,
         if ((esrc->fes_src == FIB_SOURCE_API) ||
             (esrc->fes_src == FIB_SOURCE_CLI))
         {
-            if (fib_path_is_attached(rpath))
+            if (fib_route_path_is_attached(rpath))
             {
                 esrc->fes_entry_flags |= FIB_ENTRY_FLAG_ATTACHED;
             }
@@ -1852,6 +1798,25 @@ fib_entry_get_dpo_for_source (fib_node_index_t fib_entry_index,
     return (0);
 }
 
+fib_node_index_t
+fib_entry_get_path_list_for_source (fib_node_index_t fib_entry_index,
+                                   fib_source_t source)
+{
+  fib_entry_t *fib_entry;
+  fib_entry_src_t *esrc;
+
+  if (FIB_NODE_INDEX_INVALID == fib_entry_index)
+    return FIB_NODE_INDEX_INVALID;
+
+  fib_entry = fib_entry_get(fib_entry_index);
+  esrc = fib_entry_src_find(fib_entry, source);
+
+  if (esrc)
+    return esrc->fes_pl;
+
+  return FIB_NODE_INDEX_INVALID;
+}
+
 u32
 fib_entry_get_resolving_interface_for_source (fib_node_index_t entry_index,
                                              fib_source_t source)