FIB path preference
[vpp.git] / src / vnet / fib / fib_entry.c
index dac1fce..d7ff1c8 100644 (file)
@@ -75,13 +75,7 @@ fib_entry_get_default_chain_type (const fib_entry_t *fib_entry)
        return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
     case FIB_PROTOCOL_MPLS:
        if (MPLS_EOS == fib_entry->fe_prefix.fp_eos)
-           /*
-            * 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(
-                       fib_entry->fe_prefix.fp_payload_proto));
+           return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
        else
            return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
     }
@@ -94,7 +88,6 @@ format_fib_entry (u8 * s, va_list * args)
 {
     fib_forward_chain_type_t fct;
     fib_entry_attribute_t attr;
-    fib_path_ext_t *path_ext;
     fib_entry_t *fib_entry;
     fib_entry_src_t *src;
     fib_node_index_t fei;
@@ -132,14 +125,7 @@ format_fib_entry (u8 * s, va_list * args)
            {
                s = fib_path_list_format(src->fes_pl, s);
            }
-           if (NULL != src->fes_path_exts)
-           {
-               s = format(s, "    Extensions:");
-               vec_foreach(path_ext, src->fes_path_exts)
-               {
-                   s = format(s, "\n     %U", format_fib_path_ext, path_ext);
-               }
-           }
+            s = format(s, "%U", format_fib_path_ext_list, &src->fes_path_exts);
        }));
     
        s = format (s, "\n forwarding: ");
@@ -334,7 +320,7 @@ fib_entry_show_memory (void)
        n_srcs += vec_len(entry->fe_srcs);
        vec_foreach(esrc, entry->fe_srcs)
        {
-           n_exts += vec_len(esrc->fes_path_exts);
+           n_exts += fib_path_ext_list_length(&esrc->fes_path_exts);
        }
     }));
 
@@ -370,6 +356,35 @@ fib_entry_contribute_urpf (fib_node_index_t entry_index,
     return (fib_path_list_contribute_urpf(fib_entry->fe_parent, urpf));
 }
 
+/*
+ * If the client is request a chain for multicast forwarding then swap
+ * the chain type to one that can provide such transport.
+ */
+static fib_forward_chain_type_t
+fib_entry_chain_type_mcast_to_ucast (fib_forward_chain_type_t fct)
+{
+    switch (fct)
+    {
+    case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
+    case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
+        /*
+         * we can only transport IP multicast packets if there is an
+         * LSP.
+         */
+        fct = FIB_FORW_CHAIN_TYPE_MPLS_EOS;
+        break;
+    case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
+    case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
+    case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
+    case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
+    case FIB_FORW_CHAIN_TYPE_ETHERNET:
+    case FIB_FORW_CHAIN_TYPE_NSH:
+        break;
+    }
+
+    return (fct);
+}
+
 /*
  * fib_entry_contribute_forwarding
  *
@@ -385,6 +400,11 @@ fib_entry_contribute_forwarding (fib_node_index_t fib_entry_index,
 
     fib_entry = fib_entry_get(fib_entry_index);
 
+    /*
+     * mfib children ask for mcast chains. fix these to the appropriate ucast types.
+     */
+    fct = fib_entry_chain_type_mcast_to_ucast(fct);
+
     if (fct == fib_entry_get_default_chain_type(fib_entry))
     {
         dpo_copy(dpo, &fib_entry->fe_lb);
@@ -414,6 +434,11 @@ fib_entry_contribute_forwarding (fib_node_index_t fib_entry_index,
 
         dpo_copy(dpo, &fed->fd_dpo);
     }
+    /*
+     * don't allow the special index indicating replicate.vs.load-balance
+     * to escape to the clients
+     */
+    dpo->dpoi_index &= ~MPLS_IS_REPLICATE;
 }
 
 const dpo_id_t *
@@ -437,11 +462,15 @@ fib_entry_get_adj (fib_node_index_t fib_entry_index)
     const dpo_id_t *dpo;
 
     dpo = fib_entry_contribute_ip_forwarding(fib_entry_index);
-    dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
 
-    if (dpo_is_adj(dpo))
+    if (dpo_id_is_valid(dpo))
     {
-       return (dpo->dpoi_index);
+        dpo = load_balance_get_bucket(dpo->dpoi_index, 0);
+
+        if (dpo_is_adj(dpo))
+        {
+            return (dpo->dpoi_index);
+        }
     }
     return (ADJ_INDEX_INVALID);
 }
@@ -1344,7 +1373,7 @@ fib_entry_is_resolved (fib_node_index_t fib_entry_index)
     if (NULL == fed)
     {
         /*
-         * no BFD tracking - resolved
+         * no BFD tracking - consider it resolved.
          */
         return (!0);
     }
@@ -1357,6 +1386,35 @@ fib_entry_is_resolved (fib_node_index_t fib_entry_index)
     }
 }
 
+void
+fib_entry_set_flow_hash_config (fib_node_index_t fib_entry_index,
+                                flow_hash_config_t hash_config)
+{
+    fib_entry_t *fib_entry;
+
+    fib_entry = fib_entry_get(fib_entry_index);
+
+    /*
+     * pass the hash-config on to the load-balance object where it is cached.
+     * we can ignore LBs in the delegate chains, since they will not be of the
+     * correct protocol type (i.e. they are not IP)
+     * There's no way, nor need, to change the hash config for MPLS.
+     */
+    if (dpo_id_is_valid(&fib_entry->fe_lb))
+    {
+        load_balance_t *lb;
+
+        ASSERT(DPO_LOAD_BALANCE == fib_entry->fe_lb.dpoi_type);
+
+        lb = load_balance_get(fib_entry->fe_lb.dpoi_index);
+
+        /*
+         * atomic update for packets in flight
+         */
+        lb->lb_hash_config = hash_config;
+    }
+}
+
 static int
 fib_ip4_address_compare (const ip4_address_t * a1,
                          const ip4_address_t * a2)