]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #234 from donaldsharp/v6_multipath_rework1
authorRuss White <russ@riw.us>
Wed, 1 Mar 2017 14:48:04 +0000 (09:48 -0500)
committerGitHub <noreply@github.com>
Wed, 1 Mar 2017 14:48:04 +0000 (09:48 -0500)
V6 multipath rework1

zebra/if_netlink.c
zebra/if_netlink.h
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/rt_netlink.c
zebra/rt_netlink.h

index 660fad65307bfdd27781f5bd7d31b3850174ae12..65fc8789f9064c571d2319816034a637f9e59e93 100644 (file)
@@ -302,7 +302,7 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name)
    during bootstrap. */
 static int
 netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                   ns_id_t ns_id)
+                   ns_id_t ns_id, int startup)
 {
   int len;
   struct ifinfomsg *ifi;
@@ -403,7 +403,7 @@ interface_lookup_netlink (struct zebra_ns *zns)
   ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd);
   if (ret < 0)
     return ret;
-  ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0);
+  ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1);
   if (ret < 0)
     return ret;
 
@@ -411,7 +411,7 @@ interface_lookup_netlink (struct zebra_ns *zns)
   ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd);
   if (ret < 0)
     return ret;
-  ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0);
+  ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1);
   if (ret < 0)
     return ret;
 
@@ -419,7 +419,7 @@ interface_lookup_netlink (struct zebra_ns *zns)
   ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd);
   if (ret < 0)
     return ret;
-  ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0);
+  ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1);
   if (ret < 0)
     return ret;
 
@@ -475,7 +475,7 @@ netlink_address (int cmd, int family, struct interface *ifp,
     addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
                strlen (ifc->label) + 1);
 
-  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
+  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
 }
 
 int
@@ -492,7 +492,7 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
 
 int
 netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                        ns_id_t ns_id)
+                        ns_id_t ns_id, int startup)
 {
   int len;
   struct ifaddrmsg *ifa;
@@ -630,7 +630,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h,
 
 int
 netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                     ns_id_t ns_id)
+                     ns_id_t ns_id, int startup)
 {
   int len;
   struct ifinfomsg *ifi;
index aac67916c034986a7382915617c0f49c3dceeb4d..6fa39ccab24ee9b53b5a184797d8f94a5983167e 100644 (file)
@@ -25,9 +25,9 @@
 #ifdef HAVE_NETLINK
 
 extern int netlink_interface_addr (struct sockaddr_nl *snl,
-                                   struct nlmsghdr *h, ns_id_t ns_id);
+                                   struct nlmsghdr *h, ns_id_t ns_id, int startup);
 extern int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                                ns_id_t ns_id);
+                                ns_id_t ns_id, int startup);
 extern int interface_lookup_netlink (struct zebra_ns *zns);
 
 #endif /* HAVE_NETLINK */
index 058d14481e979a0ab693a66a8c30ebfc9f2e5c21..c9c2d90eac399f8e303b3909bea01fa0cfa20081 100644 (file)
@@ -125,7 +125,7 @@ extern struct zebra_privs_t zserv_privs;
 
 int
 netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h,
