]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge branch 'cmaster' of ssh://stash.cumulusnetworks.com:7999/quag/quagga into cmaster
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 27 Nov 2015 16:47:38 +0000 (08:47 -0800)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 27 Nov 2015 16:47:38 +0000 (08:47 -0800)
1  2 
zebra/redistribute.c
zebra/rib.h
zebra/rt_netlink.c
zebra/zebra_rib.c
zebra/zserv.c

diff --combined zebra/redistribute.c
index e547d1e2d325f01400ec4cb3d45fccd717fdf213,ba7945ad23c5ec5523e35812f2b222b81e02dbf3..1899a4d114a6f75d18e361b24cf8da0185474850
@@@ -181,6 -181,15 +181,15 @@@ redistribute_update (struct prefix *p, 
    struct zserv *client;
    int send_redistribute;
    int afi;
+   char buf[INET6_ADDRSTRLEN];
+   if (IS_ZEBRA_DEBUG_RIB)
+     {
+       inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
+       zlog_debug ("%u:%s/%d: Redist update rib %p (type %d), old %p (type %d)",
+                   rib->vrf_id, buf, p->prefixlen, rib, rib->type,
+                   prev_rib, prev_rib ? prev_rib->type : -1);
+     }
  
    afi = family2afi(p->family);
    if (!afi)
@@@ -254,6 -263,14 +263,14 @@@ redistribute_delete (struct prefix *p, 
  {
    struct listnode *node, *nnode;
    struct zserv *client;
+   char buf[INET6_ADDRSTRLEN];
+   if (IS_ZEBRA_DEBUG_RIB)
+     {
+       inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
+       zlog_debug ("%u:%s/%d: Redist delete rib %p (type %d)",
+                   rib->vrf_id, buf, p->prefixlen, rib, rib->type);
+     }
  
    /* Add DISTANCE_INFINITY check. */
    if (rib->distance == DISTANCE_INFINITY)
@@@ -544,7 -561,7 +561,7 @@@ zebra_add_import_table_entry (struct ro
  
          /* Assuming these routes are never recursive */
          for (nhop = rib->nexthop; nhop; nhop = nhop->next)
 -          copy_nexthops(newrib, nhop);
 +          rib_copy_nexthops(newrib, nhop);
  
          rib_add_ipv4_multipath(&p4, newrib, SAFI_UNICAST);
        }
diff --combined zebra/rib.h
index 56ea597550b211b4d463b65833fb542f77b6ef2d,1f045310a57c314afb6c6533bd4d52fc5c451226..aefe437be2756fa84494684c29b38a00cf6cc8b2
@@@ -259,16 -259,7 +259,7 @@@ struct static_rout
                                        : ((tnexthop) = (nexthop)->next)) \
                         : (((recursing) = 0),((tnexthop) = (tnexthop)->next)))
  
- /* Router advertisement feature. */
- #ifndef RTADV
- #if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
-   #ifdef HAVE_RTADV
-     #define RTADV
-   #endif
- #endif
- #endif
- #if defined (RTADV)
+ #if defined (HAVE_RTADV)
  /* Structure which hold status of router advertisement. */
  struct rtadv
  {
    struct thread *ra_read;
    struct thread *ra_timer;
  };
- #endif /* RTADV */
+ #endif /* HAVE_RTADV */
  
  #ifdef HAVE_NETLINK
  /* Socket interface to kernel */
@@@ -338,9 -329,9 +329,9 @@@ struct zebra_vr
    struct list *rid_lo_sorted_list;
    struct prefix rid_user_assigned;
  
- #if defined (RTADV)
+ #if defined (HAVE_RTADV)
    struct rtadv rtadv;
- #endif /* RTADV */
+ #endif /* HAVE_RTADV */
  };
  
  /*
@@@ -380,17 -371,19 +371,17 @@@ typedef struct rib_tables_iter_t
    rib_tables_iter_state_t state;
  } rib_tables_iter_t;
  
 -extern struct nexthop *nexthop_ifindex_add (struct rib *, unsigned int);
 -extern struct nexthop *nexthop_ifname_add (struct rib *, char *);
 -extern struct nexthop *nexthop_blackhole_add (struct rib *);
 -extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *,
 -                                       struct in_addr *);
 -extern struct nexthop *nexthop_ipv4_ifindex_add (struct rib *,
 -                                                 struct in_addr *,
 -                                                 struct in_addr *,
 -                                                 unsigned int);
 -extern void nexthop_free (struct nexthop *nexthop, struct route_node *);
 -extern void nexthops_free (struct nexthop *nexthop, struct route_node *);
 -extern void nexthop_add (struct rib *rib, struct nexthop *nexthop);
 -extern void copy_nexthops (struct rib *rib, struct nexthop *nh);
 +extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, unsigned int);
 +extern struct nexthop *rib_nexthop_ifname_add (struct rib *, char *);
 +extern struct nexthop *rib_nexthop_blackhole_add (struct rib *);
 +extern struct nexthop *rib_nexthop_ipv4_add (struct rib *, struct in_addr *,
 +                                           struct in_addr *);
 +extern struct nexthop *rib_nexthop_ipv4_ifindex_add (struct rib *,
 +                                                   struct in_addr *,
 +                                                   struct in_addr *,
 +                                                   unsigned int);
 +extern void rib_nexthop_add (struct rib *rib, struct nexthop *nexthop);
 +extern void rib_copy_nexthops (struct rib *rib, struct nexthop *nh);
  
  extern int nexthop_has_fib_child(struct nexthop *);
  extern void rib_lookup_and_dump (struct prefix_ipv4 *);
@@@ -406,13 -399,12 +397,13 @@@ extern int rib_lookup_ipv4_route (struc
  #define ZEBRA_RIB_FOUND_CONNECTED 2
  #define ZEBRA_RIB_NOTFOUND 3
  
 -extern struct nexthop *nexthop_ipv6_add (struct rib *, struct in6_addr *);
 -extern struct nexthop *nexthop_ipv6_ifindex_add (struct rib *rib,
 -                      struct in6_addr *ipv6, unsigned int ifindex);
 -extern struct nexthop *nexthop_ipv6_ifname_add (struct rib *rib,
 -                                              struct in6_addr *ipv6,
 -                                              char *ifname);
 +extern struct nexthop *rib_nexthop_ipv6_add (struct rib *, struct in6_addr *);
 +extern struct nexthop *rib_nexthop_ipv6_ifindex_add (struct rib *rib,
 +                                                   struct in6_addr *ipv6,
 +                                                   unsigned int ifindex);
 +extern struct nexthop *rib_nexthop_ipv6_ifname_add (struct rib *rib,
 +                                                  struct in6_addr *ipv6,
 +                                                  char *ifname);
  
  extern struct zebra_vrf *zebra_vrf_lookup (vrf_id_t vrf_id);
  extern struct zebra_vrf *zebra_vrf_alloc (vrf_id_t);
diff --combined zebra/rt_netlink.c
index d528c0352e67ed47e90731fdd9c0ff8e93aea8ac,5640168deac89ffb678abdd67c0fdc074cee9f0a..97a73ddbca8a6d68ef3c943ab68f221ea8fc3819
@@@ -497,6 -497,9 +497,9 @@@ netlink_interface (struct sockaddr_nl *
    if (len < 0)
      return -1;
  
+   if (ifi->ifi_family == AF_BRIDGE)
+     return 0;
    /* Looking up interface name. */
    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
