FIB table add/delete API 71/8371/2
authorNeale Ranns <nranns@cisco.com>
Sun, 10 Sep 2017 11:39:11 +0000 (04:39 -0700)
committerDamjan Marion <dmarion.lists@gmail.com>
Mon, 11 Sep 2017 10:14:36 +0000 (10:14 +0000)
part 2;
  - this adds the code to create an IP and MPLS table via the API.
  - but the enforcement that the table must be created before it is used is still missing, this is so that CSIT can pass.

Change-Id: Id124d884ade6cb7da947225200e3bb193454c555
Signed-off-by: Neale Ranns <nranns@cisco.com>
65 files changed:
src/plugins/nat/nat.c
src/plugins/nat/nat64.c
src/vnet/classify/vnet_classify.c
src/vnet/dhcp/dhcp4_proxy_node.c
src/vnet/dhcp/dhcp6_proxy_node.c
src/vnet/dhcp/dhcp_proxy.c
src/vnet/dpo/lookup_dpo.c
src/vnet/dpo/mpls_label_dpo.c
src/vnet/ethernet/arp.c
src/vnet/fib/fib_api.h
src/vnet/fib/fib_entry.c
src/vnet/fib/fib_entry.h
src/vnet/fib/fib_entry_src_mpls.c
src/vnet/fib/fib_table.c
src/vnet/fib/fib_table.h
src/vnet/fib/fib_test.c
src/vnet/fib/ip4_fib.c
src/vnet/fib/ip4_fib.h
src/vnet/fib/ip6_fib.c
src/vnet/fib/ip6_fib.h
src/vnet/fib/mpls_fib.c
src/vnet/fib/mpls_fib.h
src/vnet/interface_api.c
src/vnet/ip/ip.h
src/vnet/ip/ip4.h
src/vnet/ip/ip4_forward.c
src/vnet/ip/ip4_source_and_port_range_check.c
src/vnet/ip/ip6.h
src/vnet/ip/ip6_forward.c
src/vnet/ip/ip6_neighbor.c
src/vnet/ip/ip_api.c
src/vnet/ip/lookup.c
src/vnet/lisp-gpe/interface.c
src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
src/vnet/lisp-gpe/lisp_gpe_sub_interface.c
src/vnet/mfib/ip4_mfib.c
src/vnet/mfib/ip4_mfib.h
src/vnet/mfib/ip6_mfib.c
src/vnet/mfib/ip6_mfib.h
src/vnet/mfib/mfib_entry.c
src/vnet/mfib/mfib_entry.h
src/vnet/mfib/mfib_table.c
src/vnet/mfib/mfib_table.h
src/vnet/mfib/mfib_test.c
src/vnet/mfib/mfib_types.h
src/vnet/mpls/interface.c
src/vnet/mpls/mpls.c
src/vnet/mpls/mpls.h
src/vnet/mpls/mpls_api.c
src/vnet/srv6/sr_policy_rewrite.c
src/vnet/srv6/sr_steering.c
src/vpp/api/api.c
src/vpp/api/custom_dump.c
test/test_dhcp.py
test/test_gre.py
test/test_ip4.py
test/test_ip4_vrf_multi_instance.py
test/test_ip6.py
test/test_ip6_vrf_multi_instance.py
test/test_ip_mcast.py
test/test_mpls.py
test/test_nat.py
test/test_neighbor.py
test/vpp_ip_route.py
test/vpp_papi_provider.py

index aa7ef10..8aecac6 100644 (file)
@@ -167,7 +167,8 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr, u32 vrf_id)
   ap->addr = *addr;
   if (vrf_id != ~0)
     ap->fib_index =
-      fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+      fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+                                         FIB_SOURCE_PLUGIN_HI);
   else
     ap->fib_index = ~0;
 #define _(N, i, n, s) \
@@ -625,7 +626,8 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
         return VNET_API_ERROR_INVALID_VALUE;
 
       fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                     vrf_id);
+                                                     vrf_id,
+                                                     FIB_SOURCE_PLUGIN_HI);
 
       /* Find external address in allocated addresses and reserve port for
          address and port pair mapping when dynamic translations enabled */
@@ -754,7 +756,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
       if (!m)
         return VNET_API_ERROR_NO_SUCH_ENTRY;
 
-      fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4);
+      fib_table_unlock (m->fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_PLUGIN_HI);
 
       /* Free external address port */
       if (!sm->static_mapping_only)
@@ -874,7 +876,8 @@ int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
     }
 
   if (a->fib_index != ~0)
-    fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4);
+    fib_table_unlock(a->fib_index, FIB_PROTOCOL_IP4,
+                     FIB_SOURCE_PLUGIN_HI);
 
   /* Delete sessions using address */
   if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
@@ -2151,10 +2154,12 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
   sm->max_translations_per_user = max_translations_per_user;
   sm->outside_vrf_id = outside_vrf_id;
   sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                             outside_vrf_id);
+                                                             outside_vrf_id,
+                                                             FIB_SOURCE_PLUGIN_HI);
   sm->inside_vrf_id = inside_vrf_id;
   sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                            inside_vrf_id);
+                                                            inside_vrf_id,
+                                                            FIB_SOURCE_PLUGIN_HI);
   sm->static_mapping_only = static_mapping_only;
   sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
 
index b04901f..bfcfa9b 100644 (file)
@@ -107,7 +107,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add)
       a->fib_index = 0;
       if (vrf_id != ~0)
        a->fib_index =
-         fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+         fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+                                            FIB_SOURCE_PLUGIN_HI);
 #define _(N, i, n, s) \
       clib_bitmap_alloc (a->busy_##n##_port_bitmap, 65535);
       foreach_snat_protocol
@@ -119,7 +120,8 @@ nat64_add_del_pool_addr (ip4_address_t * addr, u32 vrf_id, u8 is_add)
        return VNET_API_ERROR_NO_SUCH_ENTRY;
 
       if (a->fib_index)
-       fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6);
+       fib_table_unlock (a->fib_index, FIB_PROTOCOL_IP6,
+                         FIB_SOURCE_PLUGIN_HI);
 
 #define _(N, id, n, s) \
       clib_bitmap_free (a->busy_##n##_port_bitmap);
@@ -353,8 +355,8 @@ nat64_add_del_static_bib_entry (ip6_address_t * in_addr,
 {
   nat64_main_t *nm = &nat64_main;
   nat64_db_bib_entry_t *bibe;
-  u32 fib_index =
-    fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+  u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+                                                    FIB_SOURCE_PLUGIN_HI);
   snat_protocol_t p = ip_proto_to_snat_proto (proto);
   ip46_address_t addr;
   int i;
@@ -644,7 +646,8 @@ nat64_add_del_prefix (ip6_address_t * prefix, u8 plen, u32 vrf_id, u8 is_add)
        {
          vec_add2 (nm->pref64, p, 1);
          p->fib_index =
-           fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id);
+           fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
+                                              FIB_SOURCE_PLUGIN_HI);
          p->vrf_id = vrf_id;
        }
 
index 879fba3..57d8674 100644 (file)
@@ -368,10 +368,10 @@ vnet_classify_entry_claim_resource (vnet_classify_entry_t *e)
     switch (e->action)
     {
     case CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
-        fib_table_lock (e->metadata, FIB_PROTOCOL_IP4);
+        fib_table_lock (e->metadata, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
         break;
     case CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
-        fib_table_lock (e->metadata, FIB_PROTOCOL_IP6);
+        fib_table_lock (e->metadata, FIB_PROTOCOL_IP6, FIB_SOURCE_CLASSIFY);
         break;
     }
 }
@@ -382,10 +382,10 @@ vnet_classify_entry_release_resource (vnet_classify_entry_t *e)
     switch (e->action)
     {
     case CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
-        fib_table_unlock (e->metadata, FIB_PROTOCOL_IP4);
+        fib_table_unlock (e->metadata, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
         break;
     case CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
-        fib_table_unlock (e->metadata, FIB_PROTOCOL_IP6);
+        fib_table_unlock (e->metadata, FIB_PROTOCOL_IP6, FIB_SOURCE_CLASSIFY);
         break;
     }
 }
@@ -2096,9 +2096,13 @@ int vnet_classify_add_del_session (vnet_classify_main_t * cm,
   e->flags = 0;
   e->action = action;
   if (e->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX)
-    e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, metadata);
+    e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+                                                     metadata,
+                                                     FIB_SOURCE_CLASSIFY);
   else if (e->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
-    e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, metadata);
+    e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
+                                                     metadata,
+                                                     FIB_SOURCE_CLASSIFY);
   else
     e->metadata = 0;
 
index 1b59cde..339a788 100644 (file)
@@ -785,7 +785,8 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
     return VNET_API_ERROR_INVALID_SRC_ADDRESS;
 
   rx_fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
-                                                   rx_table_id);
+                                                   rx_table_id,
+                                                   FIB_SOURCE_DHCP);
 
   if (is_del)
     {
@@ -795,7 +796,7 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
           fib_table_entry_special_remove(rx_fib_index,
                                          &all_1s,
                                          FIB_SOURCE_DHCP);
-          fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
+          fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
       }
     }
   else
@@ -808,10 +809,10 @@ dhcp4_proxy_set_server (ip46_address_t *addr,
                                       &all_1s,
                                       FIB_SOURCE_DHCP,
                                       FIB_ENTRY_FLAG_LOCAL);
-          fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4);
+          fib_table_lock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
       }
   }
-  fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4);
+  fib_table_unlock (rx_fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_DHCP);
 
   return (rc);
 }
index 9c2f522..ce7a8fc 100644 (file)
@@ -841,7 +841,8 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
     return VNET_API_ERROR_INVALID_SRC_ADDRESS;
 
   rx_fib_index = mfib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6,
-                                                    rx_table_id);
+                                                    rx_table_id,
+                                                    MFIB_SOURCE_DHCP);
 
   if (is_del)
     {
@@ -851,7 +852,7 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
           mfib_table_entry_delete(rx_fib_index,
                                   &all_dhcp_servers,
                                   MFIB_SOURCE_DHCP);
-          mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
+          mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
       }
     }
   else
@@ -885,11 +886,11 @@ dhcp6_proxy_set_server (ip46_address_t *addr,
                                  MFIB_SOURCE_DHCP,
                                  MFIB_RPF_ID_NONE,
                                  MFIB_ENTRY_FLAG_ACCEPT_ALL_ITF);
-         mfib_table_lock(rx_fib_index, FIB_PROTOCOL_IP6);
+         mfib_table_lock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
      }
     }
 
-  mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6);
+  mfib_table_unlock(rx_fib_index, FIB_PROTOCOL_IP6, MFIB_SOURCE_DHCP);
 
   return (rc);
 }
index ba7f354..1784906 100644 (file)
@@ -29,9 +29,9 @@ dhcp_proxy_rx_table_lock (fib_protocol_t proto,
                           u32 fib_index)
 {
     if (FIB_PROTOCOL_IP4 == proto)
-        fib_table_lock(fib_index, proto);
+        fib_table_lock(fib_index, proto, FIB_SOURCE_DHCP);
     else
-        mfib_table_lock(fib_index, proto);
+        mfib_table_lock(fib_index, proto, MFIB_SOURCE_DHCP);
 }
 
 static void
@@ -39,9 +39,9 @@ dhcp_proxy_rx_table_unlock (fib_protocol_t proto,
                             u32 fib_index)
 {
     if (FIB_PROTOCOL_IP4 == proto)
-        fib_table_unlock(fib_index, proto);
+        fib_table_unlock(fib_index, proto, FIB_SOURCE_DHCP);
     else
-        mfib_table_unlock(fib_index, proto);
+        mfib_table_unlock(fib_index, proto, MFIB_SOURCE_DHCP);
 }
 
  u32
@@ -169,7 +169,7 @@ dhcp_proxy_server_del (fib_protocol_t proto,
       if (~0 != index)
       {
           server = &proxy->dhcp_servers[index];
-          fib_table_unlock (server->server_fib_index, proto);
+          fib_table_unlock (server->server_fib_index, proto, FIB_SOURCE_DHCP);
 
           vec_del1(proxy->dhcp_servers, index);
 
@@ -228,7 +228,8 @@ dhcp_proxy_server_add (fib_protocol_t proto,
   dhcp_server_t server = {
       .dhcp_server = *addr,
       .server_fib_index = fib_table_find_or_create_and_lock(proto,
-                                                            server_table_id),
+                                                            server_table_id,
+                                                            FIB_SOURCE_DHCP),
   };
 
   vec_add1(proxy->dhcp_servers, server);
@@ -297,9 +298,11 @@ int dhcp_proxy_set_vss (fib_protocol_t proto,
   int rc = 0;
   
   if (proto == FIB_PROTOCOL_IP4)
-      rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id);
+      rx_fib_index = fib_table_find_or_create_and_lock(proto, tbl_id,
+                                                       FIB_SOURCE_DHCP);
   else
-      rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id);
+      rx_fib_index = mfib_table_find_or_create_and_lock(proto, tbl_id,
+                                                        MFIB_SOURCE_DHCP);
   v = dhcp_get_vss_info(dm, rx_fib_index, proto);
 
   if (NULL != v)
index 26363a2..af189ed 100644 (file)
@@ -135,11 +135,15 @@ lookup_dpo_add_or_lock_w_fib_index (fib_node_index_t fib_index,
     {
         if (LOOKUP_UNICAST == cast)
         {
-            fib_table_lock(fib_index, dpo_proto_to_fib(proto));
+            fib_table_lock(fib_index,
+                           dpo_proto_to_fib(proto),
+                           FIB_SOURCE_RR);
         }
         else
         {
-            mfib_table_lock(fib_index, dpo_proto_to_fib(proto));
+            mfib_table_lock(fib_index,
+                            dpo_proto_to_fib(proto),
+                            MFIB_SOURCE_RR);
         }
     }
     lookup_dpo_add_or_lock_i(fib_index, proto, cast, input, table_config, dpo);
@@ -161,13 +165,15 @@ lookup_dpo_add_or_lock_w_table_id (u32 table_id,
         {
             fib_index =
                 fib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
-                                                  table_id);
+                                                  table_id,
+                                                  FIB_SOURCE_RR);
         }
         else
         {
             fib_index =
                 mfib_table_find_or_create_and_lock(dpo_proto_to_fib(proto),
-                                                   table_id);
+                                                   table_id,
+                                                   MFIB_SOURCE_RR);
         }
     }
 
@@ -238,12 +244,14 @@ lookup_dpo_unlock (dpo_id_t *dpo)
             if (LOOKUP_UNICAST == lkd->lkd_cast)
             {
                 fib_table_unlock(lkd->lkd_fib_index,
-                                 dpo_proto_to_fib(lkd->lkd_proto));
+                                 dpo_proto_to_fib(lkd->lkd_proto),
+                                 FIB_SOURCE_RR);
             }
             else
             {
                 mfib_table_unlock(lkd->lkd_fib_index,
-                                  dpo_proto_to_fib(lkd->lkd_proto));
+                                  dpo_proto_to_fib(lkd->lkd_proto),
+                                  MFIB_SOURCE_RR);
             }
         }
         pool_put(lookup_dpo_pool, lkd);
index b178a90..2a6e7dd 100644 (file)
@@ -105,10 +105,18 @@ format_mpls_label_dpo (u8 *s, va_list *args)
     mpls_label_dpo_t *mld;
     u32 ii;
 
-    mld = mpls_label_dpo_get(index);
-
     s = format(s, "mpls-label:[%d]:", index);
 
+    if (pool_is_free_index(mpls_label_dpo_pool, index))
+    {
+        /*
+         * the packet trace can be printed after the DPO has been deleted
+         */
+        return (s);
+    }
+
+    mld = mpls_label_dpo_get(index);
+
     for (ii = 0; ii < mld->mld_n_labels; ii++)
     {
        hdr.label_exp_s_ttl =
index c84ff47..08e9137 100644 (file)
@@ -522,6 +522,24 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
     }
 }
 
+static void
+arp_adj_fib_add (ethernet_arp_ip4_entry_t * e, uint32_t fib_index)
+{
+  fib_prefix_t pfx = {
+    .fp_len = 32,
+    .fp_proto = FIB_PROTOCOL_IP4,
+    .fp_addr.ip4 = e->ip4_address,
+  };
+
+  e->fib_entry_index =
+    fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             DPO_PROTO_IP4, &pfx.fp_addr,
+                             e->sw_if_index, ~0, 1, NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
+  fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
+}
+
 int
 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
                                         vnet_arp_set_ip4_over_ethernet_rpc_args_t
@@ -576,21 +594,9 @@ vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
 
       if (!is_no_fib_entry)
        {
-         fib_prefix_t pfx = {
-           .fp_len = 32,
-           .fp_proto = FIB_PROTOCOL_IP4,
-           .fp_addr.ip4 = a->ip4,
-         };
-         u32 fib_index;
-
-         fib_index =
-           ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
-         e->fib_entry_index =
-           fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
-                                     FIB_ENTRY_FLAG_ATTACHED,
-                                     DPO_PROTO_IP4, &pfx.fp_addr,
-                                     e->sw_if_index, ~0, 1, NULL,
-                                     FIB_ROUTE_PATH_FLAG_NONE);
+         arp_adj_fib_add (e,
+                          ip4_fib_table_get_index_for_sw_if_index
+                          (e->sw_if_index));
        }
       else
        {
@@ -1561,6 +1567,65 @@ arp_add_del_interface_address (ip4_main_t * im,
     }
 }
 