-    ns_id_t ns_id)
+                     ns_id_t ns_id, int startup)
 {
   zlog_warn ("netlink_talk: ignoring message type 0x%04x NS %u", h->nlmsg_type,
              ns_id);
@@ -239,7 +239,7 @@ netlink_socket (struct nlsock *nl, unsigned long groups, ns_id_t ns_id)
 
 static int
 netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
-    ns_id_t ns_id)
+                           ns_id_t ns_id, int startup)
 {
   /* JF: Ignore messages that aren't from the kernel */
   if ( snl->nl_pid != 0 )
@@ -251,22 +251,22 @@ netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h,
   switch (h->nlmsg_type)
     {
     case RTM_NEWROUTE:
-      return netlink_route_change (snl, h, ns_id);
+      return netlink_route_change (snl, h, ns_id, startup);
       break;
     case RTM_DELROUTE:
-      return netlink_route_change (snl, h, ns_id);
+      return netlink_route_change (snl, h, ns_id, startup);
       break;
     case RTM_NEWLINK:
-      return netlink_link_change (snl, h, ns_id);
+      return netlink_link_change (snl, h, ns_id, startup);
       break;
     case RTM_DELLINK:
-      return netlink_link_change (snl, h, ns_id);
+      return netlink_link_change (snl, h, ns_id, startup);
       break;
     case RTM_NEWADDR:
-      return netlink_interface_addr (snl, h, ns_id);
+      return netlink_interface_addr (snl, h, ns_id, startup);
       break;
     case RTM_DELADDR:
-      return netlink_interface_addr (snl, h, ns_id);
+      return netlink_interface_addr (snl, h, ns_id, startup);
       break;
     default:
       zlog_warn ("Unknown netlink nlmsg_type %d vrf %u\n", h->nlmsg_type,
@@ -280,7 +280,7 @@ static int
 kernel_read (struct thread *thread)
 {
   struct zebra_ns *zns = (struct zebra_ns *)THREAD_ARG (thread);
-  netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5);
+  netlink_parse_info (netlink_information_fetch, &zns->netlink, zns, 5, 0);
   zns->t_netlink = thread_add_read (zebrad.master, kernel_read, zns,
                                      zns->netlink.sock);
 
@@ -444,12 +444,23 @@ nl_rttype_to_str (u_char rttype)
   return lookup (rttype_str, rttype);
 }
 
-/* Receive message from netlink interface and pass those information
-   to the given function. */
+/*
+ * netlink_parse_info
+ *
+ * Receive message from netlink interface and pass those information
+ *  to the given function.
+ *
+ * filter  -> Function to call to read the results
+ * nl      -> netlink socket information
+ * zns     -> The zebra namespace data
+ * count   -> How many we should read in, 0 means as much as possible
+ * startup -> Are we reading in under startup conditions? passed to
+ *            the filter.
+ */
 int
 netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
-                                   ns_id_t),
-                    struct nlsock *nl, struct zebra_ns *zns, int count)
+                                   ns_id_t, int),
+                    struct nlsock *nl, struct zebra_ns *zns, int count, int startup)
 {
   int status;
   int ret = 0;
@@ -613,7 +624,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
               continue;
             }
 
-          error = (*filter) (&snl, h, zns->ns_id);
+          error = (*filter) (&snl, h, zns->ns_id, startup);
           if (error < 0)
             {
               zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
@@ -637,11 +648,23 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
   return ret;
 }
 
-/* sendmsg() to netlink socket then recvmsg(). */
+/*
+ * netlink_talk
+ *
+ * sendmsg() to netlink socket then recvmsg().
+ * Calls netlink_parse_info to parse returned data
+ *
+ * filter   -> The filter to read final results from kernel
+ * nlmsghdr -> The data to send to the kernel
+ * nl       -> The netlink socket information
+ * zns      -> The zebra namespace information
+ * startup  -> Are we reading in under startup conditions
+ *             This is passed through eventually to filter.
+ */
 int
 netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
-                            ns_id_t),
-             struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns)
+                             ns_id_t, int startup),
+              struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, int startup)
 {
   int status;
   struct sockaddr_nl snl;
@@ -697,7 +720,7 @@ netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
    * Get reply from netlink socket.
    * The reply should either be an acknowlegement or an error.
    */
-  return netlink_parse_info (filter, nl, zns, 0);
+  return netlink_parse_info (filter, nl, zns, 0, startup);
 }
 
 /* Get type specified information from netlink. */
index f17f1380c25c3aaf6ba59f20e771bd00dabdd3fc..adbcf71f636fa7c3607de14c66c33cb652792a4f 100644 (file)
@@ -44,14 +44,15 @@ extern const char * nl_family_to_str (u_char family);
 extern const char * nl_rttype_to_str (u_char rttype);
 
 extern int netlink_parse_info (int (*filter) (struct sockaddr_nl *,
-                               struct nlmsghdr *, ns_id_t), struct nlsock *nl,
-                               struct zebra_ns *zns, int count);
+                                              struct nlmsghdr *, ns_id_t, int),
+                               struct nlsock *nl, struct zebra_ns *zns,
+                               int count, int startup);
 extern int netlink_talk_filter (struct sockaddr_nl *, struct nlmsghdr *,
-                               ns_id_t);
+                               ns_id_t, int startup);
 extern int netlink_talk (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *,
-                                       ns_id_t),
+                                       ns_id_t, int startup),
                         struct nlmsghdr *n, struct nlsock *nl,
-                         struct zebra_ns *zns);
+                         struct zebra_ns *zns, int startup);
 extern int netlink_request (int family, int type, struct nlsock *nl);
 
 #endif /* HAVE_NETLINK */
