ip: Protocol Independent IP Neighbors
[vpp.git] / src / vnet / bfd / bfd_udp.c
index 5c0da0a..0a9106e 100644 (file)
@@ -29,6 +29,7 @@
 #include <vnet/ip/ip4.h>
 #include <vnet/ip/ip6.h>
 #include <vnet/ip/ip6_packet.h>
+#include <vnet/ip/ip6_link.h>
 #include <vnet/adj/adj.h>
 #include <vnet/adj/adj_nbr.h>
 #include <vnet/dpo/receive_dpo.h>
@@ -82,7 +83,7 @@ vnet_api_error_t
 bfd_udp_set_echo_source (u32 sw_if_index)
 {
   vnet_sw_interface_t *sw_if =
-    vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index);
+    vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
   if (sw_if)
     {
       bfd_udp_main.echo_source_sw_if_index = sw_if_index;
@@ -114,8 +115,8 @@ bfd_udp_is_echo_available (bfd_transport_e transport)
    * pick an unused address from that subnet
    */
   vnet_sw_interface_t *sw_if =
-    vnet_get_sw_interface_safe (bfd_udp_main.vnet_main,
-                               bfd_udp_main.echo_source_sw_if_index);
+    vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main,
+                                  bfd_udp_main.echo_source_sw_if_index);
   if (sw_if && sw_if->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
     {
       if (BFD_TRANSPORT_UDP4 == transport)
@@ -566,7 +567,7 @@ bfd_udp_validate_api_input (u32 sw_if_index,
 {
   bfd_udp_main_t *bum = &bfd_udp_main;
   vnet_sw_interface_t *sw_if =
-    vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index);
+    vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
   u8 local_ip_valid = 0;
   ip_interface_address_t *ia = NULL;
   if (!sw_if)
@@ -608,21 +609,35 @@ bfd_udp_validate_api_input (u32 sw_if_index,
                        "IP family mismatch (local is ipv6, peer is ipv4)");
          return VNET_API_ERROR_INVALID_ARGUMENT;
        }
-      ip6_main_t *im = &ip6_main;
-      /* *INDENT-OFF* */
-      foreach_ip_interface_address (
-          &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
-            ip6_address_t *x =
-                ip_interface_address_get_address (&im->lookup_main, ia);
-            if (local_addr->ip6.as_u64[0] == x->as_u64[0] &&
-                local_addr->ip6.as_u64[1] == x->as_u64[1])
-              {
-                /* valid address for this interface */
-                local_ip_valid = 1;
-                break;
-              }
-          }));
-      /* *INDENT-ON* */
+
+      if (ip6_address_is_link_local_unicast (&local_addr->ip6))
+       {
+         const ip6_address_t *ll_addr;
+         ll_addr = ip6_get_link_local_address (sw_if_index);
+         if (ip6_address_is_equal (ll_addr, &local_addr->ip6))
+           {
+             /* valid address for this interface */
+             local_ip_valid = 1;
+           }
+       }
+      else
+       {
+         ip6_main_t *im = &ip6_main;
+         /* *INDENT-OFF* */
+         foreach_ip_interface_address (
+             &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
+               ip6_address_t *x =
+                   ip_interface_address_get_address (&im->lookup_main, ia);
+               if (local_addr->ip6.as_u64[0] == x->as_u64[0] &&
+                   local_addr->ip6.as_u64[1] == x->as_u64[1])
+                 {
+                   /* valid address for this interface */
+                   local_ip_valid = 1;
+                   break;
+                 }
+             }));
+         /* *INDENT-ON* */
+       }
     }
 
   if (!local_ip_valid)