+void
+arp_adj_fib_remove (ethernet_arp_ip4_entry_t * e, uint32_t fib_index)
+{
+  if (FIB_NODE_INDEX_INVALID != e->fib_entry_index)
+    {
+      fib_prefix_t pfx = {
+       .fp_len = 32,
+       .fp_proto = FIB_PROTOCOL_IP4,
+       .fp_addr.ip4 = e->ip4_address,
+      };
+      u32 fib_index;
+
+      fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
+
+      fib_table_entry_path_remove (fib_index, &pfx,
+                                  FIB_SOURCE_ADJ,
+                                  DPO_PROTO_IP4,
+                                  &pfx.fp_addr,
+                                  e->sw_if_index, ~0, 1,
+                                  FIB_ROUTE_PATH_FLAG_NONE);
+      fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
+    }
+}
+
+static void
+arp_table_bind (ip4_main_t * im,
+               uword opaque,
+               u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
+{
+  ethernet_arp_main_t *am = &ethernet_arp_main;
+  ethernet_arp_interface_t *eai;
+  ethernet_arp_ip4_entry_t *e;
+  hash_pair_t *pair;
+
+  /*
+   * the IP table that the interface is bound to has changed.
+   * reinstall all the adj fibs.
+   */
+
+  if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
+    return;
+
+  eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
+
+  /* *INDENT-OFF* */
+  hash_foreach_pair (pair, eai->arp_entries,
+  ({
+    e = pool_elt_at_index(am->ip4_entry_pool,
+                          pair->value[0]);
+    /*
+     * remove the adj-fib from the old table and add to the new
+     */
+    arp_adj_fib_remove(e, old_fib_index);
+    arp_adj_fib_add(e, new_fib_index);
+  }));
+  /* *INDENT-ON* */
+
+}
+
 static clib_error_t *
 ethernet_arp_init (vlib_main_t * vm)
 {
@@ -1606,6 +1671,11 @@ ethernet_arp_init (vlib_main_t * vm)
   cb.function_opaque = 0;
   vec_add1 (im->add_del_interface_address_callbacks, cb);
 
+  ip4_table_bind_callback_t cbt;
+  cbt.function = arp_table_bind;
+  cbt.function_opaque = 0;
+  vec_add1 (im->table_bind_callbacks, cbt);
+
   return 0;
 }
 
@@ -1616,24 +1686,9 @@ arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
 {
   ethernet_arp_main_t *am = &ethernet_arp_main;
 
-  if (FIB_NODE_INDEX_INVALID != e->fib_entry_index)
-    {
-      fib_prefix_t pfx = {
-       .fp_len = 32,
-       .fp_proto = FIB_PROTOCOL_IP4,
-       .fp_addr.ip4 = e->ip4_address,
-      };
-      u32 fib_index;
-
-      fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
-
-      fib_table_entry_path_remove (fib_index, &pfx,
-                                  FIB_SOURCE_ADJ,
-                                  DPO_PROTO_IP4,
-                                  &pfx.fp_addr,
-                                  e->sw_if_index, ~0, 1,
-                                  FIB_ROUTE_PATH_FLAG_NONE);
-    }
+  arp_adj_fib_remove (e,
+                     ip4_fib_table_get_index_for_sw_if_index
+                     (e->sw_if_index));
   hash_unset (eai->arp_entries, e->ip4_address.as_u32);
   pool_put (am->ip4_entry_pool, e);
 }
@@ -1693,7 +1748,11 @@ vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
        * does in response to interface events. unset is only done
        * by the control plane.
        */
-      if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
+      if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
+       {
+         e->flags &= ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC;
+       }
+      else if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
        {
          arp_entry_free (eai, e);
        }
index d07d6ca..f5a107c 100644 (file)
@@ -23,7 +23,6 @@ add_del_route_check (fib_protocol_t table_proto,
                     u32 next_hop_sw_if_index,
                     dpo_proto_t next_hop_table_proto,
                     u32 next_hop_table_id,
-                    u8 create_missing_tables,
                      u8 is_rpf_id,
                     u32 * fib_index, u32 * next_hop_fib_index);
 
index 2027f2b..4cb6cf6 100644 (file)
@@ -89,6 +89,17 @@ fib_entry_get_default_chain_type (const fib_entry_t *fib_entry)
     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
 }
 
+u8 *
+format_fib_source (u8 * s, va_list * args)
+{
+    fib_source_t source = va_arg (*args, int);
+
+    s = format (s, "\n  src:%s ",
+                fib_source_names[source]);
+
+    return (s);
+}
+
 u8 *
 format_fib_entry (u8 * s, va_list * args)
 {
@@ -114,8 +125,8 @@ format_fib_entry (u8 * s, va_list * args)
 
        FOR_EACH_SRC_ADDED(fib_entry, src, source,
         ({
-           s = format (s, "\n  src:%s ",
-                       fib_source_names[source]);
+           s = format (s, "\n  src:%U ",
+                       format_fib_source, source);
            s = fib_entry_src_format(fib_entry, source, s);
            s = format (s, " refs:%d ", src->fes_ref_count);
            if (FIB_ENTRY_FLAG_NONE != src->fes_entry_flags) {
index 93b8016..2f6e37f 100644 (file)
@@ -431,6 +431,7 @@ typedef struct fib_entry_t_ {
 #define FIB_ENTRY_FORMAT_DETAIL2 (0x2)
 
 extern u8 *format_fib_entry (u8 * s, va_list * args);
+extern u8 *format_fib_source (u8 * s, va_list * args);
 
 extern fib_node_index_t fib_entry_create_special(u32 fib_index,
                                                 const fib_prefix_t *prefix,
index a616458..6fdd5c0 100644 (file)
@@ -94,7 +94,9 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
            fib_table_entry_delete_index(src->mpls.fesm_lfes[eos],
                                         FIB_SOURCE_SPECIAL);
         }
-        fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID, FIB_PROTOCOL_MPLS);
+        fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID,
+                         FIB_PROTOCOL_MPLS,
+                         FIB_SOURCE_MPLS);
         src->mpls.fesm_label = label;
     }
     else
@@ -113,7 +115,8 @@ fib_entry_src_mpls_set_data (fib_entry_src_t *src,
         {
             fib_index =
                fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
-                                                 MPLS_FIB_DEFAULT_TABLE_ID);
+                                                 MPLS_FIB_DEFAULT_TABLE_ID,
+                                                  FIB_SOURCE_MPLS);
         }
        else
        {
index 6b6cc5c..75d1562 100644 (file)
@@ -1039,7 +1039,8 @@ fib_table_find (fib_protocol_t proto,
 
 u32
 fib_table_find_or_create_and_lock (fib_protocol_t proto,
-                                  u32 table_id)
+                                  u32 table_id,
+                                   fib_source_t src)
 {
     fib_table_t *fib_table;
     fib_node_index_t fi;
@@ -1047,13 +1048,13 @@ fib_table_find_or_create_and_lock (fib_protocol_t proto,
     switch (proto)
     {
     case FIB_PROTOCOL_IP4:
-       fi = ip4_fib_table_find_or_create_and_lock(table_id);
+       fi = ip4_fib_table_find_or_create_and_lock(table_id, src);
         break;
     case FIB_PROTOCOL_IP6:
-       fi = ip6_fib_table_find_or_create_and_lock(table_id);
+       fi = ip6_fib_table_find_or_create_and_lock(table_id, src);
         break;
     case FIB_PROTOCOL_MPLS:
-       fi = mpls_fib_table_find_or_create_and_lock(table_id);
+       fi = mpls_fib_table_find_or_create_and_lock(table_id, src);
         break;
     default:
         return (~0);        
@@ -1070,6 +1071,7 @@ fib_table_find_or_create_and_lock (fib_protocol_t proto,
 
 u32
 fib_table_create_and_lock (fib_protocol_t proto,
+                           fib_source_t src,
                            const char *const fmt,
                            ...)
 {
@@ -1082,13 +1084,13 @@ fib_table_create_and_lock (fib_protocol_t proto,
     switch (proto)
     {
     case FIB_PROTOCOL_IP4:
-       fi = ip4_fib_table_create_and_lock();
+       fi = ip4_fib_table_create_and_lock(src);
         break;
     case FIB_PROTOCOL_IP6:
-       fi = ip6_fib_table_create_and_lock();
+       fi = ip6_fib_table_create_and_lock(src);
         break;
      case FIB_PROTOCOL_MPLS:
-       fi = mpls_fib_table_create_and_lock();
+       fi = mpls_fib_table_create_and_lock(src);
         break;
    default:
         return (~0);        
@@ -1143,26 +1145,43 @@ fib_table_walk (u32 fib_index,
 
 void
 fib_table_unlock (u32 fib_index,
-                 fib_protocol_t proto)
+                 fib_protocol_t proto,
+                  fib_source_t source)
 {
     fib_table_t *fib_table;
 
     fib_table = fib_table_get(fib_index, proto);
-    fib_table->ft_locks--;
+    fib_table->ft_locks[source]--;
+    fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]--;
 
-    if (0 == fib_table->ft_locks)
+    if (0 == fib_table->ft_locks[source])
     {
+        /*
+         * The source no longer needs the table. flush any routes
+         * from it just in case
+         */
+        fib_table_flush(fib_index, proto, source);
+    }
+
+    if (0 == fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS])
+    {
+        /*
+         * no more locak from any source - kill it
+         */
        fib_table_destroy(fib_table);
     }
 }
+
 void
 fib_table_lock (u32 fib_index,
-               fib_protocol_t proto)
+               fib_protocol_t proto,
+                fib_source_t source)
 {
     fib_table_t *fib_table;
 
     fib_table = fib_table_get(fib_index, proto);
-    fib_table->ft_locks++;
+    fib_table->ft_locks[source]++;
+    fib_table->ft_locks[FIB_TABLE_TOTAL_LOCKS]++;
 }
 
 u32
index 579740e..6b7011b 100644 (file)
 #include <vnet/mpls/mpls.h>
 #include <vnet/mpls/packet.h>
 
+/**
+ * Keep a lock per-source and a total
+ */
+#define FIB_TABLE_N_LOCKS (FIB_SOURCE_MAX+1)
+#define FIB_TABLE_TOTAL_LOCKS FIB_SOURCE_MAX
+
 /**
  * @brief 
  *   A protocol Independent FIB table
@@ -34,9 +40,9 @@ typedef struct fib_table_t_
     fib_protocol_t ft_proto;
 
     /**
-     * number of locks on the table
+     * per-source number of locks on the table
      */
-    u16 ft_locks;
+    u16 ft_locks[FIB_TABLE_N_LOCKS];
 
     /**
      * Table ID (hash key) for this FIB.
@@ -628,9 +634,13 @@ extern u32 fib_table_find(fib_protocol_t proto, u32 table_id);
  *
  * @return fib_index
  *  The index of the FIB
+ *
+ * @param source
+ *  The ID of the client/source.
  */
 extern u32 fib_table_find_or_create_and_lock(fib_protocol_t proto,
-                                            u32 table_id);
+                                            u32 table_id,
+                                             fib_source_t source);
 
 /**
  * @brief
@@ -643,10 +653,14 @@ extern u32 fib_table_find_or_create_and_lock(fib_protocol_t proto,
  * @param fmt
  *  A string to describe the table
  *
+ * @param source
+ *  The ID of the client/source.
+ *
  * @return fib_index
  *  The index of the FIB
  */
 extern u32 fib_table_create_and_lock(fib_protocol_t proto,
+                                     fib_source_t source,
                                      const char *const fmt,
                                      ...);
 
@@ -704,9 +718,13 @@ extern void fib_table_set_flow_hash_config(u32 fib_index,
  *
  * @paran proto
  *  The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ *  The ID of the client/source.
  */ 
 extern void fib_table_unlock(u32 fib_index,
-                            fib_protocol_t proto);
+                            fib_protocol_t proto,
+                             fib_source_t source);
 
 /**
  * @brief
@@ -718,9 +736,13 @@ extern void fib_table_unlock(u32 fib_index,
  *
  * @paran proto
  *  The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ *  The ID of the client/source.
  */ 
 extern void fib_table_lock(u32 fib_index,
-                          fib_protocol_t proto);
+                          fib_protocol_t proto,
+                           fib_source_t source);
 
 /**
  * @brief
index 6867cca..572d7f0 100644 (file)
@@ -739,7 +739,8 @@ fib_test_v4 (void)
     lb_count = pool_elts(load_balance_pool);
 
     /* Find or create FIB table 11 */
-    fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
+    fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11,
+                                                  FIB_SOURCE_API);
 
     for (ii = 0; ii < 4; ii++)
     {
@@ -4150,7 +4151,7 @@ fib_test_v4 (void)
                                              FIB_SOURCE_INTERFACE)),
              "NO INterface Source'd prefixes");
 
-    fib_table_unlock(fib_index, FIB_PROTOCOL_IP4);
+    fib_table_unlock(fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
 
     FIB_TEST((0  == fib_path_list_db_size()), "path list DB population:%d",
             fib_path_list_db_size());
@@ -4201,7 +4202,8 @@ fib_test_v6 (void)
     dpo_drop = drop_dpo_get(DPO_PROTO_IP6);
 
     /* Find or create FIB table 11 */
-    fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11);
+    fib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP6, 11,
+                                                  FIB_SOURCE_API);
 
     for (ii = 0; ii < 4; ii++)
     {
@@ -5025,7 +5027,7 @@ fib_test_v6 (void)
     /*
      * now remove the VRF
      */
-    fib_table_unlock(fib_index, FIB_PROTOCOL_IP6);
+    fib_table_unlock(fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
 
     FIB_TEST((0 == fib_path_list_db_size()),   "path list DB population:%d",
             fib_path_list_db_size());
@@ -5157,7 +5159,9 @@ fib_test_ae (void)
      */
     u32 import_fib_index1;
 
-    import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 11);
+    import_fib_index1 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4,
+                                                          11,
+                                                          FIB_SOURCE_CLI);
 
     /*
      * Add an attached route in the import FIB
@@ -5233,7 +5237,8 @@ fib_test_ae (void)
      */
     u32 import_fib_index2;
 
-    import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12);
+    import_fib_index2 = fib_table_find_or_create_and_lock(FIB_PROTOCOL_IP4, 12,
+                                                          FIB_SOURCE_CLI);
 
     /*
      * Add an attached route in the import FIB
@@ -5595,8 +5600,8 @@ fib_test_ae (void)
                           &local_pfx,
                           FIB_SOURCE_API);
 
-    fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4);
-    fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4);
+    fib_table_unlock(import_fib_index1, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
+    fib_table_unlock(import_fib_index2, FIB_PROTOCOL_IP4, FIB_SOURCE_CLI);
 
     FIB_TEST((0 == adj_nbr_db_size()), "ADJ DB size is %d",
             adj_nbr_db_size());
@@ -8168,9 +8173,10 @@ lfib_test (void)
     /*
      * MPLS enable an interface so we get the MPLS table created
      */
