Index: zebra/ioctl.c =================================================================== RCS file: /var/cvsroot/quagga/zebra/ioctl.c,v retrieving revision 1.14 diff -u -r1.14 ioctl.c --- zebra/ioctl.c 11 Jan 2008 15:57:13 -0000 1.14 +++ zebra/ioctl.c 20 Feb 2008 15:56:23 -0000 @@ -196,6 +196,7 @@ struct prefix_ipv4 *p; p = (struct prefix_ipv4 *) ifc->address; + rib_lookup_and_pushup (p); memset (&addreq, 0, sizeof addreq); strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); Index: zebra/rib.h =================================================================== RCS file: /var/cvsroot/quagga/zebra/rib.h,v retrieving revision 1.14 diff -u -r1.14 rib.h --- zebra/rib.h 13 Aug 2007 16:03:07 -0000 1.14 +++ zebra/rib.h 20 Feb 2008 15:56:23 -0000 @@ -212,6 +212,7 @@ extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *, struct in_addr *); extern void rib_lookup_and_dump (struct prefix_ipv4 *); +extern void rib_lookup_and_pushup (struct prefix_ipv4 *); extern void rib_dump (const char *, const struct prefix_ipv4 *, const struct rib *); extern int rib_lookup_ipv4_route (struct prefix_ipv4 *, union sockunion *); #define ZEBRA_RIB_LOOKUP_ERROR -1 Index: zebra/zebra_rib.c =================================================================== RCS file: /var/cvsroot/quagga/zebra/zebra_rib.c,v retrieving revision 1.42 diff -u -r1.42 zebra_rib.c --- zebra/zebra_rib.c 8 Jan 2008 20:12:46 -0000 1.42 +++ zebra/zebra_rib.c 20 Feb 2008 15:56:23 -0000 @@ -1614,6 +1614,62 @@ } } +/* Check if requested address assignment will fail due to another + * non-CONNECTED route being installed in FIB already. Take necessary + * actions, if needed: remove such a route from FIB and deSELECT + * corresponding RIB entry. Then put affected RN into RIBQ head. + */ +void rib_lookup_and_pushup (struct prefix_ipv4 * p) +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + unsigned changed = 0; + + if (NULL == (table = vrf_table (AFI_IP, SAFI_UNICAST, 0))) + { + zlog_err ("%s: vrf_table() returned NULL", __func__); + return; + } + + /* No matches would be the simplest case. */ + if (NULL == (rn = route_node_lookup (table, (struct prefix *) p))) + return; + + /* Unlock node. */ + route_unlock_node (rn); + + /* Check all RIB entries. In case any changes have to be done, requeue + * the RN into RIBQ head. If the routing message about the new connected + * route (generated by the IP address we are going to assign very soon) + * comes before the RIBQ is processed, the new RIB entry will join + * RIBQ record already on head. This is necessary for proper revalidation + * of the rest of the RIB. + */ + for (rib = rn->info; rib; rib = rib->next) + { + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) && + rib->type != ZEBRA_ROUTE_CONNECT) // Should we leave ZEBRA_ROUTE_KERNEL intact as well? + { + changed = 1; + if (IS_ZEBRA_DEBUG_RIB) + { + 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); + rib_dump (__func__, (struct prefix_ipv4 *)&rn->p, rib); + } + rib_uninstall (rn, rib); + } + } + if (changed) + { + work_queue_aim_head (zebrad.ribq, 1); + rib_queue_add (&zebrad, rn); + work_queue_aim_head (zebrad.ribq, 0); + } +} + int rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib) {