@@@ -575,8 -578,9 +578,9 @@@ netlink_interface_addr (struct sockaddr
    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]),
    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,
@@@ -791,12 -801,12 +801,12 @@@ netlink_routing_table (struct sockaddr_
                if (gate)
                  {
                    if (index)
 -                    nexthop_ipv4_ifindex_add (rib, gate, src, index);
 +                    rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
                    else
 -                    nexthop_ipv4_add (rib, gate, src);
 +                    rib_nexthop_ipv4_add (rib, gate, src);
                  }
                else
 -                nexthop_ifindex_add (rib, index);
 +                rib_nexthop_ifindex_add (rib, index);
  
                len -= NLMSG_ALIGN(rtnh->rtnh_len);
                rtnh = RTNH_NEXT(rtnh);
@@@ -996,12 -1006,12 +1006,12 @@@ netlink_route_change (struct sockaddr_n
                    if (gate)
                      {
                        if (index)
 -                        nexthop_ipv4_ifindex_add (rib, gate, src, index);
 +                        rib_nexthop_ipv4_ifindex_add (rib, gate, src, index);
                        else
 -                        nexthop_ipv4_add (rib, gate, src);
 +                        rib_nexthop_ipv4_add (rib, gate, src);
                      }
                    else
 -                    nexthop_ifindex_add (rib, index);
 +                    rib_nexthop_ifindex_add (rib, index);
  
                    len -= NLMSG_ALIGN(rtnh->rtnh_len);
                    rtnh = RTNH_NEXT(rtnh);
@@@ -1074,6 -1084,9 +1084,9 @@@ netlink_link_change (struct sockaddr_n
    if (len < 0)
      return -1;
  
+   if (ifi->ifi_family == AF_BRIDGE)
+     return 0;
    /* Looking up interface name. */
    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
@@@ -2112,6 -2125,12 +2125,12 @@@ kernel_add_ipv6 (struct prefix *p, stru
      }
  }
  
+ int
+ kernel_update_ipv6 (struct prefix *p, struct rib *rib)
+ {
+   return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6, 1);
+ }
  int
  kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
  {
diff --combined zebra/zebra_rib.c
index 36bcfc859f66fb57ed27a75bc21504ed46e1c2f7,d1f679361a1dbf96d849fcae2f257514fd8226e2..e2d7119e03a33bbccdac717fa619da5fff1f3aa6
@@@ -80,6 -80,31 +80,6 @@@ static const struc
    /* no entry/default: 150 */
  };
  
 -/*
 - * nexthop_type_to_str
 - */
 -const char *
 -nexthop_type_to_str (enum nexthop_types_t nh_type)
 -{
 -  static const char *desc[] = {
 -    "none",
 -    "Directly connected",
 -    "Interface route",
 -    "IPv4 nexthop",
 -    "IPv4 nexthop with ifindex",
 -    "IPv4 nexthop with ifname",
 -    "IPv6 nexthop",
 -    "IPv6 nexthop with ifindex",
 -    "IPv6 nexthop with ifname",
 -    "Null0 nexthop",
 -  };
 -
 -  if (nh_type >= ZEBRA_NUM_OF (desc))
 -    return "<Invalid nh type>";
 -
 -  return desc[nh_type];
 -}
 -
  int
  is_zebra_valid_kernel_table(u_int32_t table_id)
  {
@@@ -125,21 -150,57 +125,21 @@@ zebra_check_addr (struct prefix *p
    return 1;
  }
  
 -/* Add nexthop to the end of a nexthop list.  */
 -static void
 -_nexthop_add (struct nexthop **target, struct nexthop *nexthop)
 -{
 -  struct nexthop *last;
 -
 -  for (last = *target; last && last->next; last = last->next)
 -    ;
 -  if (last)
 -    last->next = nexthop;
 -  else
 -    *target = nexthop;
 -  nexthop->prev = last;
 -}
 -
  /* Add nexthop to the end of a rib node's nexthop list */
  void
 -nexthop_add (struct rib *rib, struct nexthop *nexthop)
 +rib_nexthop_add (struct rib *rib, struct nexthop *nexthop)
  {
 -  _nexthop_add(&rib->nexthop, nexthop);
 +  nexthop_add(&rib->nexthop, nexthop);
    rib->nexthop_num++;
  }
  
 -static void
 -_copy_nexthops (struct nexthop **tnh, struct nexthop *nh)
 -{
 -  struct nexthop *nexthop;
 -  struct nexthop *nh1;
 -
 -  for (nh1 = nh; nh1; nh1 = nh1->next)
 -    {
 -      nexthop = nexthop_new();
 -      nexthop->flags = nh->flags;
 -      nexthop->type = nh->type;
 -      nexthop->ifindex = nh->ifindex;
 -      if (nh->ifname)
 -      nexthop->ifname = XSTRDUP(0, nh->ifname);
 -      memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
 -      memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
 -      _nexthop_add(tnh, nexthop);
  
 -      if (CHECK_FLAG(nh1->flags, NEXTHOP_FLAG_RECURSIVE))
 -      _copy_nexthops(&nexthop->resolved, nh1->resolved);
 -    }
 -}
  
  /**
   * copy_nexthop - copy a nexthop to the rib structure.
   */
  void
 -copy_nexthops (struct rib *rib, struct nexthop *nh)
 +rib_copy_nexthops (struct rib *rib, struct nexthop *nh)
  {
    struct nexthop *nexthop;
  
      nexthop->ifname = XSTRDUP(0, nh->ifname);
    memcpy(&(nexthop->gate), &(nh->gate), sizeof(union g_addr));
    memcpy(&(nexthop->src), &(nh->src), sizeof(union g_addr));
 -  nexthop_add(rib, nexthop);
 +  rib_nexthop_add(rib, nexthop);
    if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE))
 -    _copy_nexthops(&nexthop->resolved, nh->resolved);
 +    copy_nexthops(&nexthop->resolved, nh->resolved);
  }
  
  /* Delete specified nexthop from the list. */
  static void
 -nexthop_delete (struct rib *rib, struct nexthop *nexthop)
 +rib_nexthop_delete (struct rib *rib, struct nexthop *nexthop)
  {
    if (nexthop->next)
      nexthop->next->prev = nexthop->prev;
    rib->nexthop_num--;
  }
  
 -/* Free nexthop. */
 -void
 -nexthop_free (struct nexthop *nexthop, struct route_node *rn)
 -{
 -  if (nexthop->ifname)
 -    XFREE (0, nexthop->ifname);
 -  if (nexthop->resolved)
 -    nexthops_free(nexthop->resolved, rn);
 -  XFREE (MTYPE_NEXTHOP, nexthop);
 -}
 -
 -/* Frees a list of nexthops */
 -void
 -nexthops_free (struct nexthop *nexthop, struct route_node *rn)
 -{
 -  struct nexthop *nh, *next;
 -  struct prefix nh_p;
  
 -  for (nh = nexthop; nh; nh = next)
 -    {
 -      next = nh->next;
 -      if (nh->type == NEXTHOP_TYPE_IPV4)
 -      {
 -        nh_p.family = AF_INET;
 -        nh_p.prefixlen = IPV4_MAX_BITLEN;
 -        nh_p.u.prefix4 = nh->gate.ipv4;
 -        zebra_deregister_rnh_static_nh(&nh_p, rn);
 -      }
 -      else if (nh->type == NEXTHOP_TYPE_IPV6)
 -      {
 -        nh_p.family = AF_INET6;
 -        nh_p.prefixlen = IPV6_MAX_BITLEN;
 -        nh_p.u.prefix6 = nh->gate.ipv6;
 -        zebra_deregister_rnh_static_nh(&nh_p, rn);
 -      }
 -      nexthop_free (nh, rn);
 -    }
 -}
  
  struct nexthop *
 -nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
 +rib_nexthop_ifindex_add (struct rib *rib, unsigned int ifindex)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IFINDEX;
    nexthop->ifindex = ifindex;
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ifname_add (struct rib *rib, char *ifname)
 +rib_nexthop_ifname_add (struct rib *rib, char *ifname)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IFNAME;
    nexthop->ifname = XSTRDUP (0, ifname);
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
 +rib_nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IPV4;
    nexthop->gate.ipv4 = *ipv4;
    if (src)
      nexthop->src.ipv4 = *src;
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, 
 -                          struct in_addr *src, unsigned int ifindex)
 +rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4,
 +                            struct in_addr *src, unsigned int ifindex)
  {
    struct nexthop *nexthop;
    struct interface *ifp;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
    nexthop->gate.ipv4 = *ipv4;
    if (src)
      SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
     }
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
 +rib_nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IPV6;
    nexthop->gate.ipv6 = *ipv6;
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
 -                       char *ifname)
 +rib_nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6,
 +                           char *ifname)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME;
    nexthop->gate.ipv6 = *ipv6;
    nexthop->ifname = XSTRDUP (0, ifname);
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
 -                        unsigned int ifindex)
 +rib_nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6,
 +                            unsigned int ifindex)
  {
    struct nexthop *nexthop;
  
    nexthop->gate.ipv6 = *ipv6;
    nexthop->ifindex = ifindex;
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
  
  struct nexthop *
 -nexthop_blackhole_add (struct rib *rib)
 +rib_nexthop_blackhole_add (struct rib *rib)
  {
    struct nexthop *nexthop;
  
 -  nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
 +  nexthop = nexthop_new();
    nexthop->type = NEXTHOP_TYPE_BLACKHOLE;
    SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE);
  
 -  nexthop_add (rib, nexthop);
 +  rib_nexthop_add (rib, nexthop);
  
    return nexthop;
  }
