ip: add support for buffer offload metadata in ip midchain
[vpp.git] / src / vnet / ip / ip6_link.c
index b73fbe2..c2a7cca 100644 (file)
@@ -146,7 +146,7 @@ ip6_link_is_enabled (u32 sw_if_index)
 
 
 int
-ip6_link_enable (u32 sw_if_index)
+ip6_link_enable (u32 sw_if_index, const ip6_address_t * link_local_addr)
 {
   ip6_link_t *il;
   int rv;
@@ -155,41 +155,38 @@ ip6_link_enable (u32 sw_if_index)
 
   if (NULL == il)
     {
-      const vnet_sw_interface_t *sw, *sw_sup;
+      const vnet_sw_interface_t *sw_sup;
       const ethernet_interface_t *eth;
       vnet_main_t *vnm;
 
+      eth = NULL;
       vnm = vnet_get_main ();
 
       IP6_LINK_INFO ("enable: %U",
                     format_vnet_sw_if_index_name, vnm, sw_if_index);
 
       sw_sup = vnet_get_sup_sw_interface (vnm, sw_if_index);
-      if (sw_sup->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
-       {
-         rv = VNET_API_ERROR_UNSUPPORTED;
-         goto out;
-       }
-
-      eth = ethernet_get_interface (&ethernet_main, sw_sup->hw_if_index);
-
-      if (NULL == eth)
-       {
-         rv = VNET_API_ERROR_UNSUPPORTED;
-         goto out;
-       }
-
       vec_validate (ip6_links, sw_if_index);
 
       il = &ip6_links[sw_if_index];
-      il->il_locks = 1;
+      il->il_locks = 0;
       il->il_sw_if_index = sw_if_index;
+      il->il_mcast_adj = ADJ_INDEX_INVALID;
+
+      if (sw_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
+       eth = ethernet_get_interface (&ethernet_main, sw_sup->hw_if_index);
+
+      /* use a user provided LL address if given */
+      if (NULL != link_local_addr)
+       ip6_address_copy (&il->il_ll_addr, link_local_addr);
 
-      sw = vnet_get_sup_sw_interface (vnm, sw_if_index);
+      /* generate from ethernet MAC */
+      if (ip6_address_is_zero (&il->il_ll_addr) && NULL != eth)
+       ip6_link_local_address_from_mac (&il->il_ll_addr,
+                                        eth->address.mac.bytes);
 
-      if (sw->type == VNET_SW_INTERFACE_TYPE_SUB ||
-         sw->type == VNET_SW_INTERFACE_TYPE_PIPE ||
-         sw->type == VNET_SW_INTERFACE_TYPE_P2P)
+      /* choose a random address */
+      if (ip6_address_is_zero (&il->il_ll_addr))
        {
          il->il_ll_addr.as_u64[0] =
            clib_host_to_net_u64 (0xFE80000000000000ULL);
@@ -200,10 +197,6 @@ ip6_link_enable (u32 sw_if_index)
          /* clear u bit */
          il->il_ll_addr.as_u8[8] &= 0xfd;
        }
-      else
-       {
-         ip6_link_local_address_from_mac (&il->il_ll_addr, eth->address);
-       }
 
       {
        ip6_ll_prefix_t ilp = {
@@ -218,8 +211,11 @@ ip6_link_enable (u32 sw_if_index)
       ip6_mfib_interface_enable_disable (sw_if_index, 1);
       ip6_sw_interface_enable_disable (sw_if_index, 1);
 
-      il->il_mcast_adj = adj_mcast_add_or_lock (FIB_PROTOCOL_IP6,
-                                               VNET_LINK_IP6, sw_if_index);
+      /* only ehternet interfaces support MLD and RA, which use the mcast adj
+       */
+      if (NULL != eth)
+       il->il_mcast_adj =
+         adj_mcast_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6, sw_if_index);
 
       /* inform all register clients */
       ip6_link_delegate_id_t id;
@@ -236,7 +232,8 @@ ip6_link_enable (u32 sw_if_index)
       rv = VNET_API_ERROR_VALUE_EXIST;
     }
 
-out:
+  il->il_locks++;
+
   return (rv);
 }
 
@@ -245,14 +242,10 @@ ip6_link_delegate_flush (ip6_link_t * il)
 {
   ip6_link_delegate_t *ild;
 
-  /* *INDET-OFF* */
-  FOREACH_IP6_LINK_DELEGATE (ild, il, (
-                                       {
-                                       il_delegate_vfts[ild->
-                                                        ild_type].ildv_disable
-                                       (ild->ild_index);
-                                       }));
-  /* *INDET-ON* */
+  FOREACH_IP6_LINK_DELEGATE (ild, il,
+  ({
+    il_delegate_vfts[ild->ild_type].ildv_disable(ild->ild_index);
+  }));
 
   vec_free (il->il_delegates);
   il->il_delegates = NULL;
@@ -316,9 +309,10 @@ ip6_get_link_local_address (u32 sw_if_index)
 {
   const ip6_link_t *il;
 
-  vec_validate (ip6_links, sw_if_index);
+  il = ip6_link_get (sw_if_index);
 
-  il = &ip6_links[sw_if_index];
+  if (NULL == il)
+    return (NULL);
 
   return (&il->il_ll_addr);
 }
@@ -328,48 +322,16 @@ ip6_link_get_mcast_adj (u32 sw_if_index)
 {
   const ip6_link_t *il;
 
-  il = &ip6_links[sw_if_index];
-
-  return (il->il_mcast_adj);
-}
-
-int
-ip6_src_address_for_packet (u32 sw_if_index,
-                           const ip6_address_t * dst, ip6_address_t * src)
-{
-  ip_lookup_main_t *lm;
-
-  lm = &ip6_main.lookup_main;
-
-  if (ip6_address_is_link_local_unicast (dst))
-    {
-      ip6_address_copy (src, ip6_get_link_local_address (sw_if_index));
-
-      return (!0);
-    }
-  else
-    {
-      u32 if_add_index =
-       lm->if_address_pool_index_by_sw_if_index[sw_if_index];
-      if (PREDICT_TRUE (if_add_index != ~0))
-       {
-         ip_interface_address_t *if_add =
-           pool_elt_at_index (lm->if_address_pool, if_add_index);
-         ip6_address_t *if_ip =
-           ip_interface_address_get_address (lm, if_add);
-         *src = *if_ip;
-         return (!0);
-       }
-    }
+  il = ip6_link_get (sw_if_index);
 
-  src->as_u64[0] = 0;
-  src->as_u64[1] = 0;
+  if (NULL == il)
+    return (INDEX_INVALID);
 
-  return (0);
+  return (il->il_mcast_adj);
 }
 
 int
-ip6_set_link_local_address (u32 sw_if_index, const ip6_address_t * address)
+ip6_link_set_local_address (u32 sw_if_index, const ip6_address_t * address)
 {
   ip6_link_delegate_t *ild;
   ip6_link_t *il;
@@ -377,7 +339,7 @@ ip6_set_link_local_address (u32 sw_if_index, const ip6_address_t * address)
   il = ip6_link_get (sw_if_index);
 
   if (NULL == il)
-    return (VNET_API_ERROR_IP6_NOT_ENABLED);
+    return ip6_link_enable (sw_if_index, address);
 
   ip6_ll_prefix_t ilp = {
     .ilp_addr = il->il_ll_addr,
@@ -393,14 +355,12 @@ ip6_set_link_local_address (u32 sw_if_index, const ip6_address_t * address)
   ip6_address_copy (&ilp.ilp_addr, address);
   ip6_ll_table_entry_update (&ilp, FIB_ROUTE_PATH_LOCAL);
 
-  /* *INDENT-OFF* */
   FOREACH_IP6_LINK_DELEGATE (ild, il,
   ({
     if (NULL != il_delegate_vfts[ild->ild_type].ildv_ll_change)
       il_delegate_vfts[ild->ild_type].ildv_ll_change(ild->ild_index,
                                                      &il->il_ll_addr);
   }));
-  /* *INDENT-ON* */
 
   return (0);
 }
@@ -501,7 +461,6 @@ ip6_link_add_del_address (ip6_main_t * im,
   if (NULL == il)
     return;
 
-  /* *INDENT-OFF* */
   FOREACH_IP6_LINK_DELEGATE (ild, il,
   ({
       if (is_delete)
@@ -517,7 +476,6 @@ ip6_link_add_del_address (ip6_main_t * im,
                                                           address, address_length);
         }
   }));
-  /* *INDENT-ON* */
 }
 
 static clib_error_t *
@@ -591,14 +549,12 @@ test_ip6_link_command_fn (vlib_main_t * vm,
  * Original MAC address: 16:d9:e0:91:79:86
  * @cliexend
 ?*/
-/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (test_link_command, static) =
 {
   .path = "test ip6 link",
   .function = test_ip6_link_command_fn,
   .short_help = "test ip6 link <mac-address>",
 };
-/* *INDENT-ON* */
 
 static u8 *
 ip6_print_addrs (u8 * s, u32 * addrs)
@@ -630,11 +586,10 @@ format_ip6_link (u8 * s, va_list * arg)
   if (!ip6_link_is_enabled_i (il))
     return (s);
 
-  s = format (s, "%U is admin %s\n",
-             format_vnet_sw_interface_name, vnm,
-             vnet_get_sw_interface (vnm, il->il_sw_if_index),
-             (vnet_sw_interface_is_admin_up (vnm, il->il_sw_if_index) ?
-              "up" : "down"));
+  s = format (
+    s, "%U is admin %s\n", format_vnet_sw_if_index_name, vnm,
+    il->il_sw_if_index,
+    (vnet_sw_interface_is_admin_up (vnm, il->il_sw_if_index) ? "up" : "down"));
 
   u32 ai;
   u32 *link_scope = 0, *global_scope = 0;
@@ -696,13 +651,11 @@ format_ip6_link (u8 * s, va_list * arg)
   s = format (s, "%U%U\n",
              format_white_space, 4, format_ip6_address, &il->il_ll_addr);
 
-  /* *INDENT-OFF* */
   FOREACH_IP6_LINK_DELEGATE(ild, il,
   ({
     s = format (s, "%U", il_delegate_vfts[ild->ild_type].ildv_format,
                      ild->ild_index, 2);
   }));
-  /* *INDENT-ON* */
 
   return (s);
 }
@@ -775,14 +728,12 @@ ip6_link_show (vlib_main_t * vm,
  * show ip6 interface: IPv6 not enabled on interface
  * @cliexend
 ?*/
-/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (ip6_link_show_command, static) =
 {
   .path = "show ip6 interface",
   .function = ip6_link_show,
   .short_help = "show ip6 interface <interface>",
 };
-/* *INDENT-ON* */
 
 static clib_error_t *
 enable_ip6_interface_cmd (vlib_main_t * vm,
@@ -796,7 +747,7 @@ enable_ip6_interface_cmd (vlib_main_t * vm,
 
   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     {
-      if (ip6_link_enable (sw_if_index))
+      if (ip6_link_enable (sw_if_index, NULL))
        error = clib_error_return (0, "Failed\n");
     }
   else
@@ -815,14 +766,12 @@ enable_ip6_interface_cmd (vlib_main_t * vm,
  * Example of how enable IPv6 on a given interface:
  * @cliexcmd{enable ip6 interface GigabitEthernet2/0/0}
 ?*/
-/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (enable_ip6_interface_command, static) =
 {
   .path = "enable ip6 interface",
   .function = enable_ip6_interface_cmd,
   .short_help = "enable ip6 interface <interface>",
 };
-/* *INDENT-ON* */
 
 static clib_error_t *
 disable_ip6_interface_cmd (vlib_main_t * vm,
@@ -855,14 +804,12 @@ disable_ip6_interface_cmd (vlib_main_t * vm,
  * Example of how disable IPv6 on a given interface:
  * @cliexcmd{disable ip6 interface GigabitEthernet2/0/0}
 ?*/
-/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (disable_ip6_interface_command, static) =
 {
   .path = "disable ip6 interface",
   .function = disable_ip6_interface_cmd,
   .short_help = "disable ip6 interface <interface>",
 };
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON