]> git.puffer.fish Git - matthieu/frr.git/commitdiff
(no commit message)
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 11 Jun 2015 16:19:59 +0000 (09:19 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 11 Jun 2015 16:19:59 +0000 (09:19 -0700)
zebra/interface.c
zebra/interface.h
zebra/kernel_null.c
zebra/rt_netlink.c
zebra/rt_netlink.h
zebra/zebra_rib.c
zebra/zserv.c

index 9a1259c73a817c5415e65a21d3bb6d0d5ff21874..8af7ef7180775f9dc590b2b71c06b97d6d705b61 100644 (file)
@@ -41,6 +41,7 @@
 #include "zebra/debug.h"
 #include "zebra/irdp.h"
 #include "zebra/zebra_ptm.h"
+#include "zebra/rt_netlink.h"
 
 #define ZEBRA_PTM_SUPPORT
 
@@ -528,6 +529,64 @@ if_delete_update (struct interface *ifp)
   ifp->ifindex = IFINDEX_INTERNAL;
 }
 
+void
+ipv6_ll_address_to_mac (struct in6_addr *address, u_char *mac)
+{
+  mac[0] = address->s6_addr[8];
+  mac[0] &= ~0x02;
+  mac[1] = address->s6_addr[9];
+  mac[2] = address->s6_addr[10];
+  mac[3] = address->s6_addr[13];
+  mac[4] = address->s6_addr[14];
+  mac[5] = address->s6_addr[15];
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp,
+                                      struct in6_addr *address,
+                                      int add)
+{
+  char buf[16] = "169.254.0.1";
+  struct in_addr ipv4_ll;
+  u_char mac[6];
+
+  inet_pton (AF_INET, buf, &ipv4_ll);
+
+  ipv6_ll_address_to_mac(address, mac);
+  netlink_neigh_update (add ? RTM_NEWNEIGH : RTM_DELNEIGH,
+                        ifp->ifindex, ipv4_ll.s_addr, mac, 6);
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (struct interface *ifp)
+{
+  if (listhead(ifp->nbr_connected))
+    {
+      struct nbr_connected *nbr_connected;
+      struct listnode *node;
+
+      for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected))
+        if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp,
+                                              &nbr_connected->address->u.prefix6,
+                                              1);
+    }
+}
+
+void
+if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp)
+{
+  if (listhead(ifp->nbr_connected))
+    {
+      struct nbr_connected *nbr_connected;
+      struct listnode *node;
+
+      for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, nbr_connected))
+        if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp,
+                                              &nbr_connected->address->u.prefix6,
+                                              0);
+    }
+}
+
 /* Interface is up. */
 void
 if_up (struct interface *ifp)
@@ -545,6 +604,7 @@ if_up (struct interface *ifp)
   }
   zebra_interface_up_update (ifp);
 
+  if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp);
 
   /* Install connected routes to the kernel. */
   if (ifp->connected)
@@ -597,6 +657,8 @@ if_down (struct interface *ifp)
 
   /* Examine all static routes which direct to the interface. */
   rib_update ();
+
+  if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
 }
 
 void
index d20d991515c4017e9ec7554bd8a115574ccd2116..72e40044fc3dda7604abf0be8b5c0cf02773ea2c 100644 (file)
@@ -213,6 +213,9 @@ struct zebra_if
 #endif /* SUNOS_5 */
 };
 
+extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update (struct interface *ifp,
+                                                  struct in6_addr *address, int add);
+extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp);
 extern void if_delete_update (struct interface *ifp);
 extern void if_add_update (struct interface *ifp);
 extern void if_up (struct interface *);
index 2e833febe6e8a8b6fa0791b9257b25a614a29ed2..9b45acb79b0c99850bbaea15c8e02e4d39f8b488 100644 (file)
@@ -48,6 +48,11 @@ int kernel_address_delete_ipv4 (struct interface *a, struct connected *b)
   return 0;
 }
 
+int netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
+{
+  return 0;
+}
+
 void kernel_init (void) { return; }
 #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA
 #pragma weak route_read = kernel_init
