bfd: allow IPv6 link-local address as local address

Type: fix

Change-Id: Ia3dacd2628591f7ba9710e8e4d68df97ae21935c
Signed-off-by: Alexander Chernavin <achernavin@netgate.com>
diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c
index cc3b40c..c545042 100644
--- a/src/vnet/bfd/bfd_udp.c
+++ b/src/vnet/bfd/bfd_udp.c
@@ -29,6 +29,7 @@
 #include <vnet/ip/ip4.h>
 #include <vnet/ip/ip6.h>
 #include <vnet/ip/ip6_packet.h>
+#include <vnet/ip/ip6_neighbor.h>
 #include <vnet/adj/adj.h>
 #include <vnet/adj/adj_nbr.h>
 #include <vnet/dpo/receive_dpo.h>
@@ -608,21 +609,35 @@
 			"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))
+	{
+	  ip6_address_t ll_addr;
+	  ll_addr = ip6_neighbor_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)