+    mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
     mpls_sw_interface_enable_disable(&mpls_main,
                                      tm->hw[0]->sw_if_index,
-                                     1);
+                                     1, 1);
 
     ip46_address_t nh_10_10_10_1 = {
        .ip4.as_u32 = clib_host_to_net_u32(0x0a0a0a01),
@@ -8662,7 +8668,8 @@ lfib_test (void)
      */
     mpls_sw_interface_enable_disable(&mpls_main,
                                      tm->hw[0]->sw_if_index,
-                                     0);
+                                     0, 1);
+    mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
 
     FIB_TEST(lb_count == pool_elts(load_balance_pool),
             "Load-balance resources freed %d of %d",
index d563baf..865e2dd 100644 (file)
@@ -101,7 +101,8 @@ static const ip4_fib_table_special_prefix_t ip4_specials[] = {
 
 
 static u32
-ip4_create_fib_with_table_id (u32 table_id)
+ip4_create_fib_with_table_id (u32 table_id,
+                              fib_source_t src)
 {
     fib_table_t *fib_table;
     ip4_fib_t *v4_fib;
@@ -128,7 +129,7 @@ ip4_create_fib_with_table_id (u32 table_id)
     v4_fib->fwd_classify_table_index = ~0;
     v4_fib->rev_classify_table_index = ~0;
     
-    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4);
+    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP4, src);
 
     ip4_mtrie_init(&v4_fib->mtrie);
 
@@ -198,23 +199,24 @@ ip4_fib_table_destroy (u32 fib_index)
 
 
 u32
-ip4_fib_table_find_or_create_and_lock (u32 table_id)
+ip4_fib_table_find_or_create_and_lock (u32 table_id,
+                                       fib_source_t src)
 {
     u32 index;
 
     index = ip4_fib_index_from_table_id(table_id);
     if (~0 == index)
-       return ip4_create_fib_with_table_id(table_id);
+       return ip4_create_fib_with_table_id(table_id, src);
 
-    fib_table_lock(index, FIB_PROTOCOL_IP4);
+    fib_table_lock(index, FIB_PROTOCOL_IP4, src);
 
     return (index);
 }
 
 u32
-ip4_fib_table_create_and_lock (void)
+ip4_fib_table_create_and_lock (fib_source_t src)
 {
-    return (ip4_create_fib_with_table_id(~0));
+    return (ip4_create_fib_with_table_id(~0, src));
 }
 
 u32
@@ -525,17 +527,32 @@ ip4_show_fib (vlib_main_t * vm,
     pool_foreach (fib_table, im4->fibs,
     ({
        ip4_fib_t *fib = pool_elt_at_index(im4->v4_fibs, fib_table->ft_index);
+        fib_source_t source;
+        u8 *s = NULL;
 
        if (table_id >= 0 && table_id != (int)fib->table_id)
            continue;
        if (fib_index != ~0 && fib_index != (int)fib->index)
            continue;
 
-       vlib_cli_output (vm, "%U, fib_index:%d, flow hash:[%U] locks:%d", 
-                        format_fib_table_name, fib->index, FIB_PROTOCOL_IP4,
-                        fib->index,
-                        format_ip_flow_hash_config, fib_table->ft_flow_hash_config,
-                         fib_table->ft_locks);
+       s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[",
+                   format_fib_table_name, fib->index,
+                   FIB_PROTOCOL_IP4,
+                   fib->index,
+                   format_ip_flow_hash_config,
+                   fib_table->ft_flow_hash_config);
+       FOR_EACH_FIB_SOURCE(source)
+        {
+            if (0 != fib_table->ft_locks[source])
+            {
+                s = format(s, "%U:%d, ",
+                           format_fib_source, source,
+                           fib_table->ft_locks[source]);
+            }
+        }
+        s = format (s, "]");
+        vlib_cli_output (vm, "%V", s);
+        vec_free(s);
 
        /* Show summary? */
        if (! verbose)
index 006163b..495b45c 100644 (file)
@@ -127,8 +127,9 @@ ip4_fib_lookup (ip4_main_t * im, u32 sw_if_index, ip4_address_t * dst)
  * @returns A pointer to the retrieved or created fib.
  *
  */
-extern u32 ip4_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip4_fib_table_create_and_lock(void);
+extern u32 ip4_fib_table_find_or_create_and_lock(u32 table_id,
+                                                 fib_source_t src);
+extern u32 ip4_fib_table_create_and_lock(fib_source_t src);
 
 
 static inline 
index 8fde6f9..3ddb845 100644 (file)
@@ -50,7 +50,8 @@ vnet_ip6_fib_init (u32 fib_index)
 }
 
 static u32
-create_fib_with_table_id (u32 table_id)
+create_fib_with_table_id (u32 table_id,
+                          fib_source_t src)
 {
     fib_table_t *fib_table;
     ip6_fib_t *v6_fib;
@@ -77,29 +78,30 @@ create_fib_with_table_id (u32 table_id)
     fib_table->ft_flow_hash_config = IP_FLOW_HASH_DEFAULT;
 
     vnet_ip6_fib_init(fib_table->ft_index);
-    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6);
+    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_IP6, src);
 
     return (fib_table->ft_index);
 }
 
 u32
-ip6_fib_table_find_or_create_and_lock (u32 table_id)
+ip6_fib_table_find_or_create_and_lock (u32 table_id,
+                                       fib_source_t src)
 {
     uword * p;
 
     p = hash_get (ip6_main.fib_index_by_table_id, table_id);
     if (NULL == p)
-       return create_fib_with_table_id(table_id);
+       return create_fib_with_table_id(table_id, src);
     
-    fib_table_lock(p[0], FIB_PROTOCOL_IP6);
+    fib_table_lock(p[0], FIB_PROTOCOL_IP6, src);
 
     return (p[0]);
 }
 
 u32
-ip6_fib_table_create_and_lock (void)
+ip6_fib_table_create_and_lock (fib_source_t src)
 {
-    return (create_fib_with_table_id(~0));
+    return (create_fib_with_table_id(~0, src));
 }
 
 void
@@ -588,16 +590,33 @@ ip6_show_fib (vlib_main_t * vm,
 
     pool_foreach (fib_table, im6->fibs,
     ({
+        fib_source_t source;
+        u8 *s = NULL;
+
        fib = pool_elt_at_index(im6->v6_fibs, fib_table->ft_index);
        if (table_id >= 0 && table_id != (int)fib->table_id)
            continue;
        if (fib_index != ~0 && fib_index != (int)fib->index)
            continue;
 
-       vlib_cli_output (vm, "%s, fib_index:%d, flow hash:[%U] locks:%d", 
-                        fib_table->ft_desc, fib->index,
-                        format_ip_flow_hash_config, fib_table->ft_flow_hash_config,
-                         fib_table->ft_locks);
+       s = format(s, "%U, fib_index:%d, flow hash:[%U] locks:[",
+                   format_fib_table_name, fib->index,
+                   FIB_PROTOCOL_IP6,
+                   fib->index,
+                   format_ip_flow_hash_config,
+                   fib_table->ft_flow_hash_config);
+       FOR_EACH_FIB_SOURCE(source)
+        {
+            if (0 != fib_table->ft_locks[source])
+            {
+                s = format(s, "%U:%d, ",
+                           format_fib_source, source,
+                           fib_table->ft_locks[source]);
+            }
+        }
+        s = format (s, "]");
+        vlib_cli_output (vm, "%V", s);
+        vec_free(s);
 
        /* Show summary? */
        if (! verbose)
index aad8305..9728eec 100644 (file)
@@ -144,8 +144,9 @@ ip6_src_lookup_for_packet (ip6_main_t * im,
  * \returns A pointer to the retrieved or created fib.
  *
  */
-extern u32 ip6_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip6_fib_table_create_and_lock(void);
+extern u32 ip6_fib_table_find_or_create_and_lock(u32 table_id,
+                                                 fib_source_t src);
+extern u32 ip6_fib_table_create_and_lock(fib_source_t src);
 
 static inline ip6_fib_t *
 ip6_fib_get (fib_node_index_t index)
index ca6271f..4eeef7a 100644 (file)
@@ -83,7 +83,8 @@ mpls_fib_index_from_table_id (u32 table_id)
 }
 
 static u32
-mpls_fib_create_with_table_id (u32 table_id)
+mpls_fib_create_with_table_id (u32 table_id,
+                               fib_source_t src)
 {
     dpo_id_t dpo = DPO_INVALID;
     fib_table_t *fib_table;
@@ -107,7 +108,7 @@ mpls_fib_create_with_table_id (u32 table_id)
     fib_table->ft_table_id = table_id;
     fib_table->ft_flow_hash_config = MPLS_FLOW_HASH_DEFAULT;
     
-    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_MPLS);
+    fib_table_lock(fib_table->ft_index, FIB_PROTOCOL_MPLS, src);
 
     if (INDEX_INVALID == mpls_fib_drop_dpo_index)
     {
@@ -220,22 +221,23 @@ mpls_fib_create_with_table_id (u32 table_id)
 }
 
 u32
-mpls_fib_table_find_or_create_and_lock (u32 table_id)
+mpls_fib_table_find_or_create_and_lock (u32 table_id,
+                                        fib_source_t src)
 {
     u32 index;
 
     index = mpls_fib_index_from_table_id(table_id);
     if (~0 == index)
-       return mpls_fib_create_with_table_id(table_id);
+       return mpls_fib_create_with_table_id(table_id, src);
 
-    fib_table_lock(index, FIB_PROTOCOL_MPLS);
+    fib_table_lock(index, FIB_PROTOCOL_MPLS, src);
 
     return (index);
 }
 u32
-mpls_fib_table_create_and_lock (void)
+mpls_fib_table_create_and_lock (fib_source_t src)
 {
-    return (mpls_fib_create_with_table_id(~0));
+    return (mpls_fib_create_with_table_id(~0, src));
 }
 
 void
index dfb8b7f..29cd1d2 100644 (file)
@@ -59,8 +59,9 @@ mpls_fib_get (fib_node_index_t index)
     return (pool_elt_at_index(mpls_main.mpls_fibs, index));
 }
 
-extern u32 mpls_fib_table_find_or_create_and_lock(u32 table_id);
-extern u32 mpls_fib_table_create_and_lock(void);
+extern u32 mpls_fib_table_find_or_create_and_lock(u32 table_id,
+                                                  fib_source_t src);
+extern u32 mpls_fib_table_create_and_lock(fib_source_t src);
 // extern mpls_fib_t * mpls_fib_find(u32 table_id);
 extern u32 mpls_fib_index_from_table_id(u32 table_id);
 
index 113728c..419fef9 100644 (file)
@@ -320,68 +320,189 @@ stats_dsunlock (void)
 static void
 vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
 {
-  int rv = 0;
-  u32 table_id = ntohl (mp->vrf_id);
-  u32 sw_if_index = ntohl (mp->sw_if_index);
   vl_api_sw_interface_set_table_reply_t *rmp;
-  CLIB_UNUSED (ip_interface_address_t * ia);
-  u32 fib_index;
+  u32 sw_if_index = ntohl (mp->sw_if_index);
+  u32 table_id = ntohl (mp->vrf_id);
+  int rv = 0;
 
   VALIDATE_SW_IF_INDEX (mp);
 
   stats_dslock_with_hint (1 /* release hint */ , 4 /* tag */ );
 
   if (mp->is_ipv6)
+    rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id, 1);
+  else
+    rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id, 1);
+
+  stats_dsunlock ();
+
+  BAD_SW_IF_INDEX_LABEL;
+
+  REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
+}
+
+int
+ip_table_bind (fib_protocol_t fproto,
+              uint32_t sw_if_index, uint32_t table_id, u8 is_api)
+{
+  CLIB_UNUSED (ip_interface_address_t * ia);
+  u32 fib_index, mfib_index;
+  fib_source_t src;
+  mfib_source_t msrc;
+
+  if (is_api)
+    {
+      src = FIB_SOURCE_API;
+      msrc = MFIB_SOURCE_API;
+    }
+  else
+    {
+      src = FIB_SOURCE_CLI;
+      msrc = MFIB_SOURCE_CLI;
+    }
+
+  /*
+   * This is temporary whilst I do the song and dance with the CSIT version
+   */
+  if (0 != table_id)
     {
+      fib_index = fib_table_find_or_create_and_lock (fproto, table_id, src);
+      mfib_index =
+       mfib_table_find_or_create_and_lock (fproto, table_id, msrc);
+    }
+  else
+    {
+      fib_index = 0;
+      mfib_index = 0;
+    }
+
+  /*
+   * This if table does not exist = error is what we want in the end.
+   */
+  /* fib_index = fib_table_find (fproto, table_id); */
+  /* mfib_index = mfib_table_find (fproto, table_id); */
+
+  /* if (~0 == fib_index || ~0 == mfib_index) */
+  /*   { */
+  /*     return (VNET_API_ERROR_NO_SUCH_FIB); */
+  /*   } */
+
+  if (FIB_PROTOCOL_IP6 == fproto)
+    {
+      /*
+       * If the interface already has in IP address, then a change int
+       * VRF is not allowed. The IP address applied must first be removed.
+       * We do not do that automatically here, since VPP has no knowledge
+       * of whether thoses subnets are valid in the destination VRF.
+       */
       /* *INDENT-OFF* */
       foreach_ip_interface_address (&ip6_main.lookup_main,
                                    ia, sw_if_index,
                                    1 /* honor unnumbered */ ,
       ({
-        rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE;
-        goto done;
+        return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
       }));
       /* *INDENT-ON* */
 
-      fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                    table_id);
       vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
-      ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
-      fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                     table_id);
       vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index);
-      ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
+
+      /*
+       * tell those that are interested that the binding is changing.
+       */
+      ip6_table_bind_callback_t *cb;
+      vec_foreach (cb, ip6_main.table_bind_callbacks)
+       cb->function (&ip6_main, cb->function_opaque,
+                     sw_if_index,
+                     fib_index,
+                     ip6_main.fib_index_by_sw_if_index[sw_if_index]);
+
+      if (0 == table_id)
+       {
+         /* reset back to default */
+         if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
+           fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
+                             FIB_PROTOCOL_IP6, src);
+         if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
+           mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index
+                              [sw_if_index], FIB_PROTOCOL_IP6, msrc);
+
+       }
+      else
+       {
+         /* we need to lock the table now it's inuse */
+         fib_table_lock (fib_index, FIB_PROTOCOL_IP6, src);
+         mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6, msrc);
+       }
+
+      ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
+      ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
     }
   else
     {
+      /*
+       * If the interface already has in IP address, then a change int
+       * VRF is not allowed. The IP address applied must first be removed.
+       * We do not do that automatically here, since VPP has no knowledge
+       * of whether thoses subnets are valid in the destination VRF.
+       */
       /* *INDENT-OFF* */
       foreach_ip_interface_address (&ip4_main.lookup_main,
                                    ia, sw_if_index,
                                    1 /* honor unnumbered */ ,
       ({
-        rv = VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE;
-        goto done;
+        return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
       }));
       /* *INDENT-ON* */
 
-      fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                    table_id);
       vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
-      ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
-      fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
-                                                     table_id);
       vec_validate (ip4_main.mfib_index_by_sw_if_index, sw_if_index);
-      ip4_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
-    }
 
-done:
-  stats_dsunlock ();
+      /*
+       * tell those that are interested that the binding is changing.
+       */
+      ip4_table_bind_callback_t *cb;
+      vec_foreach (cb, ip4_main.table_bind_callbacks)
+       cb->function (&ip4_main, cb->function_opaque,
+                     sw_if_index,
+                     fib_index,
+                     ip4_main.fib_index_by_sw_if_index[sw_if_index]);
+
+      if (0 == table_id)
+       {
+         /* reset back to default */
+         if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
+           fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
+                             FIB_PROTOCOL_IP4, src);
+         if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
+           mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index
+                              [sw_if_index], FIB_PROTOCOL_IP4, msrc);
 
-  BAD_SW_IF_INDEX_LABEL;
+       }
+      else
+       {
+         /* we need to lock the table now it's inuse */
+         fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+                                                        table_id, src);
 
-  REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
+         mfib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+                                                          table_id, msrc);
+       }
+
+      ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
+      ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
+    }
+
+  /*
+   * Temporary. undo the locks from the find and create at the staart
+   */
+  if (0 != table_id)
+    {
+      fib_table_unlock (fib_index, fproto, src);
+      mfib_table_unlock (mfib_index, fproto, msrc);
+    }
+
+  return (0);
 }
 
 static void
index 70b4ccd..7aae73f 100644 (file)
@@ -184,6 +184,13 @@ void ip_del_all_interface_addresses (vlib_main_t * vm, u32 sw_if_index);
 extern vlib_node_registration_t ip4_inacl_node;
 extern vlib_node_registration_t ip6_inacl_node;
 
