+ fix bug#326 by rib_lookup_and_pushup()

This commit is contained in:
Denis Ovsienko 2008-02-26 14:02:24 +00:00
parent dea04441fb
commit 20e5ff0a88
4 changed files with 64 additions and 0 deletions

View File

@ -1,3 +1,9 @@
2008-02-26 Denis Ovsienko
* zebra_rib.[ch]: (rib_lookup_and_pushup) New function, which makes sure,
that if_set_prefix() has nothing in its way of assigning an address.
* ioctl.c: (if_set_prefix) Use rib_lookup_and_pushup() to resolve
bug #326.
2008-01-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ioctl.c: If HAVE_BSD_LINK_DETECT is defined, include <net/if_media.h>

View File

@ -196,6 +196,7 @@ if_set_prefix (struct interface *ifp, struct connected *ifc)
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);

View File

@ -212,6 +212,7 @@ extern struct nexthop *nexthop_blackhole_add (struct rib *);
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

View File

@ -1614,6 +1614,62 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p)
}
}
/* Check if requested address assignment will fail due to another
* route being installed by zebra 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_SYSTEM_ROUTE (rib))
{
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)
{