index ab49406cd72d354dfa036d15e2ba57bf28f90c7d..99c4ab54f80d7b37b2ccf2349cebb97c88b88a22 100644 (file)
@@ -1483,8 +1483,30 @@ _netlink_route_build_singlepath(
         size_t req_size,
        int cmd)
 {
+
+  if (rtmsg->rtm_family == AF_INET &&
+      (nexthop->type == NEXTHOP_TYPE_IPV6
+      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
+      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
+    {
+      char buf[16] = "169.254.0.1";
+      struct in_addr ipv4_ll;
+
+      inet_pton (AF_INET, buf, &ipv4_ll);
+      rtmsg->rtm_flags |= RTNH_F_ONLINK;
+      addattr_l (nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
+      addattr32 (nlmsg, req_size, RTA_OIF, nexthop->ifindex);
+
+      if (IS_ZEBRA_DEBUG_KERNEL)
+        zlog_debug(" 5549: _netlink_route_build_singlepath() (%s): "
+                   "nexthop via %s if %u",
+                   routedesc, buf, nexthop->ifindex);
+      return;
+    }
+
   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
     rtmsg->rtm_flags |= RTNH_F_ONLINK;
+
   if (nexthop->type == NEXTHOP_TYPE_IPV4
       || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
     {
@@ -1573,14 +1595,38 @@ _netlink_route_build_multipath(
         struct nexthop *nexthop,
         struct rtattr *rta,
         struct rtnexthop *rtnh,
-        union g_addr **src
-        )
+        struct rtmsg *rtmsg,
+        union g_addr **src)
 {
   rtnh->rtnh_len = sizeof (*rtnh);
   rtnh->rtnh_flags = 0;
   rtnh->rtnh_hops = 0;
   rta->rta_len += rtnh->rtnh_len;
 
+  if (rtmsg->rtm_family == AF_INET &&
+      (nexthop->type == NEXTHOP_TYPE_IPV6
+      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
+      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX))
+    {
+      char buf[16] = "169.254.0.1";
+      struct in_addr ipv4_ll;
+
+      inet_pton (AF_INET, buf, &ipv4_ll);
+      bytelen = 4;
+      rtnh->rtnh_flags |= RTNH_F_ONLINK;
+      rta_addattr_l (rta, NL_PKT_BUF_SIZE, RTA_GATEWAY,
+                     &ipv4_ll, bytelen);
+      rtnh->rtnh_len += sizeof (struct rtattr) + bytelen;
+      rtnh->rtnh_ifindex = nexthop->ifindex;
+
+      if (IS_ZEBRA_DEBUG_KERNEL)
+        zlog_debug(" 5549: netlink_route_build_multipath() (%s): "
+                   "nexthop via %s if %u",
+                   routedesc, buf, nexthop->ifindex);
+      return;
+    }
+
+
   if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ONLINK))
     rtnh->rtnh_flags |= RTNH_F_ONLINK;
 
@@ -1683,6 +1729,32 @@ _netlink_route_debug(
     }
 }
 
+int
+netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen)
+{
+  struct {
+      struct nlmsghdr         n;
+      struct ndmsg            ndm;
+      char                    buf[256];
+  } req;
+
+  memset(&req.n, 0, sizeof(req.n));
+  memset(&req.ndm, 0, sizeof(req.ndm));
+
+  req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+  req.n.nlmsg_type = cmd; //RTM_NEWNEIGH or RTM_DELNEIGH
+  req.ndm.ndm_family = AF_INET;
+  req.ndm.ndm_state = NUD_PERMANENT;
+  req.ndm.ndm_ifindex = ifindex;
+  req.ndm.ndm_type = RTN_UNICAST;
+
+  addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
+  addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+
+  return netlink_talk (&req.n, &netlink_cmd);
+}
+
 /* Routing table change via netlink interface. */
 /* Update flag indicates whether this is a "replace" or not. */
 static int
@@ -1874,7 +1946,7 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
               _netlink_route_debug(cmd, p, nexthop,
                                    routedesc, family);
               _netlink_route_build_multipath(routedesc, bytelen,
-                                             nexthop, rta, rtnh, &src1);
+                                             nexthop, rta, rtnh, &req.r, &src1);
               rtnh = RTNH_NEXT (rtnh);
 
               if (cmd == RTM_NEWROUTE)
index 14e811db31cfb5dfcbd91755fb2fc8fbff1c5909..5b1b48cb0a79071990c1b6be91fad220637a4c9b 100644 (file)
@@ -41,6 +41,9 @@ nl_msg_type_to_str (uint16_t msg_type);
 extern const char *
 nl_rtproto_to_str (u_char rtproto);
 
+int
+netlink_neigh_update (int cmd, int ifindex, __u32 addr, char *lla, int llalen);
+
 extern int netlink_route_read(void);
 extern int interface_lookup_netlink(void);
 
index 7adbcbe5347f2dbe4d62192a117f01368cea8b5e..0d11927e3f238c2142c0cc947e4180e017f83284 100644 (file)
@@ -3962,8 +3962,14 @@ rib_close_table (struct route_table *table)
 void
 rib_close (void)
 {
+  struct listnode *node, *nnode;
+  struct interface *ifp;
+
   rib_close_table (vrf_table (AFI_IP, SAFI_UNICAST, 0));
   rib_close_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0));
+
+  for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
+    if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
 }
 
 /* Routing information base initialize. */
index 61d3a0a55ebe9a96fe9fb380267b284e1121f88a..cd986daee91514d9bb3d3c0083031deec3ee5f35 100644 (file)
@@ -44,6 +44,7 @@
 #include "zebra/debug.h"
 #include "zebra/ipforward.h"
 #include "zebra/zebra_rnh.h"
+#include "zebra/rt_netlink.h"
 
 /* Event list of zebra. */
 enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE };
@@ -415,6 +416,8 @@ nbr_connected_replacement_add_ipv6 (struct interface *ifp, struct in6_addr *addr
   prefix_copy(ifc->address, &p);
 
   zebra_interface_nbr_address_add_update (ifp, ifc);
+
+  if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 1);
 }
 
 void
@@ -436,6 +439,8 @@ nbr_connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
 
   zebra_interface_nbr_address_delete_update (ifp, ifc);
 
+  if_nbr_ipv6ll_to_ipv4ll_neigh_update (ifp, address, 0);
+
   nbr_connected_free (ifc);
 }