@@@ -338,8 -436,7 +338,8 @@@ nexthop_active_ipv4 (struct rib *rib, s
    if (set)
      {
        UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
 -      nexthops_free(nexthop->resolved, top);
 +      zebra_deregister_rnh_static_nexthops(nexthop->resolved, top);
 +      nexthops_free(nexthop->resolved);
        nexthop->resolved = NULL;
      }
  
                            resolved_hop->ifindex = newhop->ifindex;
                          }
  
 -                      _nexthop_add(&nexthop->resolved, resolved_hop);
 +                      nexthop_add(&nexthop->resolved, resolved_hop);
                      }
                    resolved = 1;
                  }
                            resolved_hop->ifindex = newhop->ifindex;
                          }
  
 -                      _nexthop_add(&nexthop->resolved, resolved_hop);
 +                      nexthop_add(&nexthop->resolved, resolved_hop);
                      }
                    resolved = 1;
                  }
@@@ -566,8 -663,7 +566,8 @@@ nexthop_active_ipv6 (struct rib *rib, s
    if (set)
      {
        UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
 -      nexthops_free(nexthop->resolved, top);
 +      zebra_deregister_rnh_static_nexthops (nexthop->resolved, top);
 +      nexthops_free(nexthop->resolved);
        nexthop->resolved = NULL;
      }
  
                                resolved_hop->ifindex = newhop->ifindex;
                          }
  
 -                      _nexthop_add(&nexthop->resolved, resolved_hop);
 +                      nexthop_add(&nexthop->resolved, resolved_hop);
                      }
                    resolved = 1;
                  }
                                resolved_hop->ifindex = newhop->ifindex;
                          }
  
 -                      _nexthop_add(&nexthop->resolved, resolved_hop);
 +                      nexthop_add(&nexthop->resolved, resolved_hop);
                      }
                    resolved = 1;
                  }
@@@ -1107,8 -1203,8 +1107,8 @@@ nexthop_active_check (struct route_nod
        if (IS_ZEBRA_DEBUG_RIB)
        {
          inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
-         zlog_debug("%s: Filtering out %s with NH out %s due to route map",
-                    __FUNCTION__, buf, nexthop->ifname);
+         zlog_debug("%u:%s/%d: Filtering out with NH out %s due to route map",
+                    rib->vrf_id, buf, rn->p.prefixlen, nexthop->ifname);
        }
        UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE);
      }
@@@ -1196,7 -1292,10 +1196,10 @@@ rib_install_kernel (struct route_node *
          ret = kernel_add_ipv4 (&rn->p, rib);
        break;
      case AF_INET6:
-       ret = kernel_add_ipv6 (&rn->p, rib);
+       if (update)
+         ret = kernel_update_ipv6 (&rn->p, rib);
+       else
+         ret = kernel_add_ipv6 (&rn->p, rib);
        break;
      }
  
@@@ -1292,6 -1391,7 +1295,7 @@@ rib_gc_dest (struct route_node *rn
  {
    rib_dest_t *dest;
    char buf[INET6_ADDRSTRLEN];
+   struct zebra_vrf *zvrf;
  
    dest = rib_dest_from_rnode (rn);
    if (!dest)
    if (!rib_can_delete_dest (dest))
      return 0;
  
-   if (IS_ZEBRA_DEBUG_RIB)
+   zvrf = rib_dest_vrf (dest);
+   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
      {
        inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf));
-       zlog_debug ("%s: %s/%d: removing dest from table", __func__,
-                 buf, rn->p.prefixlen);
+       zlog_debug ("%u:%s/%d: rn %p removing dest",
+                 zvrf->vrf_id, buf, rn->p.prefixlen, rn);
      }
  
    dest->rnode = NULL;
@@@ -1331,15 -1432,33 +1336,33 @@@ rib_process (struct route_node *rn
    struct nexthop *nexthop = NULL, *tnexthop;
    int recursing;
    char buf[INET6_ADDRSTRLEN];
-   int update_ok = 0;
-   
+   rib_dest_t *dest;
+   struct zebra_vrf *zvrf = NULL;
+   vrf_id_t vrf_id = 0;
    assert (rn);
    
-   if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q)
+   dest = rib_dest_from_rnode (rn);
+   if (dest)
+     {
+       zvrf = rib_dest_vrf (dest);
+       vrf_id = zvrf->vrf_id;
+     }
+   
+   if (IS_ZEBRA_DEBUG_RIB)
      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
  
