return 0;
}
-static int
+int
is_default (struct prefix *p)
{
if (p->family == AF_INET)
}
static void
-zebra_redistribute_default (struct zserv *client)
+zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id)
{
struct prefix_ipv4 p;
struct route_table *table;
p.family = AF_INET;
/* Lookup table. */
- table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
+ table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (table)
{
rn = route_node_lookup (table, (struct prefix *)&p);
p6.family = AF_INET6;
/* Lookup table. */
- table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
+ table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (table)
{
rn = route_node_lookup (table, (struct prefix *)&p6);
/* Redistribute routes. */
static void
-zebra_redistribute (struct zserv *client, int type, u_short instance)
+zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id)
{
struct rib *newrib;
struct route_table *table;
struct route_node *rn;
- table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
+ table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB (rn, newrib)
}
#ifdef HAVE_IPV6
- table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT);
+ table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
if (table)
for (rn = route_top (table); rn; rn = route_next (rn))
RNODE_FOREACH_RIB (rn, newrib)
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)
if (is_default(p) && client->redist_default)
send_redistribute = 1;
- if (redist_check_instance(&client->redist[afi][rib->type],
- rib->instance))
- send_redistribute = 1;
+ if (rib->instance && redist_check_instance(&client->mi_redist[afi][rib->type],
+ rib->instance))
+ send_redistribute = 1;
+ else
+ if ((is_default (p) &&
+ vrf_bitmap_check (client->redist_default, rib->vrf_id))
+ || vrf_bitmap_check (client->redist[afi][rib->type], rib->vrf_id))
+ send_redistribute = 1;
if (send_redistribute)
{
}
}
else if (prev_rib &&
- redist_check_instance(&client->redist[afi][prev_rib->type],
- rib->instance))
+ ((rib->instance &&
+ redist_check_instance(&client->mi_redist[afi][prev_rib->type],
+ rib->instance)) ||
+ vrf_bitmap_check (client->redist[afi][prev_rib->type], rib->vrf_id)))
{
switch (afi)
{
{
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)
if (is_default (p))
{
if ((p->family == AF_INET) &&
- (client->redist_default ||
- redist_check_instance(&client->redist[AFI_IP][rib->type],
- rib->instance)))
+ (vrf_bitmap_check (client->redist_default, rib->vrf_id) ||
+ (rib->instance &&
+ redist_check_instance(&client->mi_redist[AFI_IP][rib->type],
+ rib->instance)) ||
+ vrf_bitmap_check (client->redist[AFI_IP][rib->type], rib->vrf_id)))
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p,
rib);
#ifdef HAVE_IPV6
if ((p->family == AF_INET6) &&
- (client->redist_default ||
- redist_check_instance(&client->redist[AFI_IP6][rib->type],
- rib->instance)))
+ (vrf_bitmap_check (client->redist_default, rib->vrf_id) ||
+ (rib->instance &&
+ redist_check_instance(&client->mi_redist[AFI_IP6][rib->type],
+ rib->instance)) ||
+ vrf_bitmap_check (client->redist[AFI_IP6][rib->type], rib->vrf_id)))
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p,
rib);
#endif /* HAVE_IPV6 */
else
{
if ((p->family == AF_INET) &&
- redist_check_instance(&client->redist[AFI_IP][rib->type],
- rib->instance))
+ ((rib->instance &&
+ redist_check_instance(&client->mi_redist[AFI_IP][rib->type],
+ rib->instance)) ||
+ vrf_bitmap_check (client->redist[AFI_IP][rib->type], rib->vrf_id)))
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p,
rib);
#ifdef HAVE_IPV6
if ((p->family == AF_INET6) &&
- redist_check_instance(&client->redist[AFI_IP6][rib->type],
- rib->instance))
+ ((rib->instance &&
+ redist_check_instance(&client->mi_redist[AFI_IP6][rib->type],
+ rib->instance)) ||
+ vrf_bitmap_check (client->redist[AFI_IP6][rib->type], rib->vrf_id)))
zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p,
rib);
#endif /* HAVE_IPV6 */
}
void
-zebra_redistribute_add (int command, struct zserv *client, int length)
+zebra_redistribute_add (int command, struct zserv *client, int length,
+ vrf_id_t vrf_id)
{
afi_t afi;
int type;
if (type == 0 || type >= ZEBRA_ROUTE_MAX)
return;
- if (!redist_check_instance(&client->redist[afi][type], instance))
+ if (instance && !redist_check_instance(&client->mi_redist[afi][type], instance))
{
- redist_add_instance(&client->redist[afi][type], instance);
- zebra_redistribute (client, type, instance);
+ redist_add_instance(&client->mi_redist[afi][type], instance);
+ zebra_redistribute (client, type, instance, vrf_id);
}
+ else
+ if (! vrf_bitmap_check (client->redist[afi][type], vrf_id))
+ {
+ vrf_bitmap_set (client->redist[afi][type], vrf_id);
+ zebra_redistribute (client, type, 0, vrf_id);
+ }
}
void
-zebra_redistribute_delete (int command, struct zserv *client, int length)
+zebra_redistribute_delete (int command, struct zserv *client, int length,
+ vrf_id_t vrf_id)
{
afi_t afi;
int type;
if (type == 0 || type >= ZEBRA_ROUTE_MAX)
return;
- if (redist_check_instance(&client->redist[afi][type], instance))
+ if (instance && redist_check_instance(&client->mi_redist[afi][type], instance))
{
- redist_del_instance(&client->redist[afi][type], instance);
+ redist_del_instance(&client->mi_redist[afi][type], instance);
//Pending: why no reaction here?
}
+ vrf_bitmap_unset (client->redist[afi][type], vrf_id);
}
void
-zebra_redistribute_default_add (int command, struct zserv *client, int length)
+zebra_redistribute_default_add (int command, struct zserv *client, int length,
+ vrf_id_t vrf_id)
{
- client->redist_default = 1;
- zebra_redistribute_default (client);
+ vrf_bitmap_set (client->redist_default, vrf_id);
+ zebra_redistribute_default (client, vrf_id);
}
void
zebra_redistribute_default_delete (int command, struct zserv *client,
- int length)
+ int length, vrf_id_t vrf_id)
{
- client->redist_default = 0;;
+ vrf_bitmap_unset (client->redist_default, vrf_id);
}
/* Interface up information. */
}
}
+/* VRF information update. */
+void
+zebra_vrf_add_update (struct zebra_vrf *zvrf)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_VRF_ADD %s", zvrf->name);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ zsend_vrf_add (client, zvrf);
+}
+
+void
+zebra_vrf_delete_update (struct zebra_vrf *zvrf)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf->name);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ zsend_vrf_delete (client, zvrf);
+}
+
+void
+zebra_vrf_update_all (struct zserv *client)
+{
+ struct vrf *vrf;
+ vrf_iter_t iter;
+
+ for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
+ {
+ if ((vrf = vrf_iter2vrf (iter)) && vrf->vrf_id)
+ zsend_vrf_add (client, vrf_info_lookup (vrf->vrf_id));
+ }
+}
+
+
/* Interface address addition. */
void
zebra_interface_address_add_update (struct interface *ifp,
}
}
+/* Interface VRF change. May need to delete from clients not interested in
+ * the new VRF. Note that this function is invoked *prior* to the VRF change.
+ */
+void
+zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
+ ifp->name, ifp->vrf_id, new_vrf_id);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ {
+ /* Skip clients not interested in both VRFs. */
+ if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id) &&
+ !vrf_bitmap_check (client->ifinfo, new_vrf_id))
+ continue;
+
+ if (!vrf_bitmap_check (client->ifinfo, new_vrf_id))
+ {
+ /* Need to delete if the client is not interested in the new VRF. */
+ zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
+ client->ifdel_cnt++;
+ zsend_interface_delete (client, ifp);
+ }
+ else if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
+ {
+ /* Client is interested in both VRFs, inform about the change. */
+ zsend_interface_vrf_update (client, ifp, new_vrf_id);
+ }
+ }
+}
+
+/* Interface VRF change. This function is invoked *post* VRF change and sends an
+ * add to clients who are interested in the new VRF but not in the old VRF.
+ */
+void
+zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id)
+{
+ struct listnode *node, *nnode;
+ struct zserv *client;
+
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
+ ifp->name, old_vrf_id, ifp->vrf_id);
+
+ for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+ {
+ /* Skip clients interested in both VRFs - they would've got an Update. */
+ if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id) &&
+ vrf_bitmap_check (client->ifinfo, old_vrf_id))
+ continue;
+
+ /* Skip clients not interested in the new VRF - they would've
+ * got a Delete.
+ */
+ if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
+ continue;
+
+ /* Need to add if the client is interested in the new VRF. */
+ client->ifadd_cnt++;
+ zsend_interface_add (client, ifp);
+ zsend_interface_addresses (client, ifp);
+ }
+}
+
int
zebra_add_import_table_entry (struct route_node *rn, struct rib *rib)
{
if (rib->nexthop_num == 1)
{
nhop = rib->nexthop;
- if ((nhop->type == NEXTHOP_TYPE_IFINDEX) ||
- (nhop->type == NEXTHOP_TYPE_IFNAME))
+ if (nhop->type == NEXTHOP_TYPE_IFINDEX)
gate = NULL;
else
gate = &nhop->gate.ipv4;
/* 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);
}