+void ip_table_create (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+void ip_table_delete (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+int ip_table_bind (fib_protocol_t fproto,
+                  uint32_t sw_if_index, uint32_t table_id, u8 is_api);
+
 #endif /* included_ip_main_h */
 
 /*
index 8f9a8e2..decb840 100644 (file)
@@ -72,6 +72,16 @@ typedef struct
   uword function_opaque;
 } ip4_add_del_interface_address_callback_t;
 
+typedef void (ip4_table_bind_function_t)
+  (struct ip4_main_t * im,
+   uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+  ip4_table_bind_function_t *function;
+  uword function_opaque;
+} ip4_table_bind_callback_t;
+
 /**
  * @brief IPv4 main type.
  *
@@ -117,6 +127,9 @@ typedef struct ip4_main_t
     ip4_add_del_interface_address_callback_t
     * add_del_interface_address_callbacks;
 
+  /** Functions to call when interface to table biding changes. */
+  ip4_table_bind_callback_t *table_bind_callbacks;
+
   /** Template used to generate IP4 ARP packets. */
   vlib_packet_template_t ip4_arp_request_packet_template;
 
index 2d48e8a..ec4287b 100755 (executable)
@@ -1198,8 +1198,10 @@ ip4_lookup_init (vlib_main_t * vm)
   ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
 
   /* Create FIB with index 0 and table id of 0. */
-  fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
-  mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
+  fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+                                    FIB_SOURCE_DEFAULT_ROUTE);
+  mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+                                     MFIB_SOURCE_DEFAULT_ROUTE);
 
   {
     pg_node_t *pn;
@@ -2794,101 +2796,6 @@ VLIB_REGISTER_NODE (ip4_midchain_node) = {
 VLIB_NODE_FUNCTION_MULTIARCH (ip4_midchain_node, ip4_midchain);
 /* *INDENT-ON */
 
-static clib_error_t *
-add_del_interface_table (vlib_main_t * vm,
-                        unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-  vnet_main_t *vnm = vnet_get_main ();
-  ip_interface_address_t *ia;
-  clib_error_t *error = 0;
-  u32 sw_if_index, table_id;
-
-  sw_if_index = ~0;
-
-  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
-    {
-      error = clib_error_return (0, "unknown interface `%U'",
-                                format_unformat_error, input);
-      goto done;
-    }
-
-  if (unformat (input, "%d", &table_id))
-    ;
-  else
-    {
-      error = clib_error_return (0, "expected table id `%U'",
-                                format_unformat_error, input);
-      goto done;
-    }
-
-  /*
-   * If the interface already has in IP address, then a change int
-   * VRF is not allowed. The IP address applied must first be removed.
-   * We do not do that automatically here, since VPP has no knowledge
-   * of whether thoses subnets are valid in the destination VRF.
-   */
-  /* *INDENT-OFF* */
-  foreach_ip_interface_address (&ip4_main.lookup_main,
-                                ia, sw_if_index,
-                                1 /* honor unnumbered */,
-  ({
-      ip4_address_t * a;
-
-      a = ip_interface_address_get_address (&ip4_main.lookup_main, ia);
-      error = clib_error_return (0, "interface %U has address %U",
-                                 format_vnet_sw_if_index_name, vnm,
-                                 sw_if_index,
-                                 format_ip4_address, a);
-      goto done;
-   }));
-   /* *INDENT-ON* */
-
-{
-  ip4_main_t *im = &ip4_main;
-  u32 fib_index;
-
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
-
-  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
-  im->fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
-  fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
-  vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
-  im->mfib_index_by_sw_if_index[sw_if_index] = fib_index;
-}
-
-done:
-return error;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv4 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * an IP Address is assigned to an interface in the table (which adds a route
- * automatically).
- *
- * @note IP addresses added after setting the interface IP table are added to
- * the indicated FIB table. If an IP address is added prior to changing the
- * table then this is an error. The control plane must remove these addresses
- * first and then change the table. VPP will not automatically move the
- * addresses from the old to the new table as it does not know the validity
- * of such a change.
- *
- * @cliexpar
- * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
- * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
-{
-  .path = "set interface ip table",
-  .function = add_del_interface_table,
-  .short_help = "set interface ip table <interface> <table-id>",
-};
-/* *INDENT-ON* */
-
 int
 ip4_lookup_validate (ip4_address_t * a, u32 fib_index0)
 {
index ae836a1..9aa880a 100644 (file)
@@ -1126,6 +1126,14 @@ ip6_source_and_port_range_check_add_del (ip6_address_t * address,
                                         u16 * low_ports,
                                         u16 * high_ports, int is_add)
 {
+  uint32_t fib_index;
+
+  fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+
+  ASSERT (~0 != fib_index);
+
+  fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
+
   return 0;
 }
 
@@ -1138,7 +1146,8 @@ ip4_source_and_port_range_check_add_del (ip4_address_t * address,
 {
   u32 fib_index;
 
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+                                                FIB_SOURCE_CLASSIFY);
 
   if (is_add == 0)
     {
index fa92272..8aef53a 100644 (file)
@@ -103,6 +103,16 @@ typedef struct
   uword function_opaque;
 } ip6_add_del_interface_address_callback_t;
 
+typedef void (ip6_table_bind_function_t)
+  (struct ip6_main_t * im,
+   uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+  ip6_table_bind_function_t *function;
+  uword function_opaque;
+} ip6_table_bind_callback_t;
+
 /**
  * Enumeration of the FIB table instance types
  */
@@ -183,6 +193,9 @@ typedef struct ip6_main_t
     ip6_add_del_interface_address_callback_t
     * add_del_interface_address_callbacks;
 
+  /** Functions to call when interface to table biding changes. */
+  ip6_table_bind_callback_t *table_bind_callbacks;
+
   /* Template used to generate IP6 neighbor solicitation packets. */
   vlib_packet_template_t discover_neighbor_packet_template;
 
index 5832bd0..1002f6b 100644 (file)
@@ -2999,8 +2999,10 @@ ip6_lookup_init (vlib_main_t * vm)
                         im->lookup_table_nbuckets, im->lookup_table_size);
 
   /* Create FIB with index 0 and table id of 0. */
-  fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
-  mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
+  fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+                                    FIB_SOURCE_DEFAULT_ROUTE);
+  mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+                                     MFIB_SOURCE_DEFAULT_ROUTE);
 
   {
     pg_node_t *pn;
@@ -3045,103 +3047,6 @@ ip6_lookup_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (ip6_lookup_init);
 
-static clib_error_t *
-add_del_ip6_interface_table (vlib_main_t * vm,
-                            unformat_input_t * input,
-                            vlib_cli_command_t * cmd)
-{
-  vnet_main_t *vnm = vnet_get_main ();
-  ip_interface_address_t *ia;
-  clib_error_t *error = 0;
-  u32 sw_if_index, table_id;
-
-  sw_if_index = ~0;
-
-  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
-    {
-      error = clib_error_return (0, "unknown interface `%U'",
-                                format_unformat_error, input);
-      goto done;
-    }
-
-  if (unformat (input, "%d", &table_id))
-    ;
-  else
-    {
-      error = clib_error_return (0, "expected table id `%U'",
-                                format_unformat_error, input);
-      goto done;
-    }
-
-  /*
-   * If the interface already has in IP address, then a change int
-   * VRF is not allowed. The IP address applied must first be removed.
-   * We do not do that automatically here, since VPP has no knowledge
-   * of whether thoses subnets are valid in the destination VRF.
-   */
-  /* *INDENT-OFF* */
-  foreach_ip_interface_address (&ip6_main.lookup_main,
-                                ia, sw_if_index,
-                                1 /* honor unnumbered */,
-  ({
-      ip4_address_t * a;
-
-      a = ip_interface_address_get_address (&ip6_main.lookup_main, ia);
-      error = clib_error_return (0, "interface %U has address %U",
-                                 format_vnet_sw_if_index_name, vnm,
-                                 sw_if_index,
-                                 format_ip6_address, a);
-      goto done;
-  }));
-  /* *INDENT-ON* */
-
-  {
-    u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                      table_id);
-
-    vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
-    ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
-    fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
-                                                   table_id);
-
-    vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index);
-    ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
-  }
-
-
-done:
-  return error;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv6 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * an IP Address is assigned to an interface in the table (which adds a route
- * automatically).
- *
- * @note IP addresses added after setting the interface IP table are added to
- * the indicated FIB table. If an IP address is added prior to changing the
- * table then this is an error. The control plane must remove these addresses
- * first and then change the table. VPP will not automatically move the
- * addresses from the old to the new table as it does not know the validity
- * of such a change.
- *
- * @cliexpar
- * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
- * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
-{
-  .path = "set interface ip6 table",
-  .function = add_del_ip6_interface_table,
-  .short_help = "set interface ip6 table <interface> <table-id>"
-};
-/* *INDENT-ON* */
-
 void
 ip6_link_local_address_from_ethernet_mac_address (ip6_address_t * ip,
                                                  u8 * mac)
index 62cf23a..56f33ac 100644 (file)
@@ -250,6 +250,26 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
   return s;
 }
 
+static void
+ip6_neighbor_adj_fib_remove (ip6_neighbor_t * n, uint32_t fib_index)
+{
+  if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
+    {
+      fib_prefix_t pfx = {
+       .fp_len = 128,
+       .fp_proto = FIB_PROTOCOL_IP6,
+       .fp_addr.ip6 = n->key.ip6_address,
+      };
+      fib_table_entry_path_remove (fib_index,
+                                  &pfx,
+                                  FIB_SOURCE_ADJ,
+                                  DPO_PROTO_IP6,
+                                  &pfx.fp_addr,
+                                  n->key.sw_if_index, ~0,
+                                  1, FIB_ROUTE_PATH_FLAG_NONE);
+    }
+}
+
 static clib_error_t *
 ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
                                   u32 sw_if_index, u32 flags)
@@ -273,22 +293,10 @@ ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
        {
          n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
          mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
-         if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
-           {
-             fib_prefix_t pfx = {
-               .fp_len = 128,
-               .fp_proto = FIB_PROTOCOL_IP6,
-               .fp_addr.ip6 = n->key.ip6_address,
-             };
-             fib_table_entry_path_remove
-               (ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index),
-                &pfx,
-                FIB_SOURCE_ADJ,
-                DPO_PROTO_IP6,
-                &pfx.fp_addr,
-                n->key.sw_if_index, ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
-             pool_put (nm->neighbor_pool, n);
-           }
+         ip6_neighbor_adj_fib_remove (n,
+                                      ip6_fib_table_get_index_for_sw_if_index
+                                      (n->key.sw_if_index));
+         pool_put (nm->neighbor_pool, n);
        }
       vec_free (to_delete);
     }
@@ -579,6 +587,24 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
     }
 }
 
+
+static void
+ip6_neighbor_adj_fib_add (ip6_neighbor_t * n, uint32_t fib_index)
+{
+  fib_prefix_t pfx = {
+    .fp_len = 128,
+    .fp_proto = FIB_PROTOCOL_IP6,
+    .fp_addr.ip6 = n->key.ip6_address,
+  };
+
+  n->fib_entry_index =
+    fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+                             FIB_ENTRY_FLAG_ATTACHED,
+                             DPO_PROTO_IP6, &pfx.fp_addr,
+                             n->key.sw_if_index, ~0, 1, NULL,
+                             FIB_ROUTE_PATH_FLAG_NONE);
+}
+
 int
 vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
                                u32 sw_if_index,
@@ -633,21 +659,9 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
        */
       if (!is_no_fib_entry)
        {
-         fib_prefix_t pfx = {
-           .fp_len = 128,
-           .fp_proto = FIB_PROTOCOL_IP6,
-           .fp_addr.ip6 = k.ip6_address,
-         };
-         u32 fib_index;
-
-         fib_index =
-           ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index);
-         n->fib_entry_index =
-           fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
-                                     FIB_ENTRY_FLAG_ATTACHED,
-                                     DPO_PROTO_IP6, &pfx.fp_addr,
-                                     n->key.sw_if_index, ~0, 1, NULL,
-                                     FIB_ROUTE_PATH_FLAG_NONE);
+         ip6_neighbor_adj_fib_add (n,
+                                   ip6_fib_table_get_index_for_sw_if_index
+                                   (n->key.sw_if_index));
        }
       else
        {
@@ -3843,6 +3857,33 @@ ip6_set_neighbor_limit (u32 neighbor_limit)
   return 0;
 }
 
+static void
+ip6_neighbor_table_bind (ip6_main_t * im,
+                        uword opaque,
+                        u32 sw_if_index,
+                        u32 new_fib_index, u32 old_fib_index)
+{
+  ip6_neighbor_main_t *nm = &ip6_neighbor_main;
+  ip6_neighbor_t *n = NULL;
+  u32 i, *to_re_add = 0;
+
+  /* *INDENT-OFF* */
+  pool_foreach (n, nm->neighbor_pool,
+  ({
+    if (n->key.sw_if_index == sw_if_index)
+      vec_add1 (to_re_add, n - nm->neighbor_pool);
+  }));
+  /* *INDENT-ON* */
+
+  for (i = 0; i < vec_len (to_re_add); i++)
+    {
+      n = pool_elt_at_index (nm->neighbor_pool, to_re_add[i]);
+      ip6_neighbor_adj_fib_remove (n, old_fib_index);
+      ip6_neighbor_adj_fib_add (n, new_fib_index);
+    }
+  vec_free (to_re_add);
+}
+
 static clib_error_t *
 ip6_neighbor_init (vlib_main_t * vm)
 {
@@ -3874,6 +3915,11 @@ ip6_neighbor_init (vlib_main_t * vm)
   cb.function_opaque = 0;
   vec_add1 (im->add_del_interface_address_callbacks, cb);
 
+  ip6_table_bind_callback_t cbt;
+  cbt.function = ip6_neighbor_table_bind;
+  cbt.function_opaque = 0;
+  vec_add1 (im->table_bind_callbacks, cbt);
+
   mhash_init (&nm->pending_resolutions_by_address,
              /* value size */ sizeof (uword),
              /* key size */ sizeof (ip6_address_t));
index bba65ab..384ec3e 100644 (file)
@@ -699,12 +699,58 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
   REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
 }
 
+void
+ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+  u32 fib_index, mfib_index;
+
+  /*
+   * ignore action on the default table - this is always present
+   * and cannot be added nor deleted from the API
+   */
+  if (0 != table_id)
+    {
+      /*
+       * The API holds only one lock on the table.
+       * i.e. it can be added many times via the API but needs to be
+       * deleted only once.
+       * The FIB index for unicast and multicast is not necessarily the
+       * same, since internal VPP systesm (like LISP and SR) create
+       * their own unicast tables.
+       */
+      fib_index = fib_table_find (fproto, table_id);
+      mfib_index = mfib_table_find (fproto, table_id);
+
+      if (~0 != fib_index)
+       {
+         fib_table_unlock (fib_index, fproto,
+                           (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+       }
+      if (~0 != mfib_index)
+       {
+         mfib_table_unlock (mfib_index, fproto,
+                            (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
+       }
+    }
+}
+
 void
 vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
 {
   vl_api_ip_table_add_del_reply_t *rmp;
+  fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+  u32 table_id = ntohl (mp->table_id);
   int rv = 0;
 
+  if (mp->is_add)
+    {
+      ip_table_create (fproto, table_id, 1);
+    }
+  else
+    {
+      ip_table_delete (fproto, table_id, 1);
+    }
+
   REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
 }
 
@@ -866,18 +912,21 @@ add_del_route_check (fib_protocol_t table_proto,
                     u32 next_hop_sw_if_index,
                     dpo_proto_t next_hop_table_proto,
                     u32 next_hop_table_id,
-                    u8 create_missing_tables,
                     u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
 {
   vnet_main_t *vnm = vnet_get_main ();
 
+  /* Temporaray whilst I do the CSIT dance */
+  u8 create_missing_tables = 1;
+
   *fib_index = fib_table_find (table_proto, ntohl (table_id));
   if (~0 == *fib_index)
     {
       if (create_missing_tables)
        {
          *fib_index = fib_table_find_or_create_and_lock (table_proto,
-                                                         ntohl (table_id));
+                                                         ntohl (table_id),
+                                                         FIB_SOURCE_API);
        }
       else
        {
@@ -918,12 +967,14 @@ add_del_route_check (fib_protocol_t table_proto,
                *next_hop_fib_index =
                  mfib_table_find_or_create_and_lock (fib_nh_proto,
                                                      ntohl
-                                                     (next_hop_table_id));
+                                                     (next_hop_table_id),
+                                                     MFIB_SOURCE_API);
              else
                *next_hop_fib_index =
                  fib_table_find_or_create_and_lock (fib_nh_proto,
                                                     ntohl
-                                                    (next_hop_table_id));
+                                                    (next_hop_table_id),
+                                                    FIB_SOURCE_API);
            }
          else
            {
@@ -948,8 +999,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
                            mp->next_hop_sw_if_index,
                            DPO_PROTO_IP4,
                            mp->next_hop_table_id,
-                           mp->create_vrf_if_needed, 0,
-                           &fib_index, &next_hop_fib_index);
+                           0, &fib_index, &next_hop_fib_index);
 
   if (0 != rv)
     return (rv);
@@ -1008,8 +1058,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
                            mp->next_hop_sw_if_index,
                            DPO_PROTO_IP6,
                            mp->next_hop_table_id,
-                           mp->create_vrf_if_needed, 0,
-                           &fib_index, &next_hop_fib_index);
+                           0, &fib_index, &next_hop_fib_index);
 
   if (0 != rv)
     return (rv);
@@ -1074,27 +1123,57 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
   REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
 }
 
+void
+ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+  u32 fib_index, mfib_index;
+
+  /*
+   * ignore action on the default table - this is always present
+   * and cannot be added nor deleted from the API
+   */
+  if (0 != table_id)
+    {
+      /*
+       * The API holds only one lock on the table.
+       * i.e. it can be added many times via the API but needs to be
+       * deleted only once.
+       * The FIB index for unicast and multicast is not necessarily the
+       * same, since internal VPP systesm (like LISP and SR) create
+       * their own unicast tables.
+       */
+      fib_index = fib_table_find (fproto, table_id);
+      mfib_index = mfib_table_find (fproto, table_id);
+
+      if (~0 == fib_index)
+       {
+         fib_table_find_or_create_and_lock (fproto, table_id,
+                                            (is_api ?
+                                             FIB_SOURCE_API :
+                                             FIB_SOURCE_CLI));
+       }
+      if (~0 == mfib_index)
+       {
+         mfib_table_find_or_create_and_lock (fproto, table_id,
+                                             (is_api ?
+                                              MFIB_SOURCE_API :
+                                              MFIB_SOURCE_CLI));
+       }
+    }
+}
+
 static int
 add_del_mroute_check (fib_protocol_t table_proto,
                      u32 table_id,
-                     u32 next_hop_sw_if_index,
-                     u8 is_local, u8 create_missing_tables, u32 * fib_index)
+                     u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
 {
   vnet_main_t *vnm = vnet_get_main ();
 
   *fib_index = mfib_table_find (table_proto, ntohl (table_id));
   if (~0 == *fib_index)
     {
-      if (create_missing_tables)
-       {
-         *fib_index = mfib_table_find_or_create_and_lock (table_proto,
-                                                          ntohl (table_id));
-       }
-      else
-       {
-         /* No such VRF, and we weren't asked to create one */
-         return VNET_API_ERROR_NO_SUCH_FIB;
-       }
+      /* No such table */
+      return VNET_API_ERROR_NO_SUCH_FIB;
     }
 
   if (~0 != ntohl (next_hop_sw_if_index))
@@ -1163,8 +1242,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
   rv = add_del_mroute_check (fproto,
                             mp->table_id,
                             mp->next_hop_sw_if_index,
-                            mp->is_local,
-                            mp->create_vrf_if_needed, &fib_index);
+                            mp->is_local, &fib_index);
 
   if (0 != rv)
     return (rv);