+   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+     zlog_debug ("%u:%s/%d: Processing rn %p", vrf_id, buf, rn->p.prefixlen, rn);
    RNODE_FOREACH_RIB_SAFE (rn, rib, next)
      {
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+         zlog_debug ("%u:%s/%d: Examine rib %p (type %d) status %x flags %x "
+                     "dist %d metric %d",
+                     vrf_id, buf, rn->p.prefixlen, rib, rib->type, rib->status,
+                     rib->flags, rib->distance, rib->metric);
        UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
  
        /* Currently installed rib. */
            if (rib != fib)
              {
                if (IS_ZEBRA_DEBUG_RIB)
-                 zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__,
-                   buf, rn->p.prefixlen, rn, rib);
+                 zlog_debug ("%u:%s/%d: Freeing route rn %p, rib %p (type %d)",
+                             vrf_id, buf, rn->p.prefixlen, rn, rib, rib->type);
              rib_unlink (rn, rib);
              }
            else
     * del    --- equal to fib, if fib is queued for deletion, NULL otherwise
     * rib    --- NULL
     */
+   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+     zlog_debug ("%u:%s/%d: After processing: select %p fib %p del %p",
+                 vrf_id, buf, rn->p.prefixlen, select, fib, del);
  
    /* Same RIB entry is selected. Update FIB and finish. */
    if (select && select == fib)
      {
-       if (IS_ZEBRA_DEBUG_RIB)
-         zlog_debug ("%s: %s/%d: Updating existing route, select %p, fib %p",
-                      __func__, buf, rn->p.prefixlen, select, fib);
        if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED))
          {
          zfpm_trigger_update (rn, "updating existing route");
  
-           if (! RIB_SYSTEM_ROUTE (select))
-             {
-               /* For v4, use the replace semantics of netlink. */
-               if (PREFIX_FAMILY (&rn->p) == AF_INET)
-                 update_ok = 1;
-               else
-                 rib_uninstall_kernel (rn, select);
-             }
            /* Set real nexthop. */
          /* Need to check if any NHs are active to clear the
           * the selected flag
           */
            if (nexthop_active_update (rn, select, 1))
            {
-               /* Clear FIB flag for IPv4, install will set it */
-               if (update_ok)
+               if (IS_ZEBRA_DEBUG_RIB)
+                 zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d)",
+                             vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
+             if (! RIB_SYSTEM_ROUTE (select))
                  {
+                   /* Clear FIB flag if performing a replace, will get set again
+                    * as part of install.
+                    */
                    for (nexthop = select->nexthop; nexthop; nexthop = nexthop->next)
                      UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+                   rib_install_kernel (rn, select, 1);
                  }
-             if (! RIB_SYSTEM_ROUTE (select))
-               rib_install_kernel (rn, select, update_ok);
  
              /* assuming that the receiver knows how to dedup */
                redistribute_update (&rn->p, select, NULL);
            }
          else
            {
+               if (IS_ZEBRA_DEBUG_RIB)
+                 zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) "
+                             "- nexthop inactive",
+                             vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
              /* Withdraw unreachable redistribute route */
              redistribute_delete(&rn->p, select);
  
-               /* For IPv4, do the uninstall here. */
-               if (update_ok)
+               /* Do the uninstall here, if not done earlier. */
+             if (! RIB_SYSTEM_ROUTE (select))
                  rib_uninstall_kernel (rn, select);
              UNSET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
            }
     */
    if (fib)
      {
-       if (IS_ZEBRA_DEBUG_RIB)
-         zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__,
-           buf, rn->p.prefixlen, fib);
        zfpm_trigger_update (rn, "removing existing route");
  
-       /* If there's no route to replace this with, withdraw redistribute */
+       /* If there's no route to replace this with, withdraw redistribute and
+        * uninstall from kernel.
+        */
        if (!select)
-       redistribute_delete(&rn->p, fib);
-       if (! RIB_SYSTEM_ROUTE (fib))
          {
-           /* For v4, use the replace semantics of netlink -- only if there is
-            * another route to replace this with.
-            */
-           if (PREFIX_FAMILY (&rn->p) == AF_INET)
-             {
-               if (!select)
-                 rib_uninstall_kernel (rn, fib);
-               else
-                 update_ok = 1;
-             }
-             else
-               rib_uninstall_kernel (rn, fib);
+           if (IS_ZEBRA_DEBUG_RIB)
+             zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d)",
+                         vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type);
+         redistribute_delete(&rn->p, fib);
+           if (! RIB_SYSTEM_ROUTE (fib))
+             rib_uninstall_kernel (rn, fib);
          }
        UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED);
  
        /* Set real nexthop. */
     */
    if (select)
      {
-       if (IS_ZEBRA_DEBUG_RIB)
-         zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf,
-           rn->p.prefixlen, select);
        zfpm_trigger_update (rn, "new route selected");
  
        /* Set real nexthop. */
        if (nexthop_active_update (rn, select, 1))
        {
-           /* Clear FIB flag for IPv4 for previous installed route. */
-           if (update_ok)
+           if (IS_ZEBRA_DEBUG_RIB)
+             {
+               if (fib)
+                 zlog_debug ("%u:%s/%d: Updating route rn %p, rib %p (type %d) "
+                             "old %p (type %d)", vrf_id, buf, rn->p.prefixlen, rn,
+                             select, select->type, fib, fib->type);
+               else
+                 zlog_debug ("%u:%s/%d: Adding route rn %p, rib %p (type %d)",
+                             vrf_id, buf, rn->p.prefixlen, rn, select, select->type);
+             }
+           if (! RIB_SYSTEM_ROUTE (select))
              {
-               assert (fib);
-               for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
-                 UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+               /* Clear FIB flag if performing a replace, will get set again
+                * as part of install.
+                */
+               if (fib)
+                 {
+                   for (nexthop = fib->nexthop; nexthop; nexthop = nexthop->next)
+                     UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
+                 }
+               rib_install_kernel (rn, select, fib? 1 : 0);
              }
-         if (! RIB_SYSTEM_ROUTE (select))
-           rib_install_kernel (rn, select, update_ok);
+           else
+             {
+               /* Uninstall prior route here, if needed. */
+               if (fib && !RIB_SYSTEM_ROUTE (fib))
+                 rib_uninstall_kernel (rn, fib);
+             }
          SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED);
          /* Unconditionally announce, this part is exercised by new routes */
          /* If we cannot add, for example route added is learnt by the */
        }
        else
        {
-           /* For IPv4, uninstall prior route here, if any. */
-           if (update_ok)
-             {
-               assert (fib);
-               rib_uninstall_kernel (rn, fib);
-             }
-           /* if "select", the earlier redist delete wouldn't have happened */
+           /* Uninstall prior route here and do redist delete, if needed. */
            if (fib)
-             redistribute_delete(&rn->p, fib);
+             {
+               if (IS_ZEBRA_DEBUG_RIB)
+                 zlog_debug ("%u:%s/%d: Deleting route rn %p, rib %p (type %d) "
+                             "- nexthop inactive",
+                             vrf_id, buf, rn->p.prefixlen, rn, fib, fib->type);
+               if (!RIB_SYSTEM_ROUTE (fib))
+                 rib_uninstall_kernel (rn, fib);
+               redistribute_delete(&rn->p, fib);
+           }
        }
        UNSET_FLAG(select->flags, ZEBRA_FLAG_CHANGED);
      }
    if (del)
      {
        if (IS_ZEBRA_DEBUG_RIB)
-         zlog_debug ("%s: %s/%d: Deleting fib %p, rn %p", __func__, buf,
-           rn->p.prefixlen, del, rn);
+         zlog_debug ("%u:%s/%d: Freeing route rn %p, rib %p (type %d)",
+                     vrf_id, buf, rn->p.prefixlen, rn, del, del->type);
        rib_unlink (rn, del);
      }
  
  end:
