summaryrefslogtreecommitdiff
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorDenis Ovsienko <linux@pilot.org.ua>2008-02-26 14:02:24 +0000
committerDenis Ovsienko <linux@pilot.org.ua>2008-02-26 14:02:24 +0000
commit20e5ff0a8893ffad6d31739d68d224931c4a7992 (patch)
tree8ecd9184d2d7268e0fc51bcd612790301780efda /zebra/zebra_rib.c
parentdea04441fb51f74dc25f6ab4bd756b4159d961b6 (diff)
+ fix bug#326 by rib_lookup_and_pushup()
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index e27c63bf..c6af3290 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -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)
{