]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Refactor rib_add_ipv[4|6] to a common function
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 24 Aug 2016 06:20:47 +0000 (02:20 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 1 Sep 2016 11:20:18 +0000 (07:20 -0400)
rib_add_ipv[4|6] both were essentially the same function
combine and refactor everywhere.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/connected.c
zebra/kernel_socket.c
zebra/redistribute.c
zebra/rib.h
zebra/rt_netlink.c
zebra/rtread_getmsg.c
zebra/zebra_rib.c

index e3cb12bcd0f693797bbac23398389723c855a3a3..2aa91ecd6602cdb91ea46b8090339cb7ef4bbfa6 100644 (file)
@@ -185,26 +185,28 @@ connected_update(struct interface *ifp, struct connected *ifc)
 void
 connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
 {
-  struct prefix_ipv4 p;
+  struct prefix p;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
+  PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc));
 
   /* Apply mask to the network. */
-  apply_mask_ipv4 (&p);
+  apply_mask (&p);
 
   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
      address. */
-  if (prefix_ipv4_any (&p))
+  if (prefix_ipv4_any ((struct prefix_ipv4 *)&p))
     return;
 
-  rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
-               ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
+  rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT,
+          0, 0, &p, NULL, NULL, ifp->ifindex,
+          RT_TABLE_MAIN, ifp->metric, 0, 0);
 
-  rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
-               ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST);
+  rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT,
+          0, 0, &p, NULL, NULL, ifp->ifindex,
+          RT_TABLE_MAIN, ifp->metric, 0, 0);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing",
@@ -358,28 +360,28 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
   rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
 
-#ifdef HAVE_IPV6
 void
 connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
 {
-  struct prefix_ipv6 p;
+  struct prefix p;
 
   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
     return;
 
-  PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
+  PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc));
 
   /* Apply mask to the network. */
-  apply_mask_ipv6 (&p);
+  apply_mask (&p);
 
 #ifndef LINUX
   /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
-  if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
+  if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
     return;
 #endif
 
-  rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
-                RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
+  rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT,
+          0, 0, &p, NULL, NULL, ifp->ifindex,
+          RT_TABLE_MAIN, ifp->metric, 0, 0);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
@@ -502,7 +504,6 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
 
   rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
 }
-#endif /* HAVE_IPV6 */
 
 int
 connected_is_unnumbered (struct interface *ifp)
index ccc54ce81f2ac4b5ba442c686c80c514e66943af..a500fabbfb7360ba0656eae4dade3637a189061a 100644 (file)
@@ -974,12 +974,11 @@ rtm_read (struct rt_msghdr *rtm)
       if (rtm->rtm_type == RTM_GET 
           || rtm->rtm_type == RTM_ADD
           || rtm->rtm_type == RTM_CHANGE)
-       rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
-                     (struct prefix_ipv4 *)&p, &gate.sin.sin_addr, NULL, 0, VRF_DEFAULT,
-                     0, 0, 0, 0, SAFI_UNICAST);
+       rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
+                &p, &ggate, NULL, 0, 0, 0, 0, 0);
       else
        rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
-                   0, zebra_flags, &p, &&ggate, 0, 0);
+                   0, zebra_flags, &p, &ggate, 0, 0);
     }
   if (dest.sa.sa_family == AF_INET6)
     {
@@ -1017,10 +1016,9 @@ rtm_read (struct rt_msghdr *rtm)
       if (rtm->rtm_type == RTM_GET 
           || rtm->rtm_type == RTM_ADD
           || rtm->rtm_type == RTM_CHANGE)
-       rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags,
-                     (struct prefix_ipv6 *)&p, &gate.sin6.sin6_addr,
-                     ifindex, VRF_DEFAULT,
-                     0, 0, 0, 0, SAFI_UNICAST);
+       rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
+                0, zebra_flags, &p, &ggate, NULL, ifindex,
+                0, 0, 0, 0);
       else
        rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
                    0, zebra_flags, &p, &ggate, ifindex, 0);