index 5537bb0..667c679 100755 (executable)
@@ -687,6 +687,78 @@ done:
   return error;
 }
 
+clib_error_t *
+vnet_ip_table_cmd (vlib_main_t * vm,
+                  unformat_input_t * main_input,
+                  vlib_cli_command_t * cmd, fib_protocol_t fproto)
+{
+  unformat_input_t _line_input, *line_input = &_line_input;
+  clib_error_t *error = NULL;
+  u32 table_id, is_add;
+
+  is_add = 1;
+  table_id = ~0;
+
+  /* Get a line of input. */
+  if (!unformat_user (main_input, unformat_line_input, line_input))
+    return 0;
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "%d", &table_id))
+       ;
+      else if (unformat (line_input, "del"))
+       is_add = 0;
+      else if (unformat (line_input, "add"))
+       is_add = 1;
+      else
+       {
+         error = unformat_parse_error (line_input);
+         goto done;
+       }
+    }
+
+  if (~0 == table_id)
+    {
+      error = clib_error_return (0, "No table id");
+      goto done;
+    }
+  else if (0 == table_id)
+    {
+      error = clib_error_return (0, "Can't change the default table");
+      goto done;
+    }
+  else
+    {
+      if (is_add)
+       {
+         ip_table_create (fproto, table_id, 0);
+       }
+      else
+       {
+         ip_table_delete (fproto, table_id, 0);
+       }
+    }
+
+done:
+  unformat_free (line_input);
+  return error;
+}
+
+clib_error_t *
+vnet_ip4_table_cmd (vlib_main_t * vm,
+                   unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
+}
+
+clib_error_t *
+vnet_ip6_table_cmd (vlib_main_t * vm,
+                   unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
+}
+
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
   .path = "ip",
@@ -749,6 +821,159 @@ VLIB_CLI_COMMAND (ip_route_command, static) = {
   .function = vnet_ip_route_cmd,
   .is_mp_safe = 1,
 };
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4  Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip4_table_command, static) = {
+  .path = "ip table",
+  .short_help = "ip table [add|del] <table-id>",
+  .function = vnet_ip4_table_cmd,
+  .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4  Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip6_table_command, static) = {
+  .path = "ip6 table",
+  .short_help = "ip6 table [add|del] <table-id>",
+  .function = vnet_ip6_table_cmd,
+  .is_mp_safe = 1,
+};
+
+static clib_error_t *
+ip_table_bind_cmd (vlib_main_t * vm,
+                   unformat_input_t * input,
+                   vlib_cli_command_t * cmd,
+                   fib_protocol_t fproto)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  clib_error_t *error = 0;
+  u32 sw_if_index, table_id;
+  int rv;
+
+  sw_if_index = ~0;
+
+  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
+    {
+      error = clib_error_return (0, "unknown interface `%U'",
+                                format_unformat_error, input);
+      goto done;
+    }
+
+  if (unformat (input, "%d", &table_id))
+    ;
+  else
+    {
+      error = clib_error_return (0, "expected table id `%U'",
+                                format_unformat_error, input);
+      goto done;
+    }
+
+  rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
+
+  if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
+    {
+      error = clib_error_return (0, "IP addresses are still present on %U",
+                                 format_vnet_sw_if_index_name,
+                                 vnet_get_main(),
+                                 sw_if_index);
+    }
+  else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
+    {
+      error = clib_error_return (0, "no such table %d", table_id);
+    }
+  else if (0 != rv)
+    {
+      error = clib_error_return (0, "unknown error");
+    }
+
+ done:
+  return error;
+}
+
+static clib_error_t *
+ip4_table_bind_cmd (vlib_main_t * vm,
+                    unformat_input_t * input,
+                    vlib_cli_command_t * cmd)
+{
+  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
+}
+
+static clib_error_t *
+ip6_table_bind_cmd (vlib_main_t * vm,
+                    unformat_input_t * input,
+                    vlib_cli_command_t * cmd)
+{
+  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
+}
+
+/*?
+ * Place the indicated interface into the supplied IPv4 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * an IP Address is assigned to an interface in the table (which adds a route
+ * automatically).
+ *
+ * @note IP addresses added after setting the interface IP table are added to
+ * the indicated FIB table. If an IP address is added prior to changing the
+ * table then this is an error. The control plane must remove these addresses
+ * first and then change the table. VPP will not automatically move the
+ * addresses from the old to the new table as it does not know the validity
+ * of such a change.
+ *
+ * @cliexpar
+ * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
+ * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
+{
+  .path = "set interface ip table",
+  .function = ip4_table_bind_cmd,
+  .short_help = "set interface ip table <interface> <table-id>",
+};
+/* *INDENT-ON* */
+
+/*?
+ * Place the indicated interface into the supplied IPv6 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * an IP Address is assigned to an interface in the table (which adds a route
+ * automatically).
+ *
+ * @note IP addresses added after setting the interface IP table are added to
+ * the indicated FIB table. If an IP address is added prior to changing the
+ * table then this is an error. The control plane must remove these addresses
+ * first and then change the table. VPP will not automatically move the
+ * addresses from the old to the new table as it does not know the validity
+ * of such a change.
+ *
+ * @cliexpar
+ * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
+ * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
+{
+  .path = "set interface ip6 table",
+  .function = ip6_table_bind_cmd,
+  .short_help = "set interface ip6 table <interface> <table-id>"
+};
 /* *INDENT-ON* */
 
 clib_error_t *
index e832c23..a0c05e8 100644 (file)
@@ -505,12 +505,14 @@ lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id)
 {
   fib_node_index_t fib_index;
 
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
+  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id,
+                                                FIB_SOURCE_LISP);
   vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
   ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
   ip4_sw_interface_enable_disable (sw_if_index, 1);
 
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
+  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id,
+                                                FIB_SOURCE_LISP);
   vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
   ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
   ip6_sw_interface_enable_disable (sw_if_index, 1);
@@ -530,7 +532,7 @@ lisp_gpe_tenant_del_default_routes (u32 table_id)
 
     fib_index = fib_table_find (prefix.fp_proto, table_id);
     fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP);
-    fib_table_unlock (fib_index, prefix.fp_proto);
+    fib_table_unlock (fib_index, prefix.fp_proto, FIB_SOURCE_LISP);
   }
 }
 
@@ -549,7 +551,8 @@ lisp_gpe_tenant_add_default_routes (u32 table_id)
     /*
      * Add a deafult route that results in a control plane punt DPO
      */
-    fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id);
+    fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id,
+                                                  FIB_SOURCE_LISP);
     fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP,
                                     FIB_ENTRY_FLAG_EXCLUSIVE,
                                     lisp_cp_dpo_get (fib_proto_to_dpo
index d7d3cb8..0a8dc03 100644 (file)
@@ -66,6 +66,7 @@ ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix)
       /* create a new src FIB.  */
       src_fib_index =
        fib_table_create_and_lock (dst_fib_prefix.fp_proto,
+                                  FIB_SOURCE_LISP,
                                   "LISP-src for [%d,%U]",
                                   dst_fib_index,
                                   format_fib_prefix, &dst_fib_prefix);
@@ -180,7 +181,8 @@ ip_src_dst_fib_del_route (u32 src_fib_index,
        */
       fib_table_entry_special_remove (dst_fib_index,
                                      &dst_fib_prefix, FIB_SOURCE_LISP);
-      fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto);
+      fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto,
+                       FIB_SOURCE_LISP);
     }
 }
 
@@ -544,7 +546,8 @@ add_ip_fwd_entry (lisp_gpe_main_t * lgm,
   lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni);
   lfe->eid_table_id = a->table_id;
   lfe->eid_fib_index = fib_table_find_or_create_and_lock (fproto,
-                                                         lfe->eid_table_id);
+                                                         lfe->eid_table_id,
+                                                         FIB_SOURCE_LISP);
   lfe->is_src_dst = a->is_src_dst;
 
   if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type)
@@ -578,7 +581,7 @@ del_ip_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe)
 
   fproto = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ?
            FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
-  fib_table_unlock (lfe->eid_fib_index, fproto);
+  fib_table_unlock (lfe->eid_fib_index, fproto, FIB_SOURCE_LISP);
 
   hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key);
   clib_mem_free (lfe->key);
index b234d9d..26664f5 100644 (file)
@@ -89,13 +89,15 @@ lisp_gpe_sub_interface_set_table (u32 sw_if_index, u32 table_id)
 {
   fib_node_index_t fib_index;
 
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
+  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id,
+                                                FIB_SOURCE_LISP);
   ASSERT (FIB_NODE_INDEX_INVALID != fib_index);
 
   vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
   ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
 
-  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id);
+  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id,
+                                                FIB_SOURCE_LISP);
   ASSERT (FIB_NODE_INDEX_INVALID != fib_index);
 
   vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
@@ -105,9 +107,13 @@ lisp_gpe_sub_interface_set_table (u32 sw_if_index, u32 table_id)
 static void
 lisp_gpe_sub_interface_unset_table (u32 sw_if_index, u32 table_id)
 {
+  fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
+                   FIB_PROTOCOL_IP4, FIB_SOURCE_LISP);
   ip4_main.fib_index_by_sw_if_index[sw_if_index] = 0;
   ip4_sw_interface_enable_disable (sw_if_index, 0);
 
+  fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
+                   FIB_PROTOCOL_IP6, FIB_SOURCE_LISP);
   ip6_main.fib_index_by_sw_if_index[sw_if_index] = 0;
   ip6_sw_interface_enable_disable (sw_if_index, 0);
 }
@@ -185,6 +191,7 @@ lisp_gpe_sub_interface_unlock (index_t l3si)
 
   l3s = lisp_gpe_sub_interface_get_i (l3si);
 
+  ASSERT (0 != l3s->locks);
   l3s->locks--;
 
   if (0 == l3s->locks)
index 1849a3a..b248258 100644 (file)
@@ -33,7 +33,8 @@ static const mfib_prefix_t ip4_specials[] = {
 };
 
 static u32
-ip4_create_mfib_with_table_id (u32 table_id)
+ip4_create_mfib_with_table_id (u32 table_id,
+                               mfib_source_t src)
 {
     mfib_table_t *mfib_table;
 
@@ -53,7 +54,7 @@ ip4_create_mfib_with_table_id (u32 table_id)
         mfib_table->v4.table_id =
             table_id;
 
-    mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4);
+    mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP4, src);
 
     /*
      * add the special entries into the new FIB
@@ -113,14 +114,15 @@ ip4_mfib_table_destroy (ip4_mfib_t *mfib)
 }
 
 u32
-ip4_mfib_table_find_or_create_and_lock (u32 table_id)
+ip4_mfib_table_find_or_create_and_lock (u32 table_id,
+                                        mfib_source_t src)
 {
     u32 index;
 
     index = ip4_mfib_index_from_table_id(table_id);
     if (~0 == index)
-        return ip4_create_mfib_with_table_id(table_id);
-    mfib_table_lock(index, FIB_PROTOCOL_IP4);
+        return ip4_create_mfib_with_table_id(table_id, src);
+    mfib_table_lock(index, FIB_PROTOCOL_IP4, src);
 
     return (index);
 }
index ea68265..e31fb74 100644 (file)
@@ -72,8 +72,9 @@ ip4_mfib_get (u32 index)
  * @returns A pointer to the retrieved or created fib.
  *
  */
-extern u32 ip4_mfib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip4_mfib_table_create_and_lock(void);
+extern u32 ip4_mfib_table_find_or_create_and_lock(u32 table_id,
+                                                  mfib_source_t src);
+extern u32 ip4_mfib_table_create_and_lock(mfib_source_t src);
 
 static inline
 u32 ip4_mfib_index_from_table_id (u32 table_id)
index 5e48e91..e486133 100644 (file)
@@ -151,7 +151,8 @@ static const ip6_mfib_special_t ip6_mfib_specials[] =
 
 
 static u32
-ip6_create_mfib_with_table_id (u32 table_id)
+ip6_create_mfib_with_table_id (u32 table_id,
+                               mfib_source_t src)
 {
     mfib_table_t *mfib_table;
     mfib_prefix_t pfx = {
@@ -182,7 +183,7 @@ ip6_create_mfib_with_table_id (u32 table_id)
         mfib_table->v6.table_id =
             table_id;
 
-    mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP6);
+    mfib_table_lock(mfib_table->mft_index, FIB_PROTOCOL_IP6, src);
 
     mfib_table->v6.rhead =
         clib_mem_alloc_aligned (sizeof(*mfib_table->v6.rhead),
@@ -297,14 +298,15 @@ ip6_mfib_interface_enable_disable (u32 sw_if_index, int is_enable)
 }
 
 u32
-ip6_mfib_table_find_or_create_and_lock (u32 table_id)
+ip6_mfib_table_find_or_create_and_lock (u32 table_id,
+                                        mfib_source_t src)
 {
     u32 index;
 
     index = ip6_mfib_index_from_table_id(table_id);
     if (~0 == index)
-        return ip6_create_mfib_with_table_id(table_id);
-    mfib_table_lock(index, FIB_PROTOCOL_IP6);
+        return ip6_create_mfib_with_table_id(table_id, src);
+    mfib_table_lock(index, FIB_PROTOCOL_IP6, src);
 
     return (index);
 }
index adaa7ec..ea81b55 100644 (file)
@@ -79,8 +79,9 @@ ip6_mfib_get (u32 index)
  * @returns A pointer to the retrieved or created fib.
  *
  */
-extern u32 ip6_mfib_table_find_or_create_and_lock(u32 table_id);
-extern u32 ip6_mfib_table_create_and_lock(void);
+extern u32 ip6_mfib_table_find_or_create_and_lock(u32 table_id,
+                                                  mfib_source_t src);
+extern u32 ip6_mfib_table_create_and_lock(mfib_source_t src);
 
 
 static inline
index 804e10a..2302b9a 100644 (file)
@@ -334,6 +334,17 @@ mfib_entry_get_best_src (const mfib_entry_t *mfib_entry)
     return (bsrc);
 }
 