-   if (IS_ZEBRA_DEBUG_RIB_Q)
-     zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn);
    /*
     * Check if the dest can be deleted now.
     */
@@@ -1637,13 -1763,27 +1667,27 @@@ process_subq (struct list * subq, u_cha
  {
    struct listnode *lnode  = listhead (subq);
    struct route_node *rnode;
+   char buf[INET6_ADDRSTRLEN];
+   rib_dest_t *dest;
+   struct zebra_vrf *zvrf = NULL;
  
    if (!lnode)
      return 0;
  
    rnode = listgetdata (lnode);
+   dest = rib_dest_from_rnode (rnode);
+   if (dest)
+     zvrf = rib_dest_vrf (dest);
    rib_process (rnode);
  
+   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+     {
+       inet_ntop (rnode->p.family, &rnode->p.u.prefix, buf, INET6_ADDRSTRLEN);
+       zlog_debug ("%u:%s/%d: rn %p dequeued from sub-queue %u",
+                   zvrf ? zvrf->vrf_id : 0, buf, rnode->p.prefixlen, rnode, qindex);
+     }
    if (rnode->info)
      UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex));
  
@@@ -1719,7 -1859,7 +1763,7 @@@ rib_meta_queue_add (struct meta_queue *
    struct rib *rib;
    char buf[INET6_ADDRSTRLEN];
  
-   if (IS_ZEBRA_DEBUG_RIB_Q)
+   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
      inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
  
    RNODE_FOREACH_RIB (rn, rib)
        /* Invariant: at this point we always have rn->info set. */
        if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags,
                      RIB_ROUTE_QUEUED (qindex)))
-       {
-         if (IS_ZEBRA_DEBUG_RIB_Q)
-           zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u",
-                       __func__, buf, rn->p.prefixlen, rn, qindex);
-         continue;
-       }
+         continue;
  
        SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex));
        listnode_add (mq->subq[qindex], rn);
        route_lock_node (rn);
        mq->size++;
  
-       if (IS_ZEBRA_DEBUG_RIB_Q)
-       zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u",
-                   __func__, buf, rn->p.prefixlen, rn, qindex);
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+       zlog_debug ("%u:%s/%d: rn %p queued into sub-queue %u",
+                   rib->vrf_id, buf, rn->p.prefixlen, rn, qindex);
      }
  }
  
  void
  rib_queue_add (struct zebra_t *zebra, struct route_node *rn)
  {
-   char buf[INET_ADDRSTRLEN];
    assert (zebra && rn);
    
-   if (IS_ZEBRA_DEBUG_RIB_Q)
-     inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN);
    /* Pointless to queue a route_node with no RIB entries to add or remove */
    if (!rnode_to_ribs (rn))
      {
        return;
      }
  
-   if (IS_ZEBRA_DEBUG_RIB_Q)
-     zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen);
    assert (zebra);
  
    if (zebra->ribq == NULL)
  
    rib_meta_queue_add (zebra->mq, rn);
  
-   if (IS_ZEBRA_DEBUG_RIB_Q)
-     zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn);
    return;
  }
  
@@@ -1894,20 -2019,14 +1923,14 @@@ rib_link (struct route_node *rn, struc
  
    assert (rib && rn);
    
-   if (IS_ZEBRA_DEBUG_RIB)
-   {
-     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
-     zlog_debug ("%s: %s/%d: rn %p, rib %p", __func__,
-       buf, rn->p.prefixlen, rn, rib);
-   }
    dest = rib_dest_from_rnode (rn);
    if (!dest)
      {
-       if (IS_ZEBRA_DEBUG_RIB)
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
        {
-         zlog_debug ("%s: %s/%d: adding dest to table", __func__,
-                     buf, rn->p.prefixlen);
+           inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
+           zlog_debug ("%u:%s/%d: rn %p adding dest",
+                       rib->vrf_id, buf, rn->p.prefixlen, rn);
        }
  
        dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t));
      rib_queue_add (&zebrad, rn);
    else
      {
-       if (IS_ZEBRA_DEBUG_RIB)
-       {
-         zlog_debug ("%s: %s/%d: Skipping further RIB processing of non-main table",
-                     __func__, buf, rn->p.prefixlen);
-       }
        afi = (rn->p.family == AF_INET) ? AFI_IP :
        (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
        if (is_zebra_import_table_enabled (afi, rib->table))
@@@ -1949,13 -2063,6 +1967,6 @@@ rib_addnode (struct route_node *rn, str
     */
    if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
      {
-       if (IS_ZEBRA_DEBUG_RIB)
-       {
-         char buf[INET6_ADDRSTRLEN];
-         inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
-         zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p",
-                     __func__, buf, rn->p.prefixlen, rn, rib);
-       }
        UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED);
        return;
      }
  static void
  rib_unlink (struct route_node *rn, struct rib *rib)
  {
-   char buf[INET6_ADDRSTRLEN];
    rib_dest_t *dest;
  
    assert (rn && rib);
  
-   if (IS_ZEBRA_DEBUG_RIB)
-   {
-     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
-     zlog_debug ("%s: %s/%d: rn %p, rib %p",
-                 __func__, buf, rn->p.prefixlen, rn, rib);
-   }
    dest = rib_dest_from_rnode (rn);
  
    if (rib->next)
      }
  
    /* free RIB and nexthops */
 -  nexthops_free(rib->nexthop, rn);
 +  zebra_deregister_rnh_static_nexthops (rib->nexthop, rn);
 +  nexthops_free(rib->nexthop);
    XFREE (MTYPE_RIB, rib);
  
  }
@@@ -2010,13 -2108,6 +2013,6 @@@ rib_delnode (struct route_node *rn, str
  {
    afi_t afi;
  
-   if (IS_ZEBRA_DEBUG_RIB)
-   {
-     char buf[INET6_ADDRSTRLEN];
-     inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
-     zlog_debug ("%s: %s/%d: rn %p, rib %p, removing", __func__,
-       buf, rn->p.prefixlen, rn, rib);
-   }
    SET_FLAG (rib->status, RIB_ENTRY_REMOVED);
  
    if ((rib->table == RT_TABLE_MAIN) || (rib->table == zebrad.rtm_table_default))
        if (is_zebra_import_table_enabled (afi, rib->table))
        zebra_del_import_table_entry(rn, rib);
        /* Just clean up if non main table */
+       if (IS_ZEBRA_DEBUG_RIB)
+         {
+           char buf[INET6_ADDRSTRLEN];
+           if (IS_ZEBRA_DEBUG_RIB)
+             {
+               inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN);
+               zlog_debug ("%u:%s/%d: Freeing route rn %p, rib %p (type %d)",
+                           rib->vrf_id, buf, rn->p.prefixlen, rn, rib, rib->type);
+             }
+         }
        rib_unlink(rn, rib);
      }
  }