index 2eb4f257f51daa6913fd26236b5abe832bd2decd..776c3519be542fa61ab67dc579d4e0f1312cbd39 100644 (file)
@@ -550,9 +550,9 @@ int
 zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char *rmap_name)
 {
   struct rib *newrib;
-  struct prefix_ipv4 p4;
+  struct prefix p;
   struct nexthop *nhop;
-  struct in_addr *gate;
+  union g_addr *gate;
   route_map_result_t ret = RMAP_MATCH;
 
   if (rmap_name)
@@ -563,9 +563,9 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char
     {
       if (rn->p.family == AF_INET)
         {
-          p4.family = AF_INET;
-          p4.prefixlen = rn->p.prefixlen;
-          p4.prefix = rn->p.u.prefix4;
+          p.family = AF_INET;
+          p.prefixlen = rn->p.prefixlen;
+          p.u.prefix4 = rn->p.u.prefix4;
 
           if (rib->nexthop_num == 1)
            {
@@ -573,14 +573,13 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char
              if (nhop->type == NEXTHOP_TYPE_IFINDEX)
                gate = NULL;
              else
-               gate = &nhop->gate.ipv4;
-
-             rib_add_ipv4(ZEBRA_ROUTE_TABLE, rib->table, 0, &p4,
-                           gate, &nhop->src.ipv4,
-                          nhop->ifindex, rib->vrf_id, zebrad.rtm_table_default,
-                          rib->metric, rib->mtu,
-                          zebra_import_table_distance[AFI_IP][rib->table],
-                          SAFI_UNICAST);
+               gate = (union g_addr *)&nhop->gate.ipv4;
+
+             rib_add (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE,
+                      rib->table, 0, &p, gate, (union g_addr *)&nhop->src.ipv4,
+                      nhop->ifindex, zebrad.rtm_table_default,
+                      rib->metric, rib->mtu,
+                      zebra_import_table_distance[AFI_IP][rib->table]);
            }
           else if (rib->nexthop_num > 1)
            {
@@ -599,7 +598,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char
              for (nhop = rib->nexthop; nhop; nhop = nhop->next)
                rib_copy_nexthops(newrib, nhop);
 
-             rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST);
+             rib_add_ipv4_multipath((struct prefix_ipv4 *)&p, newrib, SAFI_UNICAST);
            }
         }
     }
index 8b70de7a0309eacfef5bd8ac9113b8c1206f3927..e51e1277bf6120bd04bc25f632a996e4c0d3479d 100644 (file)
@@ -338,10 +338,11 @@ extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib);
 /* NOTE:
  * All rib_add_ipv[46]* functions will not just add prefix into RIB, but
  * also implicitly withdraw equal prefix of same type. */
-extern int rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
-                        struct in_addr *gate, struct in_addr *src,
-                        ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id,
-                        u_int32_t, u_int32_t, u_char, safi_t);
+extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
+                   u_short instance, int flags, struct prefix *p,
+                   union g_addr *gate, union g_addr *src,
+                   ifindex_t ifindex, u_int32_t table_id,
+                   u_int32_t, u_int32_t, u_char);
 
 extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);
 
index dc3aa2f6bb42271611468d7d2e2b2de1ce701e03..be291c0c9b2dc08383512c90e9aae486f121d46e 100644 (file)
@@ -860,6 +860,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
   struct rtmsg *rtm;
   struct rtattr *tb[RTA_MAX + 1];
   u_char flags = 0;
+  struct prefix p;
 
   char anyaddr[16] = { 0 };
 
@@ -952,14 +953,14 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
 
   if (rtm->rtm_family == AF_INET)
     {
-      struct prefix_ipv4 p;
       p.family = AF_INET;
-      memcpy (&p.prefix, dest, 4);
+      memcpy (&p.u.prefix4, dest, 4);
       p.prefixlen = rtm->rtm_dst_len;
 
       if (!tb[RTA_MULTIPATH])
-          rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, src, index,
-                        vrf_id, table, metric, mtu, 0, SAFI_UNICAST);
+       rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+                0, flags, &p, gate, src, index,
+                table, metric, mtu, 0);
       else
         {
           /* This is a multipath route */
@@ -1016,21 +1017,19 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
           if (rib->nexthop_num == 0)
             XFREE (MTYPE_RIB, rib);
           else
-            rib_add_ipv4_multipath (&p, rib, SAFI_UNICAST);
+            rib_add_ipv4_multipath ((struct prefix_ipv4 *)&p, rib, SAFI_UNICAST);
         }
     }
-#ifdef HAVE_IPV6
   if (rtm->rtm_family == AF_INET6)
     {
-      struct prefix_ipv6 p;
       p.family = AF_INET6;
-      memcpy (&p.prefix, dest, 16);
+      memcpy (&p.u.prefix6, dest, 16);
       p.prefixlen = rtm->rtm_dst_len;
 
-      rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, flags, &p, gate, index, vrf_id,
-                    table, metric, mtu, 0, SAFI_UNICAST);
+      rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+              0, flags, &p, gate, src, index,
+              table, metric, mtu, 0);
     }
-#endif /* HAVE_IPV6 */
 
   return 0;
 }
@@ -1193,8 +1192,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
       if (h->nlmsg_type == RTM_NEWROUTE)
         {
           if (!tb[RTA_MULTIPATH])
-            rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv4 *)&p, gate, src, index, vrf_id,
-                          table, metric, mtu, 0, SAFI_UNICAST);
+            rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+                    0, 0, &p, gate, src, index,
+                    table, metric, mtu, 0);
           else
             {
               /* This is a multipath route */
@@ -1277,8 +1277,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
         }
 
       if (h->nlmsg_type == RTM_NEWROUTE)
