--- embedaddon/quagga/zebra/redistribute.c 2012/02/21 17:26:11 1.1.1.1 +++ embedaddon/quagga/zebra/redistribute.c 2016/11/02 10:09:10 1.1.1.4 @@ -30,6 +30,7 @@ #include "zclient.h" #include "linklist.h" #include "log.h" +#include "vrf.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -67,7 +68,7 @@ zebra_check_addr (struct prefix *p) return 1; } -static int +int is_default (struct prefix *p) { if (p->family == AF_INET) @@ -85,7 +86,7 @@ is_default (struct prefix *p) } 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; @@ -101,13 +102,13 @@ zebra_redistribute_default (struct zserv *client) p.family = AF_INET; /* Lookup table. */ - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) { rn = route_node_lookup (table, (struct prefix *)&p); if (rn) { - for (newrib = rn->info; newrib; newrib = newrib->next) + RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->distance != DISTANCE_INFINITY) zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); @@ -121,13 +122,13 @@ zebra_redistribute_default (struct zserv *client) p6.family = AF_INET6; /* Lookup table. */ - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) { rn = route_node_lookup (table, (struct prefix *)&p6); if (rn) { - for (newrib = rn->info; newrib; newrib = newrib->next) + RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->distance != DISTANCE_INFINITY) zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, &rn->p, newrib); @@ -139,27 +140,33 @@ zebra_redistribute_default (struct zserv *client) /* Redistribute routes. */ static void -zebra_redistribute (struct zserv *client, int type) +zebra_redistribute (struct zserv *client, int type, vrf_id_t vrf_id) { struct rib *newrib; struct route_table *table; struct route_node *rn; - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) - for (newrib = rn->info; newrib; newrib = newrib->next) - if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) - && newrib->type == type - && newrib->distance != DISTANCE_INFINITY - && zebra_check_addr (&rn->p)) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); - + RNODE_FOREACH_RIB (rn, newrib) + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, zebra_check_addr=%d", + __func__, CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), + newrib->type, newrib->distance, zebra_check_addr (&rn->p)); + if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) + && newrib->type == type + && newrib->distance != DISTANCE_INFINITY + && zebra_check_addr (&rn->p)) + zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, &rn->p, newrib); + } + #ifdef HAVE_IPV6 - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) - for (newrib = rn->info; newrib; newrib = newrib->next) + RNODE_FOREACH_RIB (rn, newrib) if (CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED) && newrib->type == type && newrib->distance != DISTANCE_INFINITY @@ -176,20 +183,10 @@ redistribute_add (struct prefix *p, struct rib *rib) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) { - if (is_default (p)) + if ((is_default (p) && + vrf_bitmap_check (client->redist_default, rib->vrf_id)) + || vrf_bitmap_check (client->redist[rib->type], rib->vrf_id)) { - if (client->redist_default || client->redist[rib->type]) - { - if (p->family == AF_INET) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); -#ifdef HAVE_IPV6 - if (p->family == AF_INET6) - zsend_route_multipath (ZEBRA_IPV6_ROUTE_ADD, client, p, rib); -#endif /* HAVE_IPV6 */ - } - } - else if (client->redist[rib->type]) - { if (p->family == AF_INET) zsend_route_multipath (ZEBRA_IPV4_ROUTE_ADD, client, p, rib); #ifdef HAVE_IPV6 @@ -212,22 +209,10 @@ redistribute_delete (struct prefix *p, struct rib *rib for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) { - if (is_default (p)) + if ((is_default (p) && + vrf_bitmap_check (client->redist_default, rib->vrf_id)) + || vrf_bitmap_check (client->redist[rib->type], rib->vrf_id)) { - if (client->redist_default || client->redist[rib->type]) - { - if (p->family == AF_INET) - zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, - rib); -#ifdef HAVE_IPV6 - if (p->family == AF_INET6) - zsend_route_multipath (ZEBRA_IPV6_ROUTE_DELETE, client, p, - rib); -#endif /* HAVE_IPV6 */ - } - } - else if (client->redist[rib->type]) - { if (p->family == AF_INET) zsend_route_multipath (ZEBRA_IPV4_ROUTE_DELETE, client, p, rib); #ifdef HAVE_IPV6 @@ -239,69 +224,50 @@ redistribute_delete (struct prefix *p, struct rib *rib } 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) { int type; type = stream_getc (client->ibuf); - switch (type) + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + + if (! vrf_bitmap_check (client->redist[type], vrf_id)) { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - case ZEBRA_ROUTE_STATIC: - case ZEBRA_ROUTE_RIP: - case ZEBRA_ROUTE_RIPNG: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_BGP: - if (! client->redist[type]) - { - client->redist[type] = 1; - zebra_redistribute (client, type); - } - break; - default: - break; + vrf_bitmap_set (client->redist[type], vrf_id); + zebra_redistribute (client, type, 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) { int type; type = stream_getc (client->ibuf); - switch (type) - { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - case ZEBRA_ROUTE_STATIC: - case ZEBRA_ROUTE_RIP: - case ZEBRA_ROUTE_RIPNG: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_BGP: - client->redist[type] = 0; - break; - default: - break; - } -} + if (type == 0 || type >= ZEBRA_ROUTE_MAX) + return; + vrf_bitmap_unset (client->redist[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. */ @@ -372,14 +338,17 @@ zebra_interface_address_add_update (struct interface * if (IS_ZEBRA_DEBUG_EVENT) { - char buf[INET6_ADDRSTRLEN]; + char buf[PREFIX_STRLEN]; p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s/%d on %s", - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), - p->prefixlen, ifc->ifp->name); + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", + prefix2str (p, buf, sizeof(buf)), + ifc->ifp->name); } + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + zlog_warn("WARNING: advertising address to clients that is not yet usable."); + router_id_add_address(ifc); for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) @@ -398,12 +367,12 @@ zebra_interface_address_delete_update (struct interfac if (IS_ZEBRA_DEBUG_EVENT) { - char buf[INET6_ADDRSTRLEN]; + char buf[PREFIX_STRLEN]; p = ifc->address; - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s/%d on %s", - inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN), - p->prefixlen, ifc->ifp->name); + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", + prefix2str (p, buf, sizeof(buf)), + ifc->ifp->name); } router_id_del_address(ifc);