+int
+mfib_entry_is_sourced (fib_node_index_t mfib_entry_index,
+                       mfib_source_t source)
+{
+    mfib_entry_t *mfib_entry;
+
+    mfib_entry = mfib_entry_get(mfib_entry_index);
+
+    return (NULL != mfib_entry_src_find(mfib_entry, source, NULL));
+}
+
 static void
 mfib_entry_src_flush (mfib_entry_src_t *msrc)
 {
index d437787..96ee49f 100644 (file)
@@ -130,6 +130,8 @@ extern void mfib_entry_unlock(fib_node_index_t fib_entry_index);
 extern void mfib_entry_get_prefix(fib_node_index_t fib_entry_index,
                                   mfib_prefix_t *pfx);
 extern u32 mfib_entry_get_fib_index(fib_node_index_t fib_entry_index);
+extern int mfib_entry_is_sourced(fib_node_index_t fib_entry_index,
+                                 mfib_source_t source);
 
 extern void mfib_entry_contribute_forwarding(
     fib_node_index_t mfib_entry_index,
index 7ffe894..e5550ad 100644 (file)
@@ -424,7 +424,8 @@ mfib_table_find (fib_protocol_t proto,
 
 u32
 mfib_table_find_or_create_and_lock (fib_protocol_t proto,
-                                    u32 table_id)
+                                    u32 table_id,
+                                    mfib_source_t src)
 {
     mfib_table_t *mfib_table;
     fib_node_index_t fi;
@@ -432,10 +433,10 @@ mfib_table_find_or_create_and_lock (fib_protocol_t proto,
     switch (proto)
     {
     case FIB_PROTOCOL_IP4:
-        fi = ip4_mfib_table_find_or_create_and_lock(table_id);
+        fi = ip4_mfib_table_find_or_create_and_lock(table_id, src);
         break;
     case FIB_PROTOCOL_IP6:
-        fi = ip6_mfib_table_find_or_create_and_lock(table_id);
+        fi = ip6_mfib_table_find_or_create_and_lock(table_id, src);
         break;
     case FIB_PROTOCOL_MPLS:
     default:
@@ -451,6 +452,59 @@ mfib_table_find_or_create_and_lock (fib_protocol_t proto,
     return (fi);
 }
 
+/**
+ * @brief Table flush context. Store the indicies of matching FIB entries
+ * that need to be removed.
+ */
+typedef struct mfib_table_flush_ctx_t_
+{
+    /**
+     * The list of entries to flush
+     */
+    fib_node_index_t *mftf_entries;
+
+    /**
+     * The source we are flushing
+     */
+    mfib_source_t mftf_source;
+} mfib_table_flush_ctx_t;
+
+static int
+mfib_table_flush_cb (fib_node_index_t mfib_entry_index,
+                     void *arg)
+{
+    mfib_table_flush_ctx_t *ctx = arg;
+
+    if (mfib_entry_is_sourced(mfib_entry_index, ctx->mftf_source))
+    {
+        vec_add1(ctx->mftf_entries, mfib_entry_index);
+    }
+    return (1);
+}
+
+void
+mfib_table_flush (u32 mfib_index,
+                  fib_protocol_t proto,
+                  mfib_source_t source)
+{
+    fib_node_index_t *mfib_entry_index;
+    mfib_table_flush_ctx_t ctx = {
+        .mftf_entries = NULL,
+        .mftf_source = source,
+    };
+
+    mfib_table_walk(mfib_index, proto,
+                    mfib_table_flush_cb,
+                    &ctx);
+
+    vec_foreach(mfib_entry_index, ctx.mftf_entries)
+    {
+        mfib_table_entry_delete_index(*mfib_entry_index, source);
+    }
+
+    vec_free(ctx.mftf_entries);
+}
+
 static void
 mfib_table_destroy (mfib_table_t *mfib_table)
 {
@@ -472,27 +526,43 @@ mfib_table_destroy (mfib_table_t *mfib_table)
 
 void
 mfib_table_unlock (u32 fib_index,
-                   fib_protocol_t proto)
+                   fib_protocol_t proto,
+                   mfib_source_t source)
 {
     mfib_table_t *mfib_table;
 
     mfib_table = mfib_table_get(fib_index, proto);
-    mfib_table->mft_locks--;
+    mfib_table->mft_locks[source]--;
+    mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]--;
+
+    if (0 == mfib_table->mft_locks[source])
+    {
+        /*
+         * The source no longer needs the table. flush any routes
+         * from it just in case
+         */
+        mfib_table_flush(fib_index, proto, source);
+    }
 
-    if (0 == mfib_table->mft_locks)
+    if (0 == mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS])
     {
-        mfib_table_destroy(mfib_table);
+        /*
+         * no more locak from any source - kill it
+         */
+       mfib_table_destroy(mfib_table);
     }
 }
 
 void
 mfib_table_lock (u32 fib_index,
-                 fib_protocol_t proto)
+                 fib_protocol_t proto,
+                 mfib_source_t source)
 {
     mfib_table_t *mfib_table;
 
     mfib_table = mfib_table_get(fib_index, proto);
-    mfib_table->mft_locks++;
+    mfib_table->mft_locks[source]++;
+    mfib_table->mft_locks[MFIB_TABLE_TOTAL_LOCKS]++;
 }
 
 void
index 83aa04e..c6b0b09 100644 (file)
 
 #include <vnet/mfib/mfib_types.h>
 
+/**
+ * Keep a lock per-source and a total
+ */
+#define MFIB_TABLE_N_LOCKS (MFIB_N_SOURCES+1)
+#define MFIB_TABLE_TOTAL_LOCKS MFIB_N_SOURCES
+
 /**
  * @brief
  *   A protocol Independent IP multicast FIB table
@@ -47,7 +53,7 @@ typedef struct mfib_table_t_
     /**
      * number of locks on the table
      */
-    u16 mft_locks;
+    u16 mft_locks[MFIB_TABLE_N_LOCKS];
 
     /**
      * Table ID (hash key) for this FIB.
@@ -259,7 +265,8 @@ extern fib_node_index_t mfib_table_entry_special_add(u32 fib_index,
  *  the source to flush
  */
 extern void mfib_table_flush(u32 fib_index,
-                             fib_protocol_t proto);
+                             fib_protocol_t proto,
+                             mfib_source_t source);
 
 /**
  * @brief
@@ -307,9 +314,13 @@ extern u32 mfib_table_find(fib_protocol_t proto, u32 table_id);
  *
  * @return fib_index
  *  The index of the FIB
+ *
+ * @param source
+ *  The ID of the client/source.
  */
 extern u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto,
-                                              u32 table_id);
+                                              u32 table_id,
+                                              mfib_source_t source);
 
 
 /**
@@ -321,9 +332,13 @@ extern u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto,
  *
  * @paran proto
  *  The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ *  The ID of the client/source.
  */
 extern void mfib_table_unlock(u32 fib_index,
-                              fib_protocol_t proto);
+                              fib_protocol_t proto,
+                              mfib_source_t source);
 
 /**
  * @brief
@@ -335,9 +350,13 @@ extern void mfib_table_unlock(u32 fib_index,
  *
  * @paran proto
  *  The protocol of the FIB (and thus the entries therein)
+ *
+ * @param source
+ *  The ID of the client/source.
  */
 extern void mfib_table_lock(u32 fib_index,
-                            fib_protocol_t proto);
+                            fib_protocol_t proto,
+                            mfib_source_t source);
 
 /**
  * @brief
index 57787ec..3055844 100644 (file)
@@ -22,6 +22,7 @@
 #include <vnet/fib/fib_path_list.h>
 #include <vnet/fib/fib_test.h>
 #include <vnet/fib/fib_table.h>
+#include <vnet/fib/mpls_fib.h>
 
 #include <vnet/dpo/replicate_dpo.h>
 #include <vnet/adj/adj_mcast.h>
@@ -366,7 +367,7 @@ mfib_test_i (fib_protocol_t PROTO,
     MFIB_TEST(3 == adj_mcast_db_size(), "3 MCAST adjs");
 
     /* Find or create FIB table 11 */
-    fib_index = mfib_table_find_or_create_and_lock(PROTO, 11);
+    fib_index = mfib_table_find_or_create_and_lock(PROTO, 11, MFIB_SOURCE_API);
 
     mfib_prefix_t pfx_dft = {
         .fp_len = 0,
@@ -1113,9 +1114,10 @@ mfib_test_i (fib_protocol_t PROTO,
     /*
      * MPLS enable an interface so we get the MPLS table created
      */
+    mpls_table_create(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
     mpls_sw_interface_enable_disable(&mpls_main,
                                      tm->hw[0]->sw_if_index,
-                                     1);
+                                     1, 0);
 
     lfei = fib_table_entry_update_one_path(0, // default MPLS Table
                                            &pfx_3500,
@@ -1192,7 +1194,7 @@ mfib_test_i (fib_protocol_t PROTO,
     /*
      * Unlock the table - it's the last lock so should be gone thereafter
      */
-    mfib_table_unlock(fib_index, PROTO);
+    mfib_table_unlock(fib_index, PROTO, MFIB_SOURCE_API);
 
     MFIB_TEST((FIB_NODE_INDEX_INVALID ==
                mfib_table_find(PROTO, fib_index)),
@@ -1207,7 +1209,8 @@ mfib_test_i (fib_protocol_t PROTO,
      */
     mpls_sw_interface_enable_disable(&mpls_main,
                                      tm->hw[0]->sw_if_index,
-                                     0);
+                                     0, 0);
+    mpls_table_delete(MPLS_FIB_DEFAULT_TABLE_ID, FIB_SOURCE_API);
 
     /*
      * test we've leaked no resources
index 863fad1..50aede0 100644 (file)
@@ -166,9 +166,10 @@ typedef enum mfib_source_t_
     MFIB_SOURCE_VXLAN,
     MFIB_SOURCE_DHCP,
     MFIB_SOURCE_SRv6,
-    MFIB_SOURCE_DEFAULT_ROUTE,
     MFIB_SOURCE_GTPU,
     MFIB_SOURCE_VXLAN_GPE,
+    MFIB_SOURCE_RR,
+    MFIB_SOURCE_DEFAULT_ROUTE,
 } mfib_source_t;
 
 #define MFIB_SOURCE_NAMES {                        \
@@ -178,11 +179,14 @@ typedef enum mfib_source_t_
     [MFIB_SOURCE_DHCP] = "DHCP",                   \
     [MFIB_SOURCE_VXLAN] = "VXLAN",                 \
     [MFIB_SOURCE_SRv6] = "SRv6",                   \
-    [MFIB_SOURCE_DEFAULT_ROUTE] = "Default Route", \
     [MFIB_SOURCE_GTPU] = "GTPU",                   \
     [MFIB_SOURCE_VXLAN_GPE] = "VXLAN-GPE",         \
+    [MFIB_SOURCE_RR] = "Recursive-resolution",     \
+    [MFIB_SOURCE_DEFAULT_ROUTE] = "Default Route", \
 }
 
+#define MFIB_N_SOURCES (MFIB_SOURCE_DEFAULT_ROUTE)
+
 /**
  * \brief Compare two prefixes for equality
  */
index a085aaa..d7c8e7d 100644 (file)
@@ -35,25 +35,33 @@ mpls_sw_interface_is_enabled (u32 sw_if_index)
     return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
 }
 
-void
+int
 mpls_sw_interface_enable_disable (mpls_main_t * mm,
                                   u32 sw_if_index,
-                                  u8 is_enable)
+                                  u8 is_enable,
+                                  u8 is_api)
 {
   fib_node_index_t lfib_index;
 
   vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
 
+  lfib_index = fib_table_find(FIB_PROTOCOL_MPLS,
+                              MPLS_FIB_DEFAULT_TABLE_ID);
+
+  if (~0 == lfib_index)
+       return VNET_API_ERROR_NO_SUCH_FIB;
+
   /*
    * enable/disable only on the 1<->0 transition
    */
   if (is_enable)
     {
       if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
-        return;
+          return (0);
+
+      fib_table_lock(lfib_index, FIB_PROTOCOL_MPLS,
+                     (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
 
-      lfib_index = fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
-                                                    MPLS_FIB_DEFAULT_TABLE_ID);
       vec_validate(mm->fib_index_by_sw_if_index, 0);
       mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
     }
@@ -61,15 +69,17 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm,
     {
       ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
       if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
-        return;
+          return (0);
 
       fib_table_unlock(mm->fib_index_by_sw_if_index[sw_if_index],
-                      FIB_PROTOCOL_MPLS);
+                      FIB_PROTOCOL_MPLS,
+                       (is_api? FIB_SOURCE_API: FIB_SOURCE_CLI));
     }
 
   vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled",
                                sw_if_index, !is_enable, 0, 0);
 
+  return (0);
 }
 
 static clib_error_t *
@@ -101,7 +111,7 @@ mpls_interface_enable_disable (vlib_main_t * vm,
       goto done;
     }
 
-  mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable);
+  mpls_sw_interface_enable_disable(&mpls_main, sw_if_index, enable, 0);
 
  done:
   return error;
index 5021ac2..7bdfd8c 100644 (file)
@@ -536,6 +536,78 @@ VLIB_CLI_COMMAND (mpls_local_label_command, static) = {
   .short_help = "Create/Delete MPL local labels",
 };
 
+clib_error_t *
+vnet_mpls_table_cmd (vlib_main_t * vm,
+                     unformat_input_t * main_input,
+                     vlib_cli_command_t * cmdo)
+{
+  unformat_input_t _line_input, *line_input = &_line_input;
+  clib_error_t *error = NULL;
+  u32 table_id, is_add;
+
+  is_add = 1;
+  table_id = ~0;
+
+  /* Get a line of input. */
+  if (!unformat_user (main_input, unformat_line_input, line_input))
+    return 0;
+
+  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (line_input, "%d", &table_id))
+       ;
+      else if (unformat (line_input, "del"))
+       is_add = 0;
+      else if (unformat (line_input, "add"))
+       is_add = 1;
+      else
+       {
+         error = unformat_parse_error (line_input);
+         goto done;
+       }
+    }
+
+  if (~0 == table_id)
+    {
+      error = clib_error_return (0, "No table id");
+      goto done;
+    }
+  else if (0 == table_id)
+    {
+      error = clib_error_return (0, "Can't change the default table");
+      goto done;
+    }
+  else
+    {
+      if (is_add)
+        {
+          mpls_table_create (table_id, 0);
+        }
+      else
+        {
+          mpls_table_delete (table_id, 0);
+        }
+    }
+
+ done:
+  unformat_free (line_input);
+  return error;
+}
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete MPLS Tables. All
+ * Tables must be explicitly added before that can be used,
+ * Including the default table.
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip6_table_command, static) = {
+  .path = "mpla table",
+  .short_help = "mpls table [add|del] <table-id>",
+  .function = vnet_mpls_table_cmd,
+  .is_mp_safe = 1,
+};
+
 int
 mpls_fib_reset_labels (u32 fib_id)
 {
@@ -546,12 +618,8 @@ mpls_fib_reset_labels (u32 fib_id)
 static clib_error_t *
 mpls_init (vlib_main_t * vm)
 {
-  mpls_main_t * mm = &mpls_main;
   clib_error_t * error;
 
-  mm->vlib_main = vm;
-  mm->vnet_main = vnet_get_main();
-
   if ((error = vlib_call_init_function (vm, ip_main_init)))
     return error;
 
index b0125e6..31cb174 100644 (file)
@@ -56,10 +56,6 @@ typedef struct {
 
   /* IP4 enabled count by software interface */
   u8 * mpls_enabled_by_sw_if_index;
-
-  /* convenience */
-  vlib_main_t * vlib_main;
-  vnet_main_t * vnet_main;
 } mpls_main_t;
 
 extern mpls_main_t mpls_main;
@@ -77,8 +73,6 @@ extern vlib_node_registration_t mpls_midchain_node;
 
 /* Parse mpls protocol as 0xXXXX or protocol name.
    In either host or network byte order. */
-unformat_function_t unformat_mpls_protocol_host_byte_order;
-unformat_function_t unformat_mpls_protocol_net_byte_order;
 unformat_function_t unformat_mpls_label_net_byte_order;
 unformat_function_t unformat_mpls_unicast_label;
 
@@ -86,9 +80,10 @@ unformat_function_t unformat_mpls_unicast_label;
 unformat_function_t unformat_mpls_header;
 unformat_function_t unformat_pg_mpls_header;
 
-void mpls_sw_interface_enable_disable (mpls_main_t * mm,
-                                      u32 sw_if_index,
-                                      u8 is_enable);
+int mpls_sw_interface_enable_disable (mpls_main_t * mm,
+                                      u32 sw_if_index,
+                                      u8 is_enable,
+                                      u8 is_api);
 
 u8 mpls_sw_interface_is_enabled (u32 sw_if_index);
 
@@ -103,4 +98,7 @@ mpls_fib_index_cmp(void * a1, void * a2);
 int
 mpls_label_cmp(void * a1, void * a2);
 
+void mpls_table_create(uint32_t table_id, u8 is_api);
+void mpls_table_delete(uint32_t table_id, u8 is_api);
+
 #endif /* included_vnet_mpls_h */
index a44b1a2..38f5b01 100644 (file)
@@ -58,6 +58,29 @@ _(MPLS_FIB_DUMP, mpls_fib_dump)
 extern void stats_dslock_with_hint (int hint, int tag);
 extern void stats_dsunlock (void);
 
+void
+mpls_table_delete (u32 table_id, u8 is_api)
+{
+  u32 fib_index;
+
+  /*
+   * The MPLS defult table must also be explicitly created via the API.
+   * So in contrast to IP, it gets no special treatment here.
+   *
+   * The API holds only one lock on the table.
+   * i.e. it can be added many times via the API but needs to be
+   * deleted only once.
+   */
+  fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
+
+  if (~0 != fib_index)
+    {
+      fib_table_unlock (fib_index,
+                       FIB_PROTOCOL_MPLS,
+                       (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+    }
+}
+
 void
 vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp)
 {
@@ -68,6 +91,13 @@ vl_api_mpls_table_add_del_t_handler (vl_api_mpls_table_add_del_t * mp)
   vnm = vnet_get_main ();
   vnm->api_errno = 0;
 
+  if (mp->mt_is_add)
+    mpls_table_create (ntohl (mp->mt_table_id), 1);
+  else
+    mpls_table_delete (ntohl (mp->mt_table_id), 1);
+
+  rv = (rv == 0) ? vnm->api_errno : rv;
+
   REPLY_MACRO (VL_API_MPLS_TABLE_ADD_DEL_REPLY);
 }
 
@@ -82,14 +112,7 @@ mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
 
   if (~0 == mpls_fib_index)
     {
-      if (mp->mb_create_table_if_needed)
-       {
-         mpls_fib_index =
-           fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
-                                              ntohl (mp->mb_mpls_table_id));
-       }
-      else
-       return VNET_API_ERROR_NO_SUCH_FIB;
+      return VNET_API_ERROR_NO_SUCH_FIB;
     }
 
   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
@@ -170,7 +193,6 @@ mpls_route_add_del_t_handler (vnet_main_t * vnm,
                            mp->mr_next_hop_sw_if_index,
                            pfx.fp_payload_proto,
                            mp->mr_next_hop_table_id,
-                           mp->mr_create_table_if_needed,
                            mp->mr_is_rpf_id,
                            &fib_index, &next_hop_fib_index);
 
@@ -235,6 +257,32 @@ vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
 }
 
+void
+mpls_table_create (u32 table_id, u8 is_api)
+{
+  u32 fib_index;
+
+  /*
+   * The MPLS defult table must also be explicitly created via the API.
+   * So in contrast to IP, it gets no special treatment here.
+   */
+
+  /*
+   * The API holds only one lock on the table.
+   * i.e. it can be added many times via the API but needs to be
+   * deleted only once.
+   */
+  fib_index = fib_table_find (FIB_PROTOCOL_MPLS, table_id);
+
+  if (~0 == fib_index)
+    {
+      fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
+                                        table_id,
+                                        (is_api ?
+                                         FIB_SOURCE_API : FIB_SOURCE_CLI));
+    }
+}
+
 static void
 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
 {
index f427bbf..2f90993 100755 (executable)
@@ -595,8 +595,10 @@ sr_policy_add (ip6_address_t * bsid, ip6_address_t * segments,
   if (sm->fib_table_ip6 == (u32) ~ 0)
     {
       sm->fib_table_ip6 = fib_table_create_and_lock (FIB_PROTOCOL_IP6,
+                                                    FIB_SOURCE_SR,
                                                     "SRv6 steering of IP6 prefixes through BSIDs");
       sm->fib_table_ip4 = fib_table_create_and_lock (FIB_PROTOCOL_IP6,
+                                                    FIB_SOURCE_SR,
                                                     "SRv6 steering of IP4 prefixes through BSIDs");
     }
 
@@ -684,8 +686,8 @@ sr_policy_del (ip6_address_t * bsid, u32 index)
   /* If FIB empty unlock it */
   if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
     {
-      fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6);
-      fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6);
+      fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
+      fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
       sm->fib_table_ip6 = (u32) ~ 0;
       sm->fib_table_ip4 = (u32) ~ 0;
     }
