|
@@ -182,11 +182,11 @@ zebra_redistribute (struct zserv *client, int type, vrf_id_t vrf_id)
|
|
|
}
|
|
|
|
|
|
void
|
|
|
-redistribute_add (struct prefix *p, struct rib *rib)
|
|
|
+redistribute_add (struct prefix *p, struct rib *rib, struct rib *rib_old)
|
|
|
{
|
|
|
struct listnode *node, *nnode;
|
|
|
struct zserv *client;
|
|
|
-
|
|
|
+
|
|
|
for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
|
|
|
{
|
|
|
if ((is_default (p) &&
|
|
@@ -204,6 +204,21 @@ redistribute_add (struct prefix *p, struct rib *rib)
|
|
|
zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib);
|
|
|
}
|
|
|
}
|
|
|
+ else if (rib_old && vrf_bitmap_check (client->redist[rib_old->type],
|
|
|
+ rib_old->vrf_id))
|
|
|
+ {
|
|
|
+ /* redistribute_add has implicit withdraw semantics, so there
|
|
|
+ * may be an old route already redistributed that is being updated.
|
|
|
+ *
|
|
|
+ * However, if the new route is of a type that is /not/ redistributed
|
|
|
+ * to the client, then we must ensure the old route is explicitly
|
|
|
+ * withdrawn.
|
|
|
+ */
|
|
|
+ if (p->family == AF_INET)
|
|
|
+ zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib_old);
|
|
|
+ if (p->family == AF_INET6)
|
|
|
+ zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, rib_old);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|