index d88dc05b2875b531ee62f33d17c0fd4f894b235b..450e15e0f7b6a625471daebaae2e2e9b68c55574 100644 (file)
@@ -126,8 +126,8 @@ vrf_lookup_by_table (u_int32_t table_id)
 
 /* Looking up routing table by netlink interface. */
 static int
-netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                       ns_id_t ns_id)
+netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
+                                   ns_id_t ns_id, int startup)
 {
   int len;
   struct rtmsg *rtm;
@@ -151,9 +151,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
 
   rtm = NLMSG_DATA (h);
 
-  if (h->nlmsg_type != RTM_NEWROUTE)
+  if (startup && h->nlmsg_type != RTM_NEWROUTE)
     return 0;
-  if (rtm->rtm_type != RTN_UNICAST)
+  if (startup && rtm->rtm_type != RTN_UNICAST)
     return 0;
 
   len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
@@ -170,6 +170,11 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (rtm->rtm_protocol == RTPROT_KERNEL)
     return 0;
 
+  if (!startup &&
+      rtm->rtm_protocol == RTPROT_ZEBRA &&
+      h->nlmsg_type == RTM_NEWROUTE)
+    return 0;
+
   /* We don't care about change notifications for the MPLS table. */
   /* TODO: Revisit this. */
   if (rtm->rtm_family == AF_MPLS)
@@ -213,19 +218,22 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
   if (tb[RTA_GATEWAY])
     gate = RTA_DATA (tb[RTA_GATEWAY]);
 
-  if (tb[RTA_PRIORITY])
-    metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
-
-  if (tb[RTA_METRICS])
+  if (h->nlmsg_type == RTM_NEWROUTE)
     {
-      struct rtattr *mxrta[RTAX_MAX+1];
+      if (tb[RTA_PRIORITY])
+        metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
 
-      memset (mxrta, 0, sizeof mxrta);
-      netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
-                            RTA_PAYLOAD(tb[RTA_METRICS]));
+      if (tb[RTA_METRICS])
+        {
+          struct rtattr *mxrta[RTAX_MAX+1];
+
+          memset (mxrta, 0, sizeof mxrta);
+          netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
+                                RTA_PAYLOAD(tb[RTA_METRICS]));
 
-      if (mxrta[RTAX_MTU])
-        mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
+          if (mxrta[RTAX_MTU])
+            mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
+        }
     }
 
   if (rtm->rtm_family == AF_INET)
@@ -233,14 +241,48 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
       p.family = AF_INET;
       memcpy (&p.u.prefix4, dest, 4);
       p.prefixlen = rtm->rtm_dst_len;
+    }
+  else if (rtm->rtm_family == AF_INET6)
+    {
+      p.family = AF_INET6;
+      memcpy (&p.u.prefix6, dest, 16);
+      p.prefixlen = rtm->rtm_dst_len;
+
+      src_p.family = AF_INET6;
+      memcpy (&src_p.prefix, src, 16);
+      src_p.prefixlen = rtm->rtm_src_len;
+    }
 
-      if (rtm->rtm_src_len != 0)
-       return 0;
+  if (rtm->rtm_src_len != 0)
+    {
+      char buf[PREFIX_STRLEN];
+      zlog_warn ("unsupported IPv[4|6] sourcedest route (dest %s vrf %u)",
+                 prefix2str (&p, buf, sizeof(buf)), vrf_id);
+      return 0;
+    }
+
+  if (IS_ZEBRA_DEBUG_KERNEL)
+    {
+      char buf[PREFIX_STRLEN];
+      char buf2[PREFIX_STRLEN];
+      zlog_debug ("%s %s%s%s vrf %u",
+                  nl_msg_type_to_str (h->nlmsg_type),
+                  prefix2str (&p, buf, sizeof(buf)),
+                  src_p.prefixlen ? " from " : "",
+                  src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
+                  vrf_id);
+    }
+
+  afi_t afi = AFI_IP;
+  if (rtm->rtm_family == AF_INET6)
+    afi = AFI_IP6;
 
+  if (h->nlmsg_type == RTM_NEWROUTE)
+    {
       if (!tb[RTA_MULTIPATH])
-       rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                0, flags, &p, NULL, gate, prefsrc, index,
-                table, metric, mtu, 0);
+        rib_add (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+                 0, flags, &p, NULL, gate, prefsrc, index,
+                 table, metric, mtu, 0);
       else
         {
           /* This is a multipath route */
@@ -280,10 +322,20 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
 
               if (gate)
                 {
-                  if (index)
-                    rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
-                  else
-                    rib_nexthop_ipv4_add (rib, gate, prefsrc);
+                  if (rtm->rtm_family == AF_INET)
+                    {
+                      if (index)
+                        rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
+                      else
+                        rib_nexthop_ipv4_add (rib, gate, prefsrc);
+                    }
+                  else if (rtm->rtm_family == AF_INET6)
+                    {
+                      if (index)
+                        rib_nexthop_ipv6_ifindex_add (rib, gate, index);
+                      else
+                        rib_nexthop_ipv6_add (rib,gate);
+                    }
                 }
               else
                 rib_nexthop_ifindex_add (rib, index);
@@ -292,250 +344,49 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
               rtnh = RTNH_NEXT(rtnh);
             }
 
-         zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
-                                rib->nexthop_num);
+          zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
+                                 rib->nexthop_num);
           if (rib->nexthop_num == 0)
             XFREE (MTYPE_RIB, rib);
           else
             rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
         }
     }