index 57fe21f..cf4e81a 100755 (executable)
@@ -159,8 +159,10 @@ sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index,
          /* If no more SR policies or steering policies */
          if (!pool_elts (sm->sr_policies) && !pool_elts (sm->steer_policies))
            {
-             fib_table_unlock (sm->fib_table_ip6, FIB_PROTOCOL_IP6);
-             fib_table_unlock (sm->fib_table_ip4, FIB_PROTOCOL_IP6);
+             fib_table_unlock (sm->fib_table_ip6,
+                               FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
+             fib_table_unlock (sm->fib_table_ip4,
+                               FIB_PROTOCOL_IP6, FIB_SOURCE_SR);
              sm->fib_table_ip6 = (u32) ~ 0;
              sm->fib_table_ip4 = (u32) ~ 0;
            }
index f9c3129..044ddb5 100644 (file)
@@ -699,8 +699,9 @@ static void
 
   VALIDATE_SW_IF_INDEX (mp);
 
-  mpls_sw_interface_enable_disable (&mpls_main,
-                                   ntohl (mp->sw_if_index), mp->enable);
+  rv = mpls_sw_interface_enable_disable (&mpls_main,
+                                        ntohl (mp->sw_if_index),
+                                        mp->enable, 1);
 
   BAD_SW_IF_INDEX_LABEL;
   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
index 1353fe2..be74b83 100644 (file)
@@ -560,9 +560,6 @@ static void *vl_api_ip_add_del_route_t_print
   if (mp->table_id != 0)
     s = format (s, "vrf %d ", ntohl (mp->table_id));
 
-  if (mp->create_vrf_if_needed)
-    s = format (s, "create-vrf ");
-
   if (mp->next_hop_weight != 1)
     s = format (s, "weight %d ", mp->next_hop_weight);
 
index 6fc2918..fe97f6c 100644 (file)
@@ -6,7 +6,7 @@ import struct
 
 from framework import VppTestCase, VppTestRunner
 from vpp_neighbor import VppNeighbor
-from vpp_ip_route import find_route
+from vpp_ip_route import find_route, VppIpTable
 from util import mk_ll_addr
 
 from scapy.layers.l2 import Ether, getmacbyip, ARP
@@ -34,9 +34,19 @@ class TestDHCP(VppTestCase):
 
         # create 3 pg interfaces
         self.create_pg_interfaces(range(4))
+        self.tables = []
 
         # pg0 and 1 are IP configured in VRF 0 and 1.
         # pg2 and 3 are non IP-configured in VRF 0 and 1
+        table_id = 0
+        for table_id in range(1, 4):
+            tbl4 = VppIpTable(self, table_id)
+            tbl4.add_vpp_config()
+            self.tables.append(tbl4)
+            tbl6 = VppIpTable(self, table_id, is_ip6=1)
+            tbl6.add_vpp_config()
+            self.tables.append(tbl6)
+
         table_id = 0
         for i in self.pg_interfaces[:2]:
             i.admin_up()
@@ -56,11 +66,15 @@ class TestDHCP(VppTestCase):
             table_id += 1
 
     def tearDown(self):
-        super(TestDHCP, self).tearDown()
-        for i in self.pg_interfaces:
+        for i in self.pg_interfaces[:2]:
             i.unconfig_ip4()
             i.unconfig_ip6()
+
+        for i in self.pg_interfaces:
+            i.set_table_ip4(0)
+            i.set_table_ip6(0)
             i.admin_down()
+        super(TestDHCP, self).tearDown()
 
     def send_and_assert_no_replies(self, intf, pkts, remark):
         intf.add_stream(pkts)
@@ -667,6 +681,8 @@ class TestDHCP(VppTestCase):
                                         "DHCP cleanup VRF 0")
         self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
                                         "DHCP cleanup VRF 1")
+        self.pg2.unconfig_ip4()
+        self.pg3.unconfig_ip4()
 
     def test_dhcp6_proxy(self):
         """ DHCPv6 Proxy"""
@@ -1045,6 +1061,8 @@ class TestDHCP(VppTestCase):
                                     server_table_id=0,
                                     is_ipv6=1,
                                     is_add=0)
+        self.pg2.unconfig_ip6()
+        self.pg3.unconfig_ip6()
 
     def test_dhcp_client(self):
         """ DHCP Client"""
index 1afc44f..9046b05 100644 (file)
@@ -6,7 +6,7 @@ from logging import *
 from framework import VppTestCase, VppTestRunner
 from vpp_sub_interface import VppDot1QSubint
 from vpp_gre_interface import VppGreInterface, VppGre6Interface
-from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
+from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable
 from vpp_papi_provider import L2_VTR_OP
 
 from scapy.packet import Raw
@@ -30,6 +30,9 @@ class TestGRE(VppTestCase):
 
         # create 3 pg interfaces - set one in a non-default table.
         self.create_pg_interfaces(range(3))
+
+        self.tbl = VppIpTable(self, 1)
+        self.tbl.add_vpp_config()
         self.pg1.set_table_ip4(1)
 
         for i in self.pg_interfaces:
@@ -43,11 +46,12 @@ class TestGRE(VppTestCase):
         self.pg2.resolve_ndp()
 
     def tearDown(self):
-        super(TestGRE, self).tearDown()
         for i in self.pg_interfaces:
             i.unconfig_ip4()
             i.unconfig_ip6()
             i.admin_down()
+        self.pg1.set_table_ip4(0)
+        super(TestGRE, self).tearDown()
 
     def create_stream_ip4(self, src_if, src_ip, dst_ip):
         pkts = []
index 7a7098c..55d1673 100644 (file)
@@ -6,7 +6,8 @@ import unittest
 from framework import VppTestCase, VppTestRunner
 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpMRoute, \
-    VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind
+    VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
+    VppMplsTable
 
 from scapy.packet import Raw
 from scapy.layers.l2 import Ether, Dot1Q, ARP
@@ -774,6 +775,8 @@ class TestIPLoadBalance(VppTestCase):
         super(TestIPLoadBalance, self).setUp()
 
         self.create_pg_interfaces(range(5))
+        mpls_tbl = VppMplsTable(self, 0)
+        mpls_tbl.add_vpp_config()
 
         for i in self.pg_interfaces:
             i.admin_up()
@@ -782,11 +785,11 @@ class TestIPLoadBalance(VppTestCase):
             i.enable_mpls()
 
     def tearDown(self):
-        super(TestIPLoadBalance, self).tearDown()
         for i in self.pg_interfaces:
             i.disable_mpls()
             i.unconfig_ip4()
             i.admin_down()
+        super(TestIPLoadBalance, self).tearDown()
 
     def send_and_expect_load_balancing(self, input, pkts, outputs):
         input.add_stream(pkts)
@@ -966,6 +969,8 @@ class TestIPVlan0(VppTestCase):
         super(TestIPVlan0, self).setUp()
 
         self.create_pg_interfaces(range(2))
+        mpls_tbl = VppMplsTable(self, 0)
+        mpls_tbl.add_vpp_config()
 
         for i in self.pg_interfaces:
             i.admin_up()
@@ -974,11 +979,11 @@ class TestIPVlan0(VppTestCase):
             i.enable_mpls()
 
     def tearDown(self):
-        super(TestIPVlan0, self).tearDown()
         for i in self.pg_interfaces:
             i.disable_mpls()
             i.unconfig_ip4()
             i.admin_down()
+        super(TestIPVlan0, self).tearDown()
 
     def send_and_expect(self, input, pkts, output):
         input.add_stream(pkts)
index b73ac94..5a8d676 100644 (file)
@@ -172,9 +172,10 @@ class TestIp4VrfMultiInst(VppTestCase):
             pg_if = self.pg_if_by_vrf_id[vrf_id][0]
             dest_addr = pg_if.remote_hosts[0].ip4n
             dest_addr_len = 24
+            self.vapi.ip_table_add_del(vrf_id, is_add=1)
             self.vapi.ip_add_del_route(
                 dest_addr, dest_addr_len, pg_if.local_ip4n,
-                table_id=vrf_id, create_vrf_if_needed=1, is_multipath=1)
+                table_id=vrf_id, is_multipath=1)
             self.logger.info("IPv4 VRF ID %d created" % vrf_id)
             if vrf_id not in self.vrf_list:
                 self.vrf_list.append(vrf_id)
@@ -216,6 +217,7 @@ class TestIp4VrfMultiInst(VppTestCase):
         self.logger.info("IPv4 VRF ID %d reset" % vrf_id)
         self.logger.debug(self.vapi.ppcli("show ip fib"))
         self.logger.debug(self.vapi.ppcli("show ip arp"))
+        self.vapi.ip_table_add_del(vrf_id, is_add=0)
 
     def create_stream(self, src_if, packet_sizes):
         """
index 285ce18..aad3713 100644 (file)
@@ -8,7 +8,7 @@ from vpp_sub_interface import VppSubInterface, VppDot1QSubint
 from vpp_pg_interface import is_ipv6_misc
 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, VppIpMRoute, \
     VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \
-    VppMplsRoute, DpoProto
+    VppMplsRoute, DpoProto, VppMplsTable
 from vpp_neighbor import find_nbr, VppNeighbor
 
 from scapy.packet import Raw
@@ -1260,6 +1260,9 @@ class TestIP6LoadBalance(VppTestCase):
 
         self.create_pg_interfaces(range(5))
 
+        mpls_tbl = VppMplsTable(self, 0)
+        mpls_tbl.add_vpp_config()
+
         for i in self.pg_interfaces:
             i.admin_up()
             i.config_ip6()
@@ -1267,11 +1270,11 @@ class TestIP6LoadBalance(VppTestCase):
             i.enable_mpls()
 
     def tearDown(self):
-        super(TestIP6LoadBalance, self).tearDown()
         for i in self.pg_interfaces:
             i.unconfig_ip6()
             i.admin_down()
             i.disable_mpls()
+        super(TestIP6LoadBalance, self).tearDown()
 
     def send_and_expect_load_balancing(self, input, pkts, outputs):
         input.add_stream(pkts)
index af80b5b..769cb2e 100644 (file)
@@ -187,9 +187,10 @@ class TestIP6VrfMultiInst(VppTestCase):
             pg_if = self.pg_if_by_vrf_id[vrf_id][0]
             dest_addr = pg_if.remote_hosts[0].ip6n
             dest_addr_len = 64
+            self.vapi.ip_table_add_del(vrf_id, is_add=1, is_ipv6=1)
             self.vapi.ip_add_del_route(
                 dest_addr, dest_addr_len, pg_if.local_ip6n, is_ipv6=1,
-                table_id=vrf_id, create_vrf_if_needed=1, is_multipath=1)
+                table_id=vrf_id, is_multipath=1)
             self.logger.info("IPv6 VRF ID %d created" % vrf_id)
             if vrf_id not in self.vrf_list:
                 self.vrf_list.append(vrf_id)
@@ -232,6 +233,7 @@ class TestIP6VrfMultiInst(VppTestCase):
         self.logger.info("IPv6 VRF ID %d reset" % vrf_id)
         self.logger.debug(self.vapi.ppcli("show ip6 fib"))
         self.logger.debug(self.vapi.ppcli("show ip6 neighbors"))
+        self.vapi.ip_table_add_del(vrf_id, is_add=0, is_ipv6=1)
 
     def create_stream(self, src_if, packet_sizes):
         """
index 276555d..7cad683 100644 (file)
@@ -5,7 +5,7 @@ import unittest
 from framework import VppTestCase, VppTestRunner
 from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
 from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \
-    MRouteItfFlags, MRouteEntryFlags
+    MRouteItfFlags, MRouteEntryFlags, VppIpTable
 
 from scapy.packet import Raw
 from scapy.layers.l2 import Ether
@@ -44,16 +44,37 @@ class TestIPMcast(VppTestCase):
         super(TestIPMcast, self).setUp()
 
         # create 8 pg interfaces
-        self.create_pg_interfaces(range(8))
+        self.create_pg_interfaces(range(9))
 
         # setup interfaces
-        for i in self.pg_interfaces:
+        for i in self.pg_interfaces[:8]:
             i.admin_up()
             i.config_ip4()
             i.config_ip6()
             i.resolve_arp()
             i.resolve_ndp()
 
+        # one more in a vrf
+        tbl4 = VppIpTable(self, 10)
+        tbl4.add_vpp_config()
+        self.pg8.set_table_ip4(10)
+        self.pg8.config_ip4()
+
+        tbl6 = VppIpTable(self, 10, is_ip6=1)
+        tbl6.add_vpp_config()
+        self.pg8.set_table_ip6(10)
+        self.pg8.config_ip6()
+
+    def tearDown(self):
+        for i in self.pg_interfaces:
+            i.unconfig_ip4()
+            i.unconfig_ip6()
+            i.admin_down()
+
+        self.pg8.set_table_ip4(0)
+        self.pg8.set_table_ip6(0)
+        super(TestIPMcast, self).tearDown()
+
     def create_stream_ip4(self, src_if, src_ip, dst_ip, payload_size=0):
         pkts = []
         # default to small packet sizes
@@ -663,6 +684,77 @@ class TestIPMcast(VppTestCase):
         #
         route_232_1_1_1.remove_vpp_config()
 