-        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, 0, (struct prefix_ipv6 *)&p, gate, index, vrf_id,
-                      table, metric, mtu, 0, SAFI_UNICAST);
+        rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
+                0, 0, &p, gate, src, index,
+                table, metric, mtu, 0);
       else
         rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL,
                    0, zebra_flags, &p, gate, index, table);
index 9defa49bfd70a9c20d9d8bb9a49e70fac7ed0a58..0facc1a19fb5fe850c70a9a6a685ce48db8a97da 100644 (file)
 static void 
 handle_route_entry (mib2_ipRouteEntry_t *routeEntry)
 {
-       struct prefix_ipv4      prefix;
-       struct in_addr          tmpaddr, gateway;
-       u_char                  zebra_flags = 0;
+  struct prefix        prefix;
+  struct in_addr               tmpaddr, gateway;
+  union g_addr *ggateway;
+  u_char                       zebra_flags = 0;
 
-       if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
-               return;
+  if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
+    return;
 
-       if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT)
-               zebra_flags |= ZEBRA_FLAG_SELFROUTE;
+  if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT)
+    zebra_flags |= ZEBRA_FLAG_SELFROUTE;
 
-       prefix.family = AF_INET;
+  prefix.family = AF_INET;
 
-       tmpaddr.s_addr = routeEntry->ipRouteDest;
-       prefix.prefix = tmpaddr;
+  tmpaddr.s_addr = routeEntry->ipRouteDest;
+  prefix.u.prefix4 = tmpaddr;
 
-       tmpaddr.s_addr = routeEntry->ipRouteMask;
-       prefix.prefixlen = ip_masklen (tmpaddr);
+  tmpaddr.s_addr = routeEntry->ipRouteMask;
+  prefix.prefixlen = ip_masklen (tmpaddr);
 
-       gateway.s_addr = routeEntry->ipRouteNextHop;
+  gateway.s_addr = routeEntry->ipRouteNextHop;
+  ggateway = (union g_addr *)&gateway;
 
-       rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix,
-                     &gateway, NULL, 0, VRF_DEFAULT, 0, 0, 0, 0, SAFI_UNICAST);
+  rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
+          zebra_flags, &prefix, ggateway, NULL, 0, 0, 0, 0, 0);
 }
 
 void
index 0dbbd47a45badac8d24f33d3a8328dcd2fffcb57..17d59236f8f60af1f809522bd79ba7b30c4acacb 100644 (file)
@@ -2354,124 +2354,6 @@ rib_delnode (struct route_node *rn, struct rib *rib)
     }
 }
 
-int
-rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p,
-             struct in_addr *gate, struct in_addr *src,
-             ifindex_t ifindex, vrf_id_t vrf_id, u_int32_t table_id,
-             u_int32_t metric, u_int32_t mtu, u_char distance, safi_t safi)
-{
-  struct rib *rib;
-  struct rib *same = NULL;
-  struct route_table *table;
-  struct route_node *rn;
-  struct nexthop *nexthop;
-
-  /* Lookup table.  */
-  table = zebra_vrf_table_with_table_id (AFI_IP, safi, vrf_id, table_id);
-  if (! table)
-    return 0;
-
-  /* Make it sure prefixlen is applied to the prefix. */
-  apply_mask_ipv4 (p);
-
-  /* Set default distance by route type. */
-  if (distance == 0)
-    {
-      if ((unsigned)type >= array_size(route_info))
-       distance = 150;
-      else
-        distance = route_info[type].distance;
-
-      /* iBGP distance is 200. */
-      if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
-       distance = 200;
-    }
-
-  /* Lookup route node.*/
-  rn = route_node_get (table, (struct prefix *) p);
-
-  /* If same type of route are installed, treat it as a implicit
-     withdraw. */
-  RNODE_FOREACH_RIB (rn, rib)
-    {
-      if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
-        continue;
-      
-      if (rib->type != type)
-       continue;
-      if (rib->instance != instance)
-       continue;
-
-      if (rib->type != ZEBRA_ROUTE_CONNECT)
-        {
-          same = rib;
-          break;
-        }
-      /* Duplicate connected route comes in. */
-      else if ((nexthop = rib->nexthop) &&
-              nexthop->type == NEXTHOP_TYPE_IFINDEX &&
-              nexthop->ifindex == ifindex &&
-              !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
-       {
-         rib->refcnt++;
-         return 0 ;
-       }
-    }
-
-  /* Allocate new rib structure. */
-  rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
-  rib->type = type;
-  rib->instance = instance;
-  rib->distance = distance;
-  rib->flags = flags;
-  rib->metric = metric;
-  rib->mtu = mtu;
-  rib->table = table_id;
-  rib->vrf_id = vrf_id;
-  rib->nexthop_num = 0;
-  rib->uptime = time (NULL);
-
-  /* Nexthop settings. */
-  if (gate)
-    {
-      if (ifindex)
-       rib_nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
-      else
-       rib_nexthop_ipv4_add (rib, gate, src);
-    }
-  else
-    rib_nexthop_ifindex_add (rib, ifindex);
-
-  /* If this route is kernel route, set FIB flag to the route. */
-  if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT)
-    for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
-      SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
-
-  /* Link new rib to node.*/
-  if (IS_ZEBRA_DEBUG_RIB)
-    {
-      char buf[INET6_ADDRSTRLEN];
-      if (IS_ZEBRA_DEBUG_RIB)
-        {
-          inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN);
-          zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
-                      "existing %p",
-                      vrf_id, buf, p->prefixlen, (void *)rn, (void *)rib, rib->type, (void *)same);
-        }
-
-      if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-        rib_dump ((struct prefix *)p, rib);
-    }
-  rib_addnode (rn, rib, 1);
-  
-  /* Free implicit route.*/
-  if (same)
-    rib_delnode (rn, same);
-  
-  route_unlock_node (rn);
-  return 0;
-}
-
 /* This function dumps the contents of a given RIB entry into
  * standard debug log. Calling function name and IP prefix in
  * question are passed as 1st and 2nd arguments.
@@ -2854,10 +2736,11 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
 
 
 int
-rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
-             struct in6_addr *gate, ifindex_t ifindex, vrf_id_t vrf_id,
-              u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
-             u_char distance, safi_t safi)
+rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
+        u_short instance, int flags, struct prefix *p,
+        union g_addr *gate, union g_addr *src, ifindex_t ifindex,
+        u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
+        u_char distance)
 {
   struct rib *rib;
   struct rib *same = NULL;
@@ -2866,22 +2749,28 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
   struct nexthop *nexthop;
 
   /* Lookup table.  */