@@@ -2119,12 -2221,12 +2126,12 @@@ rib_add_ipv4 (int type, u_short instanc
    if (gate)
      {
        if (ifindex)
 -      nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
 +      rib_nexthop_ipv4_ifindex_add (rib, gate, src, ifindex);
        else
 -      nexthop_ipv4_add (rib, gate, src);
 +      rib_nexthop_ipv4_add (rib, gate, src);
      }
    else
 -    nexthop_ifindex_add (rib, ifindex);
 +    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)
  
    /* Link new rib to node.*/
    if (IS_ZEBRA_DEBUG_RIB)
-   {
-     zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
-       __func__, rn, rib);
-     rib_dump ((struct prefix *)p, 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, rn, rib, rib->type, same);
+         }
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+         rib_dump ((struct prefix *)p, rib);
+     }
    rib_addnode (rn, rib);
    
    /* Free implicit route.*/
    if (same)
-   {
-     if (IS_ZEBRA_DEBUG_RIB)
-       zlog_debug ("%s: calling rib_delnode (%p, %p)", __func__, rn, rib);
      rib_delnode (rn, same);
-   }
    
    route_unlock_node (rn);
    return 0;
@@@ -2303,7 -2409,8 +2314,8 @@@ void rib_lookup_and_pushup (struct pref
        {
          char buf[INET_ADDRSTRLEN];
          inet_ntop (rn->p.family, &p->prefix, buf, INET_ADDRSTRLEN);
-         zlog_debug ("%s: freeing way for connected prefix %s/%d", __func__, buf, p->prefixlen);
+         zlog_debug ("%u:%s/%d: freeing way for connected prefix",
+                     rib->vrf_id, buf, p->prefixlen);
          rib_dump (&rn->p, rib);
        }
        rib_uninstall (rn, rib);
@@@ -2370,27 -2477,29 +2382,29 @@@ rib_add_ipv4_multipath (struct prefix_i
        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",
+                       rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same);
+         }
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+         rib_dump ((struct prefix *)p, rib);
+     }
    rib_addnode (rn, rib);
    ret = 1;
-   if (IS_ZEBRA_DEBUG_RIB)
-   {
-     zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
-       __func__, rn, rib);
-     rib_dump (p, rib);
-   }
  
    /* Free implicit route.*/
    if (same)
-   {
-     if (IS_ZEBRA_DEBUG_RIB)
      {
-       zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
-         __func__, rn, same);
-       rib_dump (p, same);
+       rib_delnode (rn, same);
+       ret = -1;
      }
-     rib_delnode (rn, same);
-     ret = -1;
-   }
    
    route_unlock_node (rn);
    return ret;
@@@ -2409,8 -2518,8 +2423,8 @@@ rib_delete_ipv4 (int type, u_short inst
    struct rib *same = NULL;
    struct nexthop *nexthop, *tnexthop;
    int recursing;
-   char buf1[INET_ADDRSTRLEN];
-   char buf2[INET_ADDRSTRLEN];
+   char buf1[INET6_ADDRSTRLEN];
+   char buf2[INET6_ADDRSTRLEN];
  
    /* Lookup table.  */
    if ((table_id == RT_TABLE_MAIN) || (table_id == zebrad.rtm_table_default))
    /* Apply mask. */
    apply_mask_ipv4 (p);
  
-   if (IS_ZEBRA_DEBUG_KERNEL)
-     {
-       if (gate)
-       zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u via %s ifindex %d",
-                   prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                   inet_ntoa (*gate),
-                   ifindex);
-       else
-       zlog_debug ("rib_delete_ipv4(): route delete %s vrf %u ifindex %d",
-                   prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                   ifindex);
-     }
    /* Lookup route node. */
    rn = route_node_lookup (table, (struct prefix *) p);
    if (! rn)
      {
-       if (IS_ZEBRA_DEBUG_KERNEL)
-       {
-         if (gate)
-           zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
-                      prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                      inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
-                      ifindex);
-         else
-           zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
-                      prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                      ifindex);
-       }
+       if (IS_ZEBRA_DEBUG_RIB)
+         zlog_debug ("%u:%s/%d: doesn't exist in rib",
+                     vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
+                     p->prefixlen);
        return ZEBRA_ERR_RTNOEXIST;
      }
  
        if (fib && type == ZEBRA_ROUTE_KERNEL &&
            CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE))
          {
-           if (IS_ZEBRA_DEBUG_KERNEL)
+           if (IS_ZEBRA_DEBUG_RIB)
              {
-               zlog_debug ("Zebra route %s/%d was deleted by others from kernel",
-                          inet_ntop (AF_INET, &p->prefix, buf1, INET_ADDRSTRLEN),
-                          p->prefixlen);
+               zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted "
+                           "from kernel, adding",
+                          vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
+                          p->prefixlen, rn, fib, fib->type);
              }
          if (allow_delete)
            {
          }
        else
        {
-         if (IS_ZEBRA_DEBUG_KERNEL)
+         if (IS_ZEBRA_DEBUG_RIB)
            {
              if (gate)
-               zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
+               zlog_debug ("%u:%s: via %s ifindex %d type %d "
                           "doesn't exist in rib",
-                          prefix2str (p, buf1, sizeof(buf1)), vrf_id,
+                          vrf_id, prefix2str (p, buf1, sizeof(buf1)),
                           inet_ntop (AF_INET, gate, buf2, INET_ADDRSTRLEN),
                           ifindex,
                           type);
              else
-               zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
-                          prefix2str (p, buf1, sizeof(buf1)), vrf_id,
+               zlog_debug ("%u:%s: ifindex %d type %d doesn't exist in rib",
+                          vrf_id, prefix2str (p, buf1, sizeof(buf1)),
                           ifindex,
                           type);
            }
@@@ -2599,32 -2688,43 +2593,43 @@@ static_install_route (afi_t afi, safi_
        switch (si->type)
          {
        case STATIC_IPV4_GATEWAY:
 -        nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
 +        rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
          nh_p.family = AF_INET;
          nh_p.prefixlen = IPV4_MAX_BITLEN;
          nh_p.u.prefix4 = si->addr.ipv4;
          zebra_register_rnh_static_nh(&nh_p, rn);
          break;
        case STATIC_IPV4_IFNAME:
 -        nexthop_ifname_add (rib, si->ifname);
 +        rib_nexthop_ifname_add (rib, si->ifname);
          break;
        case STATIC_IPV4_BLACKHOLE:
 -        nexthop_blackhole_add (rib);
 +        rib_nexthop_blackhole_add (rib);
          break;
        case STATIC_IPV6_GATEWAY:
 -        nexthop_ipv6_add (rib, &si->addr.ipv6);
 +        rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
          nh_p.family = AF_INET6;
          nh_p.prefixlen = IPV6_MAX_BITLEN;
          nh_p.u.prefix6 = si->addr.ipv6;
          zebra_register_rnh_static_nh(&nh_p, rn);
          break;
        case STATIC_IPV6_IFNAME:
 -        nexthop_ifname_add (rib, si->ifname);
 +        rib_nexthop_ifname_add (rib, si->ifname);
          break;
        case STATIC_IPV6_GATEWAY_IFNAME:
 -        nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
 +        rib_nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
          break;
          }
+       if (IS_ZEBRA_DEBUG_RIB)
+         {
+           char buf[INET6_ADDRSTRLEN];
+           if (IS_ZEBRA_DEBUG_RIB)
+             {
+               inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
+               zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
+                           si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
+             }
+         }
        rib_queue_add (&zebrad, rn);
      }
    else
        switch (si->type)
          {
        case STATIC_IPV4_GATEWAY:
 -        nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
 +        rib_nexthop_ipv4_add (rib, &si->addr.ipv4, NULL);
          nh_p.family = AF_INET;
          nh_p.prefixlen = IPV4_MAX_BITLEN;
          nh_p.u.prefix4 = si->addr.ipv4;
          zebra_register_rnh_static_nh(&nh_p, rn);
          break;
        case STATIC_IPV4_IFNAME:
 -        nexthop_ifname_add (rib, si->ifname);
 +        rib_nexthop_ifname_add (rib, si->ifname);
          break;
        case STATIC_IPV4_BLACKHOLE:
 -        nexthop_blackhole_add (rib);
 +        rib_nexthop_blackhole_add (rib);
          break;
        case STATIC_IPV6_GATEWAY:
 -        nexthop_ipv6_add (rib, &si->addr.ipv6);
 +        rib_nexthop_ipv6_add (rib, &si->addr.ipv6);
          nh_p.family = AF_INET6;
          nh_p.prefixlen = IPV6_MAX_BITLEN;
          nh_p.u.prefix6 = si->addr.ipv6;
          zebra_register_rnh_static_nh(&nh_p, rn);
          break;
        case STATIC_IPV6_IFNAME:
 -        nexthop_ifname_add (rib, si->ifname);
 +        rib_nexthop_ifname_add (rib, si->ifname);
          break;
        case STATIC_IPV6_GATEWAY_IFNAME:
 -        nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
 +        rib_nexthop_ipv6_ifname_add (rib, &si->addr.ipv6, si->ifname);
          break;
          }
  
        rib->flags = si->flags;
  
        /* Link this rib to the tree. */
+       if (IS_ZEBRA_DEBUG_RIB)
+         {
+           char buf[INET6_ADDRSTRLEN];
+           if (IS_ZEBRA_DEBUG_RIB)
+             {
+               inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
+               zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d)",
+                           si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
+             }
+         }
        rib_addnode (rn, rib);
      }
  }
