Distributed Virtual Router Support
[vpp.git] / src / vnet / ip / ip_api.c
index bba65ab..c34ec57 100644 (file)
@@ -180,7 +180,8 @@ copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg)
 static void
 send_ip_fib_details (vpe_api_main_t * am,
                     unix_shared_memory_queue_t * q,
-                    u32 table_id, fib_prefix_t * pfx,
+                    const fib_table_t * table,
+                    const fib_prefix_t * pfx,
                     fib_route_path_encode_t * api_rpaths, u32 context)
 {
   vl_api_ip_fib_details_t *mp;
@@ -196,7 +197,9 @@ send_ip_fib_details (vpe_api_main_t * am,
   mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
   mp->context = context;
 
-  mp->table_id = htonl (table_id);
+  mp->table_id = htonl (table->ft_table_id);
+  memcpy (mp->table_name, table->ft_desc,
+         clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
   mp->address_length = pfx->fp_len;
   memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
 
@@ -295,9 +298,7 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
     fib_table = fib_table_get (fib_index, pfx.fp_proto);
     api_rpaths = NULL;
     fib_entry_encode (*lfeip, &api_rpaths);
-    send_ip_fib_details (am, q,
-                        fib_table->ft_table_id, &pfx, api_rpaths,
-                        mp->context);
+    send_ip_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context);
     vec_free (api_rpaths);
   }
 
@@ -699,12 +700,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, mp->name);
+    }
+  else
+    {
+      ip_table_delete (fproto, table_id, 1);
+    }
+
   REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
 }
 
@@ -722,6 +769,7 @@ add_del_route_t_handler (u8 is_multipath,
                         u8 is_resolve_attached,
                         u8 is_interface_rx,
                         u8 is_rpf_id,
+                        u8 is_l2_bridged,
                         u32 fib_index,
                         const fib_prefix_t * prefix,
                         dpo_proto_t next_hop_proto,
@@ -747,12 +795,20 @@ add_del_route_t_handler (u8 is_multipath,
   fib_route_path_t *paths = NULL;
   fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
 
-  if (MPLS_LABEL_INVALID != next_hop_via_label)
+  /*
+   * the special INVALID label meams we are not recursing via a
+   * label. Exp-null value is never a valid via-label so that
+   * also means it's not a via-label and means clients that set
+   * it to 0 by default get the expected behaviour
+   */
+  if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label))
     {
       path.frp_proto = DPO_PROTO_MPLS;
       path.frp_local_label = next_hop_via_label;
       path.frp_eos = MPLS_NON_EOS;
     }
+  if (is_l2_bridged)
+    path.frp_proto = DPO_PROTO_ETHERNET;
   if (is_resolve_host)
     path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
   if (is_resolve_attached)
@@ -866,18 +922,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 +977,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 +1009,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);
@@ -986,6 +1046,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
                                   mp->classify_table_index,
                                   mp->is_resolve_host,
                                   mp->is_resolve_attached, 0, 0,
+                                  mp->is_l2_bridged,
                                   fib_index, &pfx, DPO_PROTO_IP4,
                                   &nh,
                                   ntohl (mp->next_hop_sw_if_index),
@@ -1008,8 +1069,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);
@@ -1046,6 +1106,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
                                   mp->classify_table_index,
                                   mp->is_resolve_host,
                                   mp->is_resolve_attached, 0, 0,
+                                  mp->is_l2_bridged,
                                   fib_index, &pfx, DPO_PROTO_IP6,
                                   &nh, ntohl (mp->next_hop_sw_if_index),
                                   next_hop_fib_index,
@@ -1074,27 +1135,58 @@ 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, const u8 * name)
+{
+  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_w_name (fproto, table_id,
+                                                   (is_api ?
+                                                    FIB_SOURCE_API :
+                                                    FIB_SOURCE_CLI), name);
+       }
+      if (~0 == mfib_index)
+       {
+         mfib_table_find_or_create_and_lock_w_name (fproto, table_id,
+                                                    (is_api ?
+                                                     MFIB_SOURCE_API :
+                                                     MFIB_SOURCE_CLI), name);
+       }
+    }
+}
+
 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 +1255,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);