-  table = zebra_vrf_table_with_table_id (AFI_IP6, safi, vrf_id, table_id);
+  table = zebra_vrf_table_with_table_id (afi, safi, vrf_id, table_id);
   if (! table)
     return 0;
 
   /* Make sure mask is applied. */
-  apply_mask_ipv6 (p);
+  apply_mask (p);
 
   /* Set default distance by route type. */
-  if (!distance)
-    distance = route_info[type].distance;
-  
-  if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
-    distance = 200;
+  if (distance == 0)
+    {
+      if ((unsigned)type >= array_size(route_info))
+       distance = 150;
+      else
+        distance = route_info[type].distance;
+
+      /* iBGP distance is 200. */
+      if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP))
+       distance = 200;
+    }
 
   /* Lookup route node.*/
-  rn = route_node_get (table, (struct prefix *) p);
+  rn = route_node_get (table,  p);
 
   /* If same type of route are installed, treat it as a implicit
      withdraw. */
@@ -2899,12 +2788,14 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
          same = rib;
          break;
        }
+      /* Duplicate connected route comes in. */
       else if ((nexthop = rib->nexthop) &&
               nexthop->type == NEXTHOP_TYPE_IFINDEX &&
-              nexthop->ifindex == ifindex)
+              nexthop->ifindex == ifindex &&
+              !CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
        {
          rib->refcnt++;
-         return 0;
+         return 0 ;
        }
     }
 
@@ -2925,10 +2816,20 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
   /* Nexthop settings. */
   if (gate)
     {
-      if (ifindex)
-       rib_nexthop_ipv6_ifindex_add (rib, gate, ifindex);
+      if (afi == AFI_IP6)
+       {
+         if (ifindex)
+           rib_nexthop_ipv6_ifindex_add (rib, &gate->ipv6, ifindex);
+         else
+           rib_nexthop_ipv6_add (rib, &gate->ipv6);
+       }
       else
-       rib_nexthop_ipv6_add (rib, gate);
+       {
+         if (ifindex)
+           rib_nexthop_ipv4_ifindex_add (rib, &gate->ipv4, &src->ipv4, ifindex);
+         else
+           rib_nexthop_ipv4_add (rib, &gate->ipv4, &src->ipv4);
+       }
     }
   else
     rib_nexthop_ifindex_add (rib, ifindex);
@@ -2944,7 +2845,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
       char buf[INET6_ADDRSTRLEN];
       if (IS_ZEBRA_DEBUG_RIB)
         {
-          inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN);
+          inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
           zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) "
                       "existing %p",
                       vrf_id, buf, p->prefixlen, (void *)rn,
@@ -2952,7 +2853,7 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p,
         }
 
       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-        rib_dump ((struct prefix *)p, rib);
+        rib_dump (p, rib);
     }
   rib_addnode (rn, rib, 1);