]> git.puffer.fish Git - matthieu/frr.git/commitdiff
Zebra: Handle IPv6 address status during initialization
authorvivek <vivek@cumulusnetworks.com>
Fri, 20 Nov 2015 18:34:50 +0000 (10:34 -0800)
committervivek <vivek@cumulusnetworks.com>
Fri, 20 Nov 2015 18:34:50 +0000 (10:34 -0800)
At init time, Zebra queries the kernel for all interfaces. At this time,
an IPv6 address may exist on an interface but IPv6 DAD has not completed,
or it could be that DAD has failed. Zebra should examine the flags on
the address and act accordingly. Otherwise, it may end up with addresses
and routes which are not actually valid in the kernel, and this may lead
to, for example, BGP attempting neighbor connections on an interface on
which the source IPv6 address is not yet valid.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
Ticket: CM-7176
Reviewed By: CCR-3815
Testing Done: Verify failed test (needs temporary test change)

Note: Imported from 2.5-br patch zebra-handle-ipv6-addr-status.patch.

zebra/rt_netlink.c

index 183dc6e057508f51ac8fb5e75ccc28aa8ce26f1b..88fac53310411cff320d054ff92369703b65e678 100644 (file)
@@ -575,8 +575,9 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (IS_ZEBRA_DEBUG_KERNEL)    /* remove this line to see initial ifcfg */
     {
       char buf[BUFSIZ];
-      zlog_debug ("netlink_interface_addr %s %s vrf %u:",
-                 lookup (nlmsg_str, h->nlmsg_type), ifp->name, vrf_id);
+      zlog_debug ("netlink_interface_addr %s %s vrf %u flags 0x%x:",
+                 lookup (nlmsg_str, h->nlmsg_type), ifp->name,
+                 vrf_id, ifa->ifa_flags);
       if (tb[IFA_LOCAL])
         zlog_debug ("  IFA_LOCAL     %s/%d",
                    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
@@ -654,9 +655,15 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (ifa->ifa_family == AF_INET6)
     {
       if (h->nlmsg_type == RTM_NEWADDR)
-        connected_add_ipv6 (ifp, flags,
-                            (struct in6_addr *) addr, ifa->ifa_prefixlen,
-                            (struct in6_addr *) broad, label);
+        {
+          /* Only consider valid addresses; we'll not get a notification from
+           * the kernel till IPv6 DAD has completed, but at init time, Quagga
+           * does query for and will receive all addresses.
+           */
+          if (!(ifa->ifa_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)))
+            connected_add_ipv6 (ifp, flags, (struct in6_addr *) addr,
+                    ifa->ifa_prefixlen, (struct in6_addr *) broad, label);
+        }
       else
         connected_delete_ipv6 (ifp,
                                (struct in6_addr *) addr, ifa->ifa_prefixlen,