@@@ -2766,34 -2876,30 +2781,30 @@@ static_uninstall_route (afi_t afi, safi
         * the nexthop. There is no need to re-evaluate the route for this
         * scenario.
         */
+       if (IS_ZEBRA_DEBUG_RIB)
+         {
+           char buf[INET6_ADDRSTRLEN];
+           if (IS_ZEBRA_DEBUG_RIB)
+             {
+               inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
+               zlog_debug ("%u:%s/%d: Modifying route rn %p, rib %p (type %d)",
+                           si->vrf_id, buf, p->prefixlen, rn, rib, rib->type);
+             }
+         }
        UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
        if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))
          {
-         if (afi == AFI_IP)
-           {
-             /* If there are other active nexthops, do an update. */
-             if (rib->nexthop_active_num > 1)
-               {
-                 rib_install_kernel (rn, rib, 1);
-                 redistribute_update (&rn->p, rib, NULL);
-               }
-             else
-               {
-                 redistribute_delete (&rn->p, rib);
-                 rib_uninstall_kernel (rn, rib);
-               }
-           }
-         else
-           {
-             redistribute_delete (&rn->p, rib);
-             rib_uninstall_kernel (rn, rib);
-             /* Are there other active nexthops? */
-             if (rib->nexthop_active_num > 1)
-               {
-                 rib_install_kernel (rn, rib, 0);
-                 redistribute_update (&rn->p, rib, NULL);
-               }
-           }
+           /* If there are other active nexthops, do an update. */
+           if (rib->nexthop_active_num > 1)
+             {
+               rib_install_kernel (rn, rib, 1);
+               redistribute_update (&rn->p, rib, NULL);
+             }
+           else
+             {
+               redistribute_delete (&rn->p, rib);
+               rib_uninstall_kernel (rn, rib);
+             }
          }
  
        if (afi == AFI_IP)
          nh_p.prefixlen = IPV6_MAX_BITLEN;
          nh_p.u.prefix6 = nexthop->gate.ipv6;
        }
 -      nexthop_delete (rib, nexthop);
 +      rib_nexthop_delete (rib, nexthop);
        zebra_deregister_rnh_static_nh(&nh_p, rn);
 -      nexthop_free (nexthop, rn);
 +      nexthop_free (nexthop);
      }
    /* Unlock node. */
    route_unlock_node (rn);
@@@ -3057,12 -3163,12 +3068,12 @@@ rib_add_ipv6 (int type, u_short instanc
    if (gate)
      {
        if (ifindex)
 -      nexthop_ipv6_ifindex_add (rib, gate, ifindex);
 +      rib_nexthop_ipv6_ifindex_add (rib, gate, ifindex);
        else
 -      nexthop_ipv6_add (rib, gate);
 +      rib_nexthop_ipv6_add (rib, gate);
      }
    else
 -    nexthop_ifindex_add (rib, ifindex);
 +    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)
        SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  
    /* Link new rib to node.*/
-   rib_addnode (rn, rib);
    if (IS_ZEBRA_DEBUG_RIB)
-   {
-     zlog_debug ("%s: called rib_addnode (%p, %p) on new RIB entry",
-       __func__, rn, rib);
-     rib_dump (p, 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, rn, rib, rib->type, same);
+         }
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+         rib_dump ((struct prefix *)p, rib);
+     }
+   rib_addnode (rn, rib);
  
    /* Free implicit route.*/
    if (same)
-   {
-     if (IS_ZEBRA_DEBUG_RIB)
-     {
-       zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
-         __func__, rn, same);
-       rib_dump (p, same);
-     }
      rib_delnode (rn, same);
-   }
    
    route_unlock_node (rn);
    return 0;
@@@ -3191,20 -3297,29 +3202,29 @@@ rib_add_ipv6_multipath (struct prefix *
    }
  
    /* Link new rib to node.*/
+   if (IS_ZEBRA_DEBUG_RIB)
+     {
+       char buf[INET6_ADDRSTRLEN];
+       if (IS_ZEBRA_DEBUG_RIB)
+         {
+           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",
+                       rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same);
+         }
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+         rib_dump ((struct prefix *)p, rib);
+     }
    rib_addnode (rn, rib);
    ret = 1;
    /* Free implicit route.*/
    if (same)