-  if (rtm->rtm_family == AF_INET6)
-    {
-      p.family = AF_INET6;
-      memcpy (&p.u.prefix6, dest, 16);
-      p.prefixlen = rtm->rtm_dst_len;
-
-      src_p.family = AF_INET6;
-      memcpy (&src_p.prefix, src, 16);
-      src_p.prefixlen = rtm->rtm_src_len;
-
-      rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-               0, flags, &p, &src_p, gate, prefsrc, index,
-              table, metric, mtu, 0);
-    }
-
-  return 0;
-}
-
-/* Routing information change from the kernel. */
-static int
-netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                      ns_id_t ns_id)
-{
-  int len;
-  struct rtmsg *rtm;
-  struct rtattr *tb[RTA_MAX + 1];
-  u_char zebra_flags = 0;
-  struct prefix p;
-  vrf_id_t vrf_id = VRF_DEFAULT;
-  char anyaddr[16] = { 0 };
-
-  int index = 0;
-  int table;
-  int metric = 0;
-  u_int32_t mtu = 0;
-
-  void *dest = NULL;
-  void *gate = NULL;
-  void *prefsrc = NULL;                /* IPv4 preferred source host address */
-  void *src = NULL;            /* IPv6 srcdest   source prefix */
-
-  rtm = NLMSG_DATA (h);
-
-  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
-
-  memset (tb, 0, sizeof tb);
-  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
-
-  if (rtm->rtm_flags & RTM_F_CLONED)
-    return 0;
-  if (rtm->rtm_protocol == RTPROT_REDIRECT)
-    return 0;
-  if (rtm->rtm_protocol == RTPROT_KERNEL)
-    return 0;
-
-  if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
-    return 0;
-  if (rtm->rtm_protocol == RTPROT_ZEBRA)
-    SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
-
-  /* Table corresponding to route. */
-  if (tb[RTA_TABLE])
-    table = *(int *) RTA_DATA (tb[RTA_TABLE]);
   else
-    table = rtm->rtm_table;
-
-  /* Map to VRF */
-  vrf_id = vrf_lookup_by_table(table);
-  if (vrf_id == VRF_DEFAULT)
     {
-      if (!is_zebra_valid_kernel_table(table) &&
-          !is_zebra_main_routing_table(table))
-        return 0;
-    }
-
-  if (tb[RTA_OIF])
-    index = *(int *) RTA_DATA (tb[RTA_OIF]);
-
-  if (tb[RTA_DST])
-    dest = RTA_DATA (tb[RTA_DST]);
-  else
-    dest = anyaddr;
-
-  if (tb[RTA_SRC])
-    src = RTA_DATA (tb[RTA_SRC]);
-  else
-    src = anyaddr;
-
-  if (tb[RTA_GATEWAY])
-    gate = RTA_DATA (tb[RTA_GATEWAY]);
-
-  if (tb[RTA_PREFSRC])
-    prefsrc = RTA_DATA (tb[RTA_PREFSRC]);
-
-  if (h->nlmsg_type == RTM_NEWROUTE)
-    {
-      if (tb[RTA_PRIORITY])
-        metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
-
-      if (tb[RTA_METRICS])
+      if (!tb[RTA_MULTIPATH])
+        rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
+                    &p, NULL, gate, index, table);
+      else
         {
-          struct rtattr *mxrta[RTAX_MAX+1];
-
-          memset (mxrta, 0, sizeof mxrta);
-          netlink_parse_rtattr (mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),
-                                RTA_PAYLOAD(tb[RTA_METRICS]));
-
-          if (mxrta[RTAX_MTU])
-            mtu = *(u_int32_t *) RTA_DATA(mxrta[RTAX_MTU]);
-        }
-    }
-
-  if (rtm->rtm_family == AF_INET)
-    {
-      p.family = AF_INET;
-      memcpy (&p.u.prefix4, dest, 4);
-      p.prefixlen = rtm->rtm_dst_len;
-
-      if (rtm->rtm_src_len != 0)
-       {
-         zlog_warn ("unsupported IPv4 sourcedest route (dest %s/%d)",
-                    inet_ntoa (p.u.prefix4), p.prefixlen);
-         return 0;
-       }
+          struct rtnexthop *rtnh =
+            (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
 
-      if (IS_ZEBRA_DEBUG_KERNEL)
-        {
-          char buf[PREFIX_STRLEN];
-          zlog_debug ("%s %s vrf %u",
-                      nl_msg_type_to_str (h->nlmsg_type),
-                      prefix2str (&p, buf, sizeof(buf)), vrf_id);
-        }
+          len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
 
-      if (h->nlmsg_type == RTM_NEWROUTE)
-        {
-          if (!tb[RTA_MULTIPATH])
-            rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                     0, 0, &p, NULL, gate, prefsrc, index,
-                     table, metric, mtu, 0);
-          else
+          for (;;)
             {
-              /* This is a multipath route */
-
-              struct rib *rib;
-              struct rtnexthop *rtnh =
-                (struct rtnexthop *) RTA_DATA (tb[RTA_MULTIPATH]);
-
-              len = RTA_PAYLOAD (tb[RTA_MULTIPATH]);
-
-              rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-              rib->type = ZEBRA_ROUTE_KERNEL;
-              rib->distance = 0;
-              rib->flags = 0;
-              rib->metric = metric;
-              rib->mtu = mtu;
-              rib->vrf_id = vrf_id;
-              rib->table = table;
-              rib->nexthop_num = 0;
-              rib->uptime = time (NULL);
-
-              for (;;)
-                {
-                  if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
-                    break;
-
-                  index = rtnh->rtnh_ifindex;
-                  gate = 0;
-                  if (rtnh->rtnh_len > sizeof (*rtnh))
-                    {
-                      memset (tb, 0, sizeof (tb));
-                      netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
-                                            rtnh->rtnh_len - sizeof (*rtnh));
-                      if (tb[RTA_GATEWAY])
-                        gate = RTA_DATA (tb[RTA_GATEWAY]);
-                    }
-
-                  if (gate)
-                    {
-                      if (index)
-                        rib_nexthop_ipv4_ifindex_add (rib, gate, prefsrc, index);
-                      else
-                        rib_nexthop_ipv4_add (rib, gate, prefsrc);
-                    }
-                  else
-                    rib_nexthop_ifindex_add (rib, index);
+              if (len < (int) sizeof (*rtnh) || rtnh->rtnh_len > len)
+                break;
 
-                  len -= NLMSG_ALIGN(rtnh->rtnh_len);
-                  rtnh = RTNH_NEXT(rtnh);
+              gate = NULL;
+              if (rtnh->rtnh_len > sizeof (*rtnh))
+                {
+                  memset (tb, 0, sizeof (tb));
+                  netlink_parse_rtattr (tb, RTA_MAX, RTNH_DATA (rtnh),
+                                        rtnh->rtnh_len - sizeof (*rtnh));
+                  if (tb[RTA_GATEWAY])
+                    gate = RTA_DATA (tb[RTA_GATEWAY]);
                 }
 
-             zserv_nexthop_num_warn(__func__, (const struct prefix *)&p,
-                                    rib->nexthop_num);
+              if (gate)
+                rib_delete (afi, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, flags,
+                            &p, NULL, gate, index, table);
 
-              if (rib->nexthop_num == 0)
-                XFREE (MTYPE_RIB, rib);
-              else
-                rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib);
+              len -= NLMSG_ALIGN(rtnh->rtnh_len);
+              rtnh = RTNH_NEXT(rtnh);
             }
         }