+    def test_ip_mcast_vrf(self):
+        """ IP Multicast Replication in non-default table"""
+
+        #
+        # An (S,G).
+        # one accepting interface, pg0, 2 forwarding interfaces
+        #
+        route_1_1_1_1_232_1_1_1 = VppIpMRoute(
+            self,
+            "1.1.1.1",
+            "232.1.1.1", 64,
+            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
+            [VppMRoutePath(self.pg8.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
+             VppMRoutePath(self.pg1.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
+             VppMRoutePath(self.pg2.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
+            table_id=10)
+        route_1_1_1_1_232_1_1_1.add_vpp_config()
+
+        #
+        # a stream that matches the route for (1.1.1.1,232.1.1.1)
+        #  small packets
+        #
+        self.vapi.cli("clear trace")
+        tx = self.create_stream_ip4(self.pg8, "1.1.1.1", "232.1.1.1")
+        self.pg8.add_stream(tx)
+
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+
+        # We expect replications on Pg1 & 2
+        self.verify_capture_ip4(self.pg1, tx)
+        self.verify_capture_ip4(self.pg2, tx)
+
+    def test_ip6_mcast_vrf(self):
+        """ IPv6 Multicast Replication in non-default table"""
+
+        #
+        # An (S,G).
+        # one accepting interface, pg0, 2 forwarding interfaces
+        #
+        route_2001_ff01_1 = VppIpMRoute(
+            self,
+            "2001::1",
+            "ff01::1", 256,
+            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE,
+            [VppMRoutePath(self.pg8.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
+             VppMRoutePath(self.pg1.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_FORWARD),
+             VppMRoutePath(self.pg2.sw_if_index,
+                           MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)],
+            table_id=10,
+            is_ip6=1)
+        route_2001_ff01_1.add_vpp_config()
+
+        #
+        # a stream that matches the route for (2001::1, ff00::1)
+        #
+        self.vapi.cli("clear trace")
+        tx = self.create_stream_ip6(self.pg8, "2001::1", "ff01::1")
+        self.pg8.add_stream(tx)
+
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+
+        # We expect replications on Pg1, 2,
+        self.verify_capture_ip6(self.pg1, tx)
+        self.verify_capture_ip6(self.pg2, tx)
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index b2226a7..460a32d 100644 (file)
@@ -6,7 +6,7 @@ import socket
 from framework import VppTestCase, VppTestRunner
 from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \
     VppMplsIpBind, VppIpMRoute, VppMRoutePath, \
-    MRouteItfFlags, MRouteEntryFlags, DpoProto
+    MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable
 from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface
 
 from scapy.packet import Raw
@@ -60,9 +60,23 @@ class TestMPLS(VppTestCase):
         # setup both interfaces
         # assign them different tables.
         table_id = 0
+        self.tables = []
+
+        tbl = VppMplsTable(self, 0)
+        tbl.add_vpp_config()
+        self.tables.append(tbl)
 
         for i in self.pg_interfaces:
             i.admin_up()
+
+            if table_id != 0:
+                tbl = VppIpTable(self, table_id)
+                tbl.add_vpp_config()
+                self.tables.append(tbl)
+                tbl = VppIpTable(self, table_id, is_ip6=1)
+                tbl.add_vpp_config()
+                self.tables.append(tbl)
+
             i.set_table_ip4(table_id)
             i.set_table_ip6(table_id)
             i.config_ip4()
@@ -73,12 +87,15 @@ class TestMPLS(VppTestCase):
             table_id += 1
 
     def tearDown(self):
-        super(TestMPLS, self).tearDown()
         for i in self.pg_interfaces:
             i.unconfig_ip4()
             i.unconfig_ip6()
             i.ip6_disable()
+            i.set_table_ip4(0)
+            i.set_table_ip6(0)
+            i.disable_mpls()
             i.admin_down()
+        super(TestMPLS, self).tearDown()
 
     # the default of 64 matches the IP packet TTL default
     def create_stream_labelled_ip4(
@@ -1092,6 +1109,9 @@ class TestMPLSDisabled(VppTestCase):
         # create 2 pg interfaces
         self.create_pg_interfaces(range(2))
 
+        self.tbl = VppMplsTable(self, 0)
+        self.tbl.add_vpp_config()
+
         # PG0 is MPLS enalbed
         self.pg0.admin_up()
         self.pg0.config_ip4()
@@ -1102,11 +1122,13 @@ class TestMPLSDisabled(VppTestCase):
         self.pg1.admin_up()
 
     def tearDown(self):
-        super(TestMPLSDisabled, self).tearDown()
         for i in self.pg_interfaces:
             i.unconfig_ip4()
             i.admin_down()
 
+        self.pg0.disable_mpls()
+        super(TestMPLSDisabled, self).tearDown()
+
     def send_and_assert_no_replies(self, intf, pkts, remark):
         intf.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -1174,6 +1196,13 @@ class TestMPLSPIC(VppTestCase):
         # create 2 pg interfaces
         self.create_pg_interfaces(range(4))
 
+        mpls_tbl = VppMplsTable(self, 0)
+        mpls_tbl.add_vpp_config()
+        tbl4 = VppIpTable(self, 1)
+        tbl4.add_vpp_config()
+        tbl6 = VppIpTable(self, 1, is_ip6=1)
+        tbl6.add_vpp_config()
+
         # core links
         self.pg0.admin_up()
         self.pg0.config_ip4()
@@ -1201,14 +1230,15 @@ class TestMPLSPIC(VppTestCase):
         self.pg3.resolve_ndp()
 
     def tearDown(self):
-        super(TestMPLSPIC, self).tearDown()
         self.pg0.disable_mpls()
+        self.pg1.disable_mpls()
         for i in self.pg_interfaces:
             i.unconfig_ip4()
             i.unconfig_ip6()
             i.set_table_ip4(0)
             i.set_table_ip6(0)
             i.admin_down()
+        super(TestMPLSPIC, self).tearDown()
 
     def test_mpls_ibgp_pic(self):
         """ MPLS iBGP PIC edge convergence
@@ -1534,24 +1564,30 @@ class TestMPLSL2(VppTestCase):
         # create 2 pg interfaces
         self.create_pg_interfaces(range(2))
 
+        # create the default MPLS table
+        self.tables = []
+        tbl = VppMplsTable(self, 0)
+        tbl.add_vpp_config()
+        self.tables.append(tbl)
+
         # use pg0 as the core facing interface
         self.pg0.admin_up()
         self.pg0.config_ip4()
         self.pg0.resolve_arp()
         self.pg0.enable_mpls()
 
-        # use the other 2 for customer facg L2 links
+        # use the other 2 for customer facing L2 links
         for i in self.pg_interfaces[1:]:
             i.admin_up()
 
     def tearDown(self):
-        super(TestMPLSL2, self).tearDown()
         for i in self.pg_interfaces[1:]:
             i.admin_down()
 
         self.pg0.disable_mpls()
         self.pg0.unconfig_ip4()
         self.pg0.admin_down()
+        super(TestMPLSL2, self).tearDown()
 
     def verify_capture_tunneled_ethernet(self, capture, sent, mpls_labels,
                                          ttl=255, top=None):
index 1f2d17a..73e9e21 100644 (file)
@@ -549,6 +549,8 @@ class TestNAT44(MethodHolder):
             cls.pg0.configure_ipv4_neighbors()
 
             cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
+            cls.vapi.ip_table_add_del(10, is_add=1)
+            cls.vapi.ip_table_add_del(20, is_add=1)
 
             cls.pg4._local_ip4 = "172.16.255.1"
             cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
@@ -1797,6 +1799,8 @@ class TestNAT44(MethodHolder):
 
         self.pg0.unconfig_ip4()
         self.pg1.unconfig_ip4()
+        self.vapi.ip_table_add_del(vrf_id1, is_add=1)
+        self.vapi.ip_table_add_del(vrf_id2, is_add=1)
         self.pg0.set_table_ip4(vrf_id1)
         self.pg1.set_table_ip4(vrf_id2)
         self.pg0.config_ip4()
@@ -1825,6 +1829,13 @@ class TestNAT44(MethodHolder):
         capture = self.pg2.get_capture(len(pkts))
         self.verify_capture_out(capture, nat_ip2)
 
+        self.pg0.unconfig_ip4()
+        self.pg1.unconfig_ip4()
+        self.pg0.set_table_ip4(0)
+        self.pg1.set_table_ip4(0)
+        self.vapi.ip_table_add_del(vrf_id1, is_add=0)
+        self.vapi.ip_table_add_del(vrf_id2, is_add=0)
+
     def test_vrf_feature_independent(self):
         """ NAT44 tenant VRF independent address pool mode """
 
@@ -3042,6 +3053,8 @@ class TestNAT64(MethodHolder):
             cls.ip6_interfaces.append(cls.pg_interfaces[2])
             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
 
+            cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
+
             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
 
             cls.pg0.generate_remote_hosts(2)
index 1c7cc26..68dde2f 100644 (file)
@@ -5,7 +5,8 @@ from socket import AF_INET, AF_INET6, inet_pton
 
 from framework import VppTestCase, VppTestRunner
 from vpp_neighbor import VppNeighbor, find_nbr
-from vpp_ip_route import VppIpRoute, VppRoutePath, find_route
+from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
+    VppIpTable
 
 from scapy.packet import Raw
 from scapy.layers.l2 import Ether, ARP, Dot1Q
@@ -39,11 +40,13 @@ class ARPTestCase(VppTestCase):
         self.pg1.config_ip6()
 
         # pg3 in a different VRF
+        self.tbl = VppIpTable(self, 1)
+        self.tbl.add_vpp_config()
+
         self.pg3.set_table_ip4(1)
         self.pg3.config_ip4()
 
     def tearDown(self):
-        super(ARPTestCase, self).tearDown()
         self.pg0.unconfig_ip4()
         self.pg0.unconfig_ip6()
 
@@ -51,10 +54,13 @@ class ARPTestCase(VppTestCase):
         self.pg1.unconfig_ip6()
 
         self.pg3.unconfig_ip4()
+        self.pg3.set_table_ip4(0)
 
         for i in self.pg_interfaces:
             i.admin_down()
 
+        super(ARPTestCase, self).tearDown()
+
     def verify_arp_req(self, rx, smac, sip, dip):
         ether = rx[Ether]
         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
@@ -1080,6 +1086,62 @@ class ARPTestCase(VppTestCase):
                        self.pg0.remote_ip4,
                        self.pg1.remote_hosts[1].ip4)
 
+    def test_arp_static(self):
+        """ ARP Static"""
+        self.pg2.generate_remote_hosts(3)
+
+        #
+        # Add a static ARP entry
+        #
+        static_arp = VppNeighbor(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[1].mac,
+                                 self.pg2.remote_hosts[1].ip4,
+                                 is_static=1)
+        static_arp.add_vpp_config()
+
+        #
+        # Add the connected prefix to the interface
+        #
+        self.pg2.config_ip4()
+
+        #
+        # We should now find the adj-fib
+        #
+        self.assertTrue(find_nbr(self,
+                                 self.pg2.sw_if_index,
+                                 self.pg2.remote_hosts[1].ip4,
+                                 is_static=1))
+        self.assertTrue(find_route(self,
+                                   self.pg2.remote_hosts[1].ip4,
+                                   32))
+
+        #
+        # remove the connected
+        #
+        self.pg2.unconfig_ip4()
+
+        #
+        # put the interface into table 1
+        #
+        self.pg2.set_table_ip4(1)
+
+        #
+        # configure the same connected and expect to find the
+        # adj fib in the new table
+        #
+        self.pg2.config_ip4()
+        self.assertTrue(find_route(self,
+                                   self.pg2.remote_hosts[1].ip4,
+                                   32,
+                                   table_id=1))
+
+        #
+        # clean-up
+        #
+        self.pg2.unconfig_ip4()
+        self.pg2.set_table_ip4(0)
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index 2c489e3..b799379 100644 (file)
@@ -54,6 +54,46 @@ def find_route(test, ip_addr, len, table_id=0, inet=AF_INET):
     return False
 
 
+class VppIpTable(VppObject):
+
+    def __init__(self,
+                 test,
+                 table_id,
+                 is_ip6=0):
+        self._test = test
+        self.table_id = table_id
+        self.is_ip6 = is_ip6
+
+    def add_vpp_config(self):
+        self._test.vapi.ip_table_add_del(
+            self.table_id,
+            is_ipv6=self.is_ip6,
+            is_add=1)
+        self._test.registry.register(self, self._test.logger)
+
+    def remove_vpp_config(self):
+        self._test.vapi.ip_table_add_del(
+            self.table_id,
+            is_ipv6=self.is_ip6,
+            is_add=0)
+
+    def query_vpp_config(self):
+        # find the default route
+        return find_route(self._test,
+                          "::" if self.is_ip6 else "0.0.0.0",
+                          0,
+                          self.table_id,
+                          inet=AF_INET6 if self.is_ip6 == 1 else AF_INET)
+
+    def __str__(self):
+        return self.object_id()
+
+    def object_id(self):
+        return ("table-%s-%d" %
+                ("v6" if self.is_ip6 == 1 else "v4",
+                 self.table_id))
+
+
 class VppRoutePath(object):
 
     def __init__(
@@ -391,6 +431,39 @@ class VppMplsIpBind(VppObject):
                    self.dest_addr_len))
 
 
+class VppMplsTable(VppObject):
+
+    def __init__(self,
+                 test,
+                 table_id):
+        self._test = test
+        self.table_id = table_id
+
+    def add_vpp_config(self):
+        self._test.vapi.mpls_table_add_del(
+            self.table_id,
+            is_add=1)
+        self._test.registry.register(self, self._test.logger)
+
+    def remove_vpp_config(self):
+        self._test.vapi.mpls_table_add_del(
+            self.table_id,
+            is_add=0)
+
+    def query_vpp_config(self):
+        # find the default route
+        dump = self._test.vapi.mpls_fib_dump()
+        if len(dump):
+            return True
+        return False
+
+    def __str__(self):
+        return self.object_id()
+
+    def object_id(self):
+        return ("table-mpls-%d" % (self.table_id))
+
+
 class VppMplsRoute(VppObject):
     """
     MPLS Route/LSP
index b70da02..519aff8 100644 (file)
@@ -652,6 +652,24 @@ class VppPapiProvider(object):
         return self.api(self.papi.delete_loopback,
                         {'sw_if_index': sw_if_index, })
 
+    def ip_table_add_del(self,
+                         table_id,
+                         is_add=1,
+                         is_ipv6=0):
+        """
+
+        :param table_id
+        :param is_add:  (Default value = 1)
+        :param is_ipv6:  (Default value = 0)
+
+        """
+
+        return self.api(
+            self.papi.ip_table_add_del,
+            {'table_id': table_id,
+             'is_add': is_add,
+             'is_ipv6': is_ipv6})
+
     def ip_add_del_route(
             self,
             dst_address,
@@ -664,7 +682,6 @@ class VppPapiProvider(object):
             next_hop_n_out_labels=0,
             next_hop_out_label_stack=[],
             next_hop_via_label=MPLS_LABEL_INVALID,
-            create_vrf_if_needed=0,
             is_resolve_host=0,
             is_resolve_attached=0,
             classify_table_index=0xFFFFFFFF,
@@ -687,7 +704,6 @@ class VppPapiProvider(object):
         :param vrf_id:  (Default value = 0)
         :param lookup_in_vrf:  (Default value = 0)
         :param classify_table_index:  (Default value = 0xFFFFFFFF)
-        :param create_vrf_if_needed:  (Default value = 0)
         :param is_add:  (Default value = 1)
         :param is_drop:  (Default value = 0)
         :param is_ipv6:  (Default value = 0)
@@ -707,7 +723,6 @@ class VppPapiProvider(object):
              'table_id': table_id,
              'classify_table_index': classify_table_index,
              'next_hop_table_id': next_hop_table_id,
-             'create_vrf_if_needed': create_vrf_if_needed,
              'is_add': is_add,
              'is_drop': is_drop,
              'is_unreach': is_unreach,
@@ -912,6 +927,22 @@ class VppPapiProvider(object):
     def mpls_fib_dump(self):
         return self.api(self.papi.mpls_fib_dump, {})
 
+    def mpls_table_add_del(
+            self,
+            table_id,
+            is_add=1):
+        """
+
+        :param table_id
+        :param is_add:  (Default value = 1)
+
+        """
+
+        return self.api(
+            self.papi.mpls_table_add_del,
+            {'mt_table_id': table_id,
+             'mt_is_add': is_add})
+
     def mpls_route_add_del(
             self,
             label,
@@ -925,7 +956,6 @@ class VppPapiProvider(object):
             next_hop_n_out_labels=0,
             next_hop_out_label_stack=[],
             next_hop_via_label=MPLS_LABEL_INVALID,
-            create_vrf_if_needed=0,
             is_resolve_host=0,
             is_resolve_attached=0,
             is_interface_rx=0,
@@ -947,7 +977,6 @@ class VppPapiProvider(object):
         :param vrf_id:  (Default value = 0)
         :param lookup_in_vrf:  (Default value = 0)
         :param classify_table_index:  (Default value = 0xFFFFFFFF)
-        :param create_vrf_if_needed:  (Default value = 0)
         :param is_add:  (Default value = 1)
         :param is_drop:  (Default value = 0)
         :param is_ipv6:  (Default value = 0)
@@ -968,7 +997,6 @@ class VppPapiProvider(object):
              'mr_eos': eos,
              'mr_table_id': table_id,
              'mr_classify_table_index': classify_table_index,
-             'mr_create_table_if_needed': create_vrf_if_needed,
              'mr_is_add': is_add,
              'mr_is_classify': is_classify,
              'mr_is_multipath': is_multipath,
@@ -994,7 +1022,6 @@ class VppPapiProvider(object):
             table_id=0,
             ip_table_id=0,
             is_ip4=1,
-            create_vrf_if_needed=0,
             is_bind=1):
         """
         """
@@ -1003,7 +1030,6 @@ class VppPapiProvider(object):
             {'mb_mpls_table_id': table_id,
              'mb_label': label,
              'mb_ip_table_id': ip_table_id,
-             'mb_create_table_if_needed': create_vrf_if_needed,
              'mb_is_bind': is_bind,
              'mb_is_ip4': is_ip4,
              'mb_address_length': dst_address_length,
@@ -1020,7 +1046,6 @@ class VppPapiProvider(object):
             next_hop_n_out_labels=0,
             next_hop_out_label_stack=[],
             next_hop_via_label=MPLS_LABEL_INVALID,
-            create_vrf_if_needed=0,
             is_add=1,
             l2_only=0,
             is_multicast=0):
@@ -1034,7 +1059,6 @@ class VppPapiProvider(object):
         :param vrf_id:  (Default value = 0)
         :param lookup_in_vrf:  (Default value = 0)
         :param classify_table_index:  (Default value = 0xFFFFFFFF)
-        :param create_vrf_if_needed:  (Default value = 0)
         :param is_add:  (Default value = 1)
         :param is_drop:  (Default value = 0)
         :param is_ipv6:  (Default value = 0)
@@ -1844,7 +1868,6 @@ class VppPapiProvider(object):
                           i_flags,
                           rpf_id=0,
                           table_id=0,
-                          create_vrf_if_needed=0,
                           is_add=1,
                           is_ipv6=0,
                           is_local=0):
@@ -1857,7 +1880,6 @@ class VppPapiProvider(object):
              'itf_flags': i_flags,
              'table_id': table_id,
              'rpf_id': rpf_id,
-             'create_vrf_if_needed': create_vrf_if_needed,
              'is_add': is_add,
              'is_ipv6': is_ipv6,
              'is_local': is_local,