-   {
-     if (IS_ZEBRA_DEBUG_RIB)
      {
-       zlog_debug ("%s: calling rib_delnode (%p, %p) on existing RIB entry",
-         __func__, rn, same);
-       rib_dump ((struct prefix *)p, same);
+       rib_delnode (rn, same);
+       ret = -1;
      }
-     rib_delnode (rn, same);
-     ret = -1;
-   }
  
    route_unlock_node (rn);
    return ret;
@@@ -3245,18 -3360,10 +3265,10 @@@ rib_delete_ipv6 (int type, u_short inst
    rn = route_node_lookup (table, (struct prefix *) p);
    if (! rn)
      {
-       if (IS_ZEBRA_DEBUG_KERNEL)
-       {
-         if (gate)
-           zlog_debug ("route %s vrf %u via %s ifindex %d doesn't exist in rib",
-                      prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                      inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
-                      ifindex);
-         else
-           zlog_debug ("route %s vrf %u ifindex %d doesn't exist in rib",
-                      prefix2str (p, buf1, sizeof(buf1)), vrf_id,
-                      ifindex);
-       }
+       if (IS_ZEBRA_DEBUG_RIB)
+         zlog_debug ("%u:%s/%d: doesn't exist in rib",
+                     vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
+                     p->prefixlen);
        return ZEBRA_ERR_RTNOEXIST;
      }
  
        if (fib && type == ZEBRA_ROUTE_KERNEL &&
            CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE))
          {
-           if (IS_ZEBRA_DEBUG_KERNEL)
-             {
-               zlog_debug ("Zebra route %s/%d was deleted by others from kernel",
-                          inet_ntop (AF_INET6, &p->prefix, buf1, INET6_ADDRSTRLEN),
-                          p->prefixlen);
-             }
+           if (IS_ZEBRA_DEBUG_RIB)
+             zlog_debug ("%u:%s/%d: rn %p, rib %p (type %d) was deleted "
+                         "from kernel, adding",
+                         vrf_id, inet_ntop (p->family, &p->prefix, buf1, INET6_ADDRSTRLEN),
+                         p->prefixlen, rn, fib, fib->type);
          if (allow_delete)
            {
              /* Unset flags. */
          if (IS_ZEBRA_DEBUG_KERNEL)
            {
              if (gate)
-               zlog_debug ("route %s vrf %u via %s ifindex %d type %d "
+               zlog_debug ("%s: vrf %u via %s ifindex %d type %d "
                           "doesn't exist in rib",
                           prefix2str (p, buf1, sizeof(buf1)), vrf_id,
                           inet_ntop (AF_INET6, gate, buf2, INET6_ADDRSTRLEN),
                           ifindex,
                           type);
              else
-               zlog_debug ("route %s vrf %u ifindex %d type %d doesn't exist in rib",
+               zlog_debug ("%s: vrf %u ifindex %d type %d doesn't exist in rib",
                           prefix2str (p, buf1, sizeof(buf1)), vrf_id,
                           ifindex,
                           type);
diff --combined zebra/zserv.c
index f8bf18d1e18da4465d10cb2f91f7002330c804c6,8a66b3c99cf5dc241b1b25b9611132b3c507d002..2cbc3bb5518f24c7b2da691507ae9c148cd7d04a
@@@ -1109,7 -1109,7 +1109,7 @@@ zread_ipv4_add (struct zserv *client, u
            {
            case ZEBRA_NEXTHOP_IFINDEX:
              ifindex = stream_getl (s);
 -            nexthop_ifindex_add (rib, ifindex);
 +            rib_nexthop_ifindex_add (rib, ifindex);
              break;
            case ZEBRA_NEXTHOP_IFNAME:
              ifname_len = stream_getc (s);
              break;
            case ZEBRA_NEXTHOP_IPV4:
              nexthop.s_addr = stream_get_ipv4 (s);
 -            nexthop_ipv4_add (rib, &nexthop, NULL);
 +            rib_nexthop_ipv4_add (rib, &nexthop, NULL);
              break;
            case ZEBRA_NEXTHOP_IPV4_IFINDEX:
              nexthop.s_addr = stream_get_ipv4 (s);
              ifindex = stream_getl (s);
 -            nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
 +            rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
              break;
            case ZEBRA_NEXTHOP_IPV6:
              stream_forward_getp (s, IPV6_MAX_BYTELEN);
              break;
              case ZEBRA_NEXTHOP_BLACKHOLE:
 -              nexthop_blackhole_add (rib);
 +              rib_nexthop_blackhole_add (rib);
                break;
              }
        }
@@@ -1351,7 -1351,7 +1351,7 @@@ zread_ipv4_route_ipv6_nexthop_add (stru
                }
              break;
              case ZEBRA_NEXTHOP_BLACKHOLE:
 -              nexthop_blackhole_add (rib);
 +              rib_nexthop_blackhole_add (rib);
                break;
            }
        }
          {
          if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
              if ((i < if_count) && ifindices[i]) {
 -              nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
 +              rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
              }
              else {
 -            nexthop_ipv6_add (rib, &nexthops[i]);
 +            rib_nexthop_ipv6_add (rib, &nexthops[i]);
              }
            }
            else {
              if ((i < if_count) && ifindices[i]) {
 -            nexthop_ifindex_add (rib, ifindices[i]);
 +            rib_nexthop_ifindex_add (rib, ifindices[i]);
            }
            }
        }
@@@ -1471,7 -1471,7 +1471,7 @@@ zread_ipv6_add (struct zserv *client, u
                }
              break;
              case ZEBRA_NEXTHOP_BLACKHOLE:
 -              nexthop_blackhole_add (rib);
 +              rib_nexthop_blackhole_add (rib);
                break;
            }
        }
          {
          if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
              if ((i < if_count) && ifindices[i])
 -              nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
 +              rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
              else
 -            nexthop_ipv6_add (rib, &nexthops[i]);
 +            rib_nexthop_ipv6_add (rib, &nexthops[i]);
            }
            else {
              if ((i < if_count) && ifindices[i])
 -            nexthop_ifindex_add (rib, ifindices[i]);
 +            rib_nexthop_ifindex_add (rib, ifindices[i]);
            }
        }
      }
@@@ -2285,6 -2285,17 +2285,17 @@@ DEFUN (config_table
    return CMD_SUCCESS;
  }
  
+ DEFUN (no_config_table,
+        no_config_table_cmd,
+        "no table TABLENO",
+        NO_STR
+        "Configure target kernel routing table\n"
+        "TABLE integer\n")
+ {
+   zebrad.rtm_table_default = 0;
+   return CMD_SUCCESS;
+ }
  DEFUN (ip_forwarding,
         ip_forwarding_cmd,
         "ip forwarding",
@@@ -2529,6 -2540,7 +2540,7 @@@ zebra_init (void
    install_element (VIEW_NODE, &show_table_cmd);
    install_element (ENABLE_NODE, &show_table_cmd);
    install_element (CONFIG_NODE, &config_table_cmd);
+   install_element (CONFIG_NODE, &no_config_table_cmd);
  #endif /* HAVE_NETLINK */
  
  #ifdef HAVE_IPV6