-      else
-        rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
-                   &p, NULL, gate, index, table);
-    }
-
-  if (rtm->rtm_family == AF_INET6)
-    {
-      struct prefix p;
-      struct prefix_ipv6 src_p;
-
-      p.family = AF_INET6;
-      memcpy (&p.u.prefix6, dest, 16);
-      p.prefixlen = rtm->rtm_dst_len;
-
-      src_p.family = AF_INET6;
-      memcpy (&src_p.prefix, src, 16);
-      src_p.prefixlen = rtm->rtm_src_len;
-
-      if (IS_ZEBRA_DEBUG_KERNEL)
-        {
-         char buf[PREFIX_STRLEN];
-         char buf2[PREFIX_STRLEN];
-          zlog_debug ("%s %s%s%s vrf %u",
-                      nl_msg_type_to_str (h->nlmsg_type),
-                      prefix2str (&p, buf, sizeof(buf)),
-                      src_p.prefixlen ? " from " : "",
-                      src_p.prefixlen ? prefix2str(&src_p, buf2, sizeof(buf2)) : "",
-                      vrf_id);
-        }
-
-      if (h->nlmsg_type == RTM_NEWROUTE)
-        rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                0, 0, &p, &src_p, gate, prefsrc, index,
-                table, metric, mtu, 0);
-      else
-        rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
-                   0, zebra_flags, &p, &src_p, gate, index, table);
     }
 
   return 0;
@@ -545,7 +396,7 @@ static struct mcast_route_data *mroute = NULL;
 
 static int
 netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                                    ns_id_t ns_id)
+                                     ns_id_t ns_id, int startup)
 {
   int len;
   struct rtmsg *rtm;
@@ -629,7 +480,7 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h
 
 int
 netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                     ns_id_t ns_id)
+                     ns_id_t ns_id, int startup)
 {
   int len;
   vrf_id_t vrf_id = ns_id;
@@ -665,10 +516,10 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
   switch (rtm->rtm_type)
     {
     case RTN_UNICAST:
-      netlink_route_change_read_unicast (snl, h, ns_id);
+      netlink_route_change_read_unicast (snl, h, ns_id, startup);
       break;
     case RTN_MULTICAST:
-      netlink_route_change_read_multicast (snl, h, ns_id);
+      netlink_route_change_read_multicast (snl, h, ns_id, startup);
       break;
     default:
       return 0;
@@ -689,7 +540,7 @@ netlink_route_read (struct zebra_ns *zns)
   ret = netlink_request (AF_INET, RTM_GETROUTE, &zns->netlink_cmd);
   if (ret < 0)
     return ret;
-  ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0);
+  ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
   if (ret < 0)
     return ret;
 
@@ -697,7 +548,7 @@ netlink_route_read (struct zebra_ns *zns)
   ret = netlink_request (AF_INET6, RTM_GETROUTE, &zns->netlink_cmd);
   if (ret < 0)
     return ret;
-  ret = netlink_parse_info (netlink_routing_table, &zns->netlink_cmd, zns, 0);
+  ret = netlink_parse_info (netlink_route_change_read_unicast, &zns->netlink_cmd, zns, 0, 1);
   if (ret < 0)
     return ret;
 
@@ -1244,7 +1095,7 @@ netlink_neigh_update (int cmd, int ifindex, uint32_t addr, char *lla, int llalen
   addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
   addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
 
-  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
+  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
 }
 
 /* Routing table change via netlink interface. */
@@ -1542,7 +1393,7 @@ skip:
   snl.nl_family = AF_NETLINK;
 
   /* Talk to netlink socket. */
-  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
+  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
 }
 
 int
@@ -1572,7 +1423,7 @@ kernel_get_ipmr_sg_stats (void *in)
   addattr_l (&req.n, sizeof (req), RTA_SRC, &mroute->sg.src.s_addr, 4);
   addattr_l (&req.n, sizeof (req), RTA_DST, &mroute->sg.grp.s_addr, 4);
 
-  suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns);
+  suc = netlink_talk (netlink_route_change_read_multicast, &req.n, &zns->netlink_cmd, zns, 0);
 
   mroute = NULL;
   return suc;
@@ -1766,7 +1617,7 @@ netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp)
     }
 
   /* Talk to netlink socket. */
-  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns);
+  return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0);
 }
 
 /*
index 7183525fba6ec8c48052afb6893f78833233cdbb..93ee622e3530bcdc446f1f959eca7aad24801e13 100644 (file)
@@ -34,7 +34,7 @@ extern int
 netlink_mpls_multipath (int cmd, zebra_lsp_t *lsp);
 
 extern int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
-                                 ns_id_t ns_id);
+                                 ns_id_t ns_id, int startup);
 extern int netlink_route_read (struct zebra_ns *zns);
 
 #endif /* HAVE_NETLINK */