version 1.1, 2012/02/21 17:26:11
|
version 1.1.1.3, 2013/07/21 23:54:41
|
Line 40
|
Line 40
|
#include "zebra/zserv.h" |
#include "zebra/zserv.h" |
#include "zebra/redistribute.h" |
#include "zebra/redistribute.h" |
#include "zebra/debug.h" |
#include "zebra/debug.h" |
|
#include "zebra/zebra_fpm.h" |
|
|
/* Default rtm_table for all clients */ |
/* Default rtm_table for all clients */ |
extern struct zebra_t zebrad; |
extern struct zebra_t zebrad; |
Line 55 static const struct
|
Line 56 static const struct
|
{ |
{ |
int key; |
int key; |
int distance; |
int distance; |
} route_info[] = | } route_info[ZEBRA_ROUTE_MAX] = |
{ |
{ |
{ZEBRA_ROUTE_SYSTEM, 0}, | [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0}, |
{ZEBRA_ROUTE_KERNEL, 0}, | [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0}, |
{ZEBRA_ROUTE_CONNECT, 0}, | [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0}, |
{ZEBRA_ROUTE_STATIC, 1}, | [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1}, |
{ZEBRA_ROUTE_RIP, 120}, | [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120}, |
{ZEBRA_ROUTE_RIPNG, 120}, | [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120}, |
{ZEBRA_ROUTE_OSPF, 110}, | [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110}, |
{ZEBRA_ROUTE_OSPF6, 110}, | [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110}, |
{ZEBRA_ROUTE_ISIS, 115}, | [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115}, |
{ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */} | [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */}, |
| [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 95}, |
| /* no entry/default: 150 */ |
}; |
}; |
|
|
/* Vector for routing table. */ |
/* Vector for routing table. */ |
static vector vrf_vector; |
static vector vrf_vector; |
|
|
|
/* |
|
* vrf_table_create |
|
*/ |
|
static void |
|
vrf_table_create (struct vrf *vrf, afi_t afi, safi_t safi) |
|
{ |
|
rib_table_info_t *info; |
|
struct route_table *table; |
|
|
|
assert (!vrf->table[afi][safi]); |
|
|
|
table = route_table_init (); |
|
vrf->table[afi][safi] = table; |
|
|
|
info = XCALLOC (MTYPE_RIB_TABLE_INFO, sizeof (*info)); |
|
info->vrf = vrf; |
|
info->afi = afi; |
|
info->safi = safi; |
|
table->info = info; |
|
} |
|
|
/* Allocate new VRF. */ |
/* Allocate new VRF. */ |
static struct vrf * |
static struct vrf * |
vrf_alloc (const char *name) |
vrf_alloc (const char *name) |
Line 85 vrf_alloc (const char *name)
|
Line 109 vrf_alloc (const char *name)
|
vrf->name = XSTRDUP (MTYPE_VRF_NAME, name); |
vrf->name = XSTRDUP (MTYPE_VRF_NAME, name); |
|
|
/* Allocate routing table and static table. */ |
/* Allocate routing table and static table. */ |
vrf->table[AFI_IP][SAFI_UNICAST] = route_table_init (); | vrf_table_create (vrf, AFI_IP, SAFI_UNICAST); |
vrf->table[AFI_IP6][SAFI_UNICAST] = route_table_init (); | vrf_table_create (vrf, AFI_IP6, SAFI_UNICAST); |
vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); |
vrf->stable[AFI_IP][SAFI_UNICAST] = route_table_init (); |
vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); |
vrf->stable[AFI_IP6][SAFI_UNICAST] = route_table_init (); |
|
vrf_table_create (vrf, AFI_IP, SAFI_MULTICAST); |
|
vrf_table_create (vrf, AFI_IP6, SAFI_MULTICAST); |
|
vrf->stable[AFI_IP][SAFI_MULTICAST] = route_table_init (); |
|
vrf->stable[AFI_IP6][SAFI_MULTICAST] = route_table_init (); |
|
|
|
|
return vrf; |
return vrf; |
} |
} |
|
|
Line 126 vrf_table (afi_t afi, safi_t safi, u_int32_t id)
|
Line 155 vrf_table (afi_t afi, safi_t safi, u_int32_t id)
|
if (! vrf) |
if (! vrf) |
return NULL; |
return NULL; |
|
|
|
if( afi >= AFI_MAX || safi >= SAFI_MAX ) |
|
return NULL; |
|
|
return vrf->table[afi][safi]; |
return vrf->table[afi][safi]; |
} |
} |
|
|
Line 139 vrf_static_table (afi_t afi, safi_t safi, u_int32_t id
|
Line 171 vrf_static_table (afi_t afi, safi_t safi, u_int32_t id
|
if (! vrf) |
if (! vrf) |
return NULL; |
return NULL; |
|
|
|
if( afi >= AFI_MAX || safi >= SAFI_MAX ) |
|
return NULL; |
|
|
return vrf->stable[afi][safi]; |
return vrf->stable[afi][safi]; |
} |
} |
|
|
|
/* |
|
* nexthop_type_to_str |
|
*/ |
|
const char * |
|
nexthop_type_to_str (enum nexthop_types_t nh_type) |
|
{ |
|
static const char *desc[] = { |
|
"none", |
|
"Directly connected", |
|
"Interface route", |
|
"IPv4 nexthop", |
|
"IPv4 nexthop with ifindex", |
|
"IPv4 nexthop with ifname", |
|
"IPv6 nexthop", |
|
"IPv6 nexthop with ifindex", |
|
"IPv6 nexthop with ifname", |
|
"Null0 nexthop", |
|
}; |
|
|
|
if (nh_type >= ZEBRA_NUM_OF (desc)) |
|
return "<Invalid nh type>"; |
|
|
|
return desc[nh_type]; |
|
} |
|
|
/* Add nexthop to the end of the list. */ |
/* Add nexthop to the end of the list. */ |
static void |
static void |
nexthop_add (struct rib *rib, struct nexthop *nexthop) |
nexthop_add (struct rib *rib, struct nexthop *nexthop) |
Line 225 nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv
|
Line 285 nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv
|
return nexthop; |
return nexthop; |
} |
} |
|
|
static struct nexthop * | struct nexthop * |
nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, |
nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, |
struct in_addr *src, unsigned int ifindex) |
struct in_addr *src, unsigned int ifindex) |
{ |
{ |
Line 344 nexthop_active_ipv4 (struct rib *rib, struct nexthop *
|
Line 404 nexthop_active_ipv4 (struct rib *rib, struct nexthop *
|
return 0; |
return 0; |
|
|
/* Pick up selected route. */ |
/* Pick up selected route. */ |
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 445 nexthop_active_ipv6 (struct rib *rib, struct nexthop *
|
Line 505 nexthop_active_ipv6 (struct rib *rib, struct nexthop *
|
return 0; |
return 0; |
|
|
/* Pick up selected route. */ |
/* Pick up selected route. */ |
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 536 rib_match_ipv4 (struct in_addr addr)
|
Line 596 rib_match_ipv4 (struct in_addr addr)
|
route_unlock_node (rn); |
route_unlock_node (rn); |
|
|
/* Pick up selected route. */ |
/* Pick up selected route. */ |
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 594 rib_lookup_ipv4 (struct prefix_ipv4 *p)
|
Line 654 rib_lookup_ipv4 (struct prefix_ipv4 *p)
|
/* Unlock node. */ |
/* Unlock node. */ |
route_unlock_node (rn); |
route_unlock_node (rn); |
|
|
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 651 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
Line 711 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
route_unlock_node (rn); |
route_unlock_node (rn); |
|
|
/* Find out if a "selected" RR for the discovered RIB entry exists ever. */ |
/* Find out if a "selected" RR for the discovered RIB entry exists ever. */ |
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 671 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
Line 731 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) |
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) |
{ |
{ |
/* We are happy with either direct or recursive hexthop */ |
/* We are happy with either direct or recursive hexthop */ |
if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr || | if (nexthop->gate.ipv4.s_addr == sockunion2ip (qgate) || |
nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr) | nexthop->rgate.ipv4.s_addr == sockunion2ip (qgate)) |
return ZEBRA_RIB_FOUND_EXACT; |
return ZEBRA_RIB_FOUND_EXACT; |
else |
else |
{ |
{ |
Line 681 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
Line 741 rib_lookup_ipv4_route (struct prefix_ipv4 *p, union so
|
char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; |
char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; |
inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); |
inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); |
inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN); |
inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN); |
inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN); | inet_ntop (AF_INET, &sockunion2ip (qgate), qgate_buf, INET_ADDRSTRLEN); |
zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf); |
zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf); |
} |
} |
return ZEBRA_RIB_FOUND_NOGATE; |
return ZEBRA_RIB_FOUND_NOGATE; |
Line 718 rib_match_ipv6 (struct in6_addr *addr)
|
Line 778 rib_match_ipv6 (struct in6_addr *addr)
|
route_unlock_node (rn); |
route_unlock_node (rn); |
|
|
/* Pick up selected route. */ |
/* Pick up selected route. */ |
for (match = rn->info; match; match = match->next) | RNODE_FOREACH_RIB (rn, match) |
{ |
{ |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 908 rib_install_kernel (struct route_node *rn, struct rib
|
Line 968 rib_install_kernel (struct route_node *rn, struct rib
|
int ret = 0; |
int ret = 0; |
struct nexthop *nexthop; |
struct nexthop *nexthop; |
|
|
|
/* |
|
* Make sure we update the FPM any time we send new information to |
|
* the kernel. |
|
*/ |
|
zfpm_trigger_update (rn, "installing in kernel"); |
switch (PREFIX_FAMILY (&rn->p)) |
switch (PREFIX_FAMILY (&rn->p)) |
{ |
{ |
case AF_INET: |
case AF_INET: |
Line 935 rib_uninstall_kernel (struct route_node *rn, struct ri
|
Line 1000 rib_uninstall_kernel (struct route_node *rn, struct ri
|
int ret = 0; |
int ret = 0; |
struct nexthop *nexthop; |
struct nexthop *nexthop; |
|
|
|
/* |
|
* Make sure we update the FPM any time we send new information to |
|
* the kernel. |
|
*/ |
|
zfpm_trigger_update (rn, "uninstalling from kernel"); |
|
|
switch (PREFIX_FAMILY (&rn->p)) |
switch (PREFIX_FAMILY (&rn->p)) |
{ |
{ |
case AF_INET: |
case AF_INET: |
Line 959 rib_uninstall (struct route_node *rn, struct rib *rib)
|
Line 1030 rib_uninstall (struct route_node *rn, struct rib *rib)
|
{ |
{ |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
{ |
{ |
|
zfpm_trigger_update (rn, "rib_uninstall"); |
|
|
redistribute_delete (&rn->p, rib); |
redistribute_delete (&rn->p, rib); |
if (! RIB_SYSTEM_ROUTE (rib)) |
if (! RIB_SYSTEM_ROUTE (rib)) |
rib_uninstall_kernel (rn, rib); |
rib_uninstall_kernel (rn, rib); |
Line 968 rib_uninstall (struct route_node *rn, struct rib *rib)
|
Line 1041 rib_uninstall (struct route_node *rn, struct rib *rib)
|
|
|
static void rib_unlink (struct route_node *, struct rib *); |
static void rib_unlink (struct route_node *, struct rib *); |
|
|
|
/* |
|
* rib_can_delete_dest |
|
* |
|
* Returns TRUE if the given dest can be deleted from the table. |
|
*/ |
|
static int |
|
rib_can_delete_dest (rib_dest_t *dest) |
|
{ |
|
if (dest->routes) |
|
{ |
|
return 0; |
|
} |
|
|
|
/* |
|
* Don't delete the dest if we have to update the FPM about this |
|
* prefix. |
|
*/ |
|
if (CHECK_FLAG (dest->flags, RIB_DEST_UPDATE_FPM) || |
|
CHECK_FLAG (dest->flags, RIB_DEST_SENT_TO_FPM)) |
|
return 0; |
|
|
|
return 1; |
|
} |
|
|
|
/* |
|
* rib_gc_dest |
|
* |
|
* Garbage collect the rib dest corresponding to the given route node |
|
* if appropriate. |
|
* |
|
* Returns TRUE if the dest was deleted, FALSE otherwise. |
|
*/ |
|
int |
|
rib_gc_dest (struct route_node *rn) |
|
{ |
|
rib_dest_t *dest; |
|
char buf[INET6_ADDRSTRLEN]; |
|
|
|
dest = rib_dest_from_rnode (rn); |
|
if (!dest) |
|
return 0; |
|
|
|
if (!rib_can_delete_dest (dest)) |
|
return 0; |
|
|
|
if (IS_ZEBRA_DEBUG_RIB) |
|
{ |
|
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)); |
|
zlog_debug ("%s: %s/%d: removing dest from table", __func__, |
|
buf, rn->p.prefixlen); |
|
} |
|
|
|
dest->rnode = NULL; |
|
XFREE (MTYPE_RIB_DEST, dest); |
|
rn->info = NULL; |
|
|
|
/* |
|
* Release the one reference that we keep on the route node. |
|
*/ |
|
route_unlock_node (rn); |
|
return 1; |
|
} |
|
|
/* Core function for processing routing information base. */ |
/* Core function for processing routing information base. */ |
static void |
static void |
rib_process (struct route_node *rn) |
rib_process (struct route_node *rn) |
Line 986 rib_process (struct route_node *rn)
|
Line 1122 rib_process (struct route_node *rn)
|
if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q) |
if (IS_ZEBRA_DEBUG_RIB || IS_ZEBRA_DEBUG_RIB_Q) |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
|
|
for (rib = rn->info; rib; rib = next) | RNODE_FOREACH_RIB_SAFE (rn, rib, next) |
{ |
{ |
/* The next pointer is saved, because current pointer |
|
* may be passed to rib_unlink() in the middle of iteration. |
|
*/ |
|
next = rib->next; |
|
|
|
/* Currently installed rib. */ |
/* Currently installed rib. */ |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
{ |
{ |
Line 1010 rib_process (struct route_node *rn)
|
Line 1141 rib_process (struct route_node *rn)
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__, |
zlog_debug ("%s: %s/%d: rn %p, removing rib %p", __func__, |
buf, rn->p.prefixlen, rn, rib); |
buf, rn->p.prefixlen, rn, rib); |
rib_unlink (rn, rib); | rib_unlink (rn, rib); |
} |
} |
else |
else |
del = rib; |
del = rib; |
Line 1067 rib_process (struct route_node *rn)
|
Line 1198 rib_process (struct route_node *rn)
|
/* metric tie-breaks equal distance */ |
/* metric tie-breaks equal distance */ |
if (rib->metric <= select->metric) |
if (rib->metric <= select->metric) |
select = rib; |
select = rib; |
} /* for (rib = rn->info; rib; rib = next) */ | } /* RNODE_FOREACH_RIB_SAFE */ |
|
|
/* After the cycle is finished, the following pointers will be set: |
/* After the cycle is finished, the following pointers will be set: |
* select --- the winner RIB entry, if any was found, otherwise NULL |
* select --- the winner RIB entry, if any was found, otherwise NULL |
Line 1084 rib_process (struct route_node *rn)
|
Line 1215 rib_process (struct route_node *rn)
|
__func__, buf, rn->p.prefixlen, select, fib); |
__func__, buf, rn->p.prefixlen, select, fib); |
if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) |
if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) |
{ |
{ |
|
zfpm_trigger_update (rn, "updating existing route"); |
|
|
redistribute_delete (&rn->p, select); |
redistribute_delete (&rn->p, select); |
if (! RIB_SYSTEM_ROUTE (select)) |
if (! RIB_SYSTEM_ROUTE (select)) |
rib_uninstall_kernel (rn, select); |
rib_uninstall_kernel (rn, select); |
Line 1125 rib_process (struct route_node *rn)
|
Line 1258 rib_process (struct route_node *rn)
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__, |
zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__, |
buf, rn->p.prefixlen, fib); |
buf, rn->p.prefixlen, fib); |
|
|
|
zfpm_trigger_update (rn, "removing existing route"); |
|
|
redistribute_delete (&rn->p, fib); |
redistribute_delete (&rn->p, fib); |
if (! RIB_SYSTEM_ROUTE (fib)) |
if (! RIB_SYSTEM_ROUTE (fib)) |
rib_uninstall_kernel (rn, fib); |
rib_uninstall_kernel (rn, fib); |
Line 1143 rib_process (struct route_node *rn)
|
Line 1279 rib_process (struct route_node *rn)
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf, |
zlog_debug ("%s: %s/%d: Adding route, select %p", __func__, buf, |
rn->p.prefixlen, select); |
rn->p.prefixlen, select); |
|
|
|
zfpm_trigger_update (rn, "new route selected"); |
|
|
/* Set real nexthop. */ |
/* Set real nexthop. */ |
nexthop_active_update (rn, select, 1); |
nexthop_active_update (rn, select, 1); |
|
|
Line 1164 rib_process (struct route_node *rn)
|
Line 1303 rib_process (struct route_node *rn)
|
end: |
end: |
if (IS_ZEBRA_DEBUG_RIB_Q) |
if (IS_ZEBRA_DEBUG_RIB_Q) |
zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn); |
zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn); |
|
|
|
/* |
|
* Check if the dest can be deleted now. |
|
*/ |
|
rib_gc_dest (rn); |
} |
} |
|
|
/* Take a list of route_node structs and return 1, if there was a record |
/* Take a list of route_node structs and return 1, if there was a record |
Line 1182 process_subq (struct list * subq, u_char qindex)
|
Line 1326 process_subq (struct list * subq, u_char qindex)
|
rnode = listgetdata (lnode); |
rnode = listgetdata (lnode); |
rib_process (rnode); |
rib_process (rnode); |
|
|
if (rnode->info) /* The first RIB record is holding the flags bitmask. */ | if (rnode->info) |
UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); | UNSET_FLAG (rib_dest_from_rnode (rnode)->flags, RIB_ROUTE_QUEUED (qindex)); |
| |
#if 0 |
#if 0 |
else |
else |
{ |
{ |
Line 1216 meta_queue_process (struct work_queue *dummy, void *da
|
Line 1361 meta_queue_process (struct work_queue *dummy, void *da
|
return mq->size ? WQ_REQUEUE : WQ_SUCCESS; |
return mq->size ? WQ_REQUEUE : WQ_SUCCESS; |
} |
} |
|
|
/* Map from rib types to queue type (priority) in meta queue */ | /* |
| * Map from rib types to queue type (priority) in meta queue |
| */ |
static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { |
static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { |
[ZEBRA_ROUTE_SYSTEM] = 4, |
[ZEBRA_ROUTE_SYSTEM] = 4, |
[ZEBRA_ROUTE_KERNEL] = 0, |
[ZEBRA_ROUTE_KERNEL] = 0, |
Line 1229 static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] =
|
Line 1376 static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] =
|
[ZEBRA_ROUTE_ISIS] = 2, |
[ZEBRA_ROUTE_ISIS] = 2, |
[ZEBRA_ROUTE_BGP] = 3, |
[ZEBRA_ROUTE_BGP] = 3, |
[ZEBRA_ROUTE_HSLS] = 4, |
[ZEBRA_ROUTE_HSLS] = 4, |
|
[ZEBRA_ROUTE_BABEL] = 2, |
}; |
}; |
|
|
/* Look into the RN and queue it into one or more priority queues, |
/* Look into the RN and queue it into one or more priority queues, |
Line 1243 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
Line 1391 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
if (IS_ZEBRA_DEBUG_RIB_Q) |
if (IS_ZEBRA_DEBUG_RIB_Q) |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
|
|
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
u_char qindex = meta_queue_map[rib->type]; |
u_char qindex = meta_queue_map[rib->type]; |
|
|
/* Invariant: at this point we always have rn->info set. */ |
/* Invariant: at this point we always have rn->info set. */ |
if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex))) | if (CHECK_FLAG (rib_dest_from_rnode (rn)->flags, |
| RIB_ROUTE_QUEUED (qindex))) |
{ |
{ |
if (IS_ZEBRA_DEBUG_RIB_Q) |
if (IS_ZEBRA_DEBUG_RIB_Q) |
zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", |
zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", |
Line 1256 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
Line 1405 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
continue; |
continue; |
} |
} |
|
|
SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); | SET_FLAG (rib_dest_from_rnode (rn)->flags, RIB_ROUTE_QUEUED (qindex)); |
listnode_add (mq->subq[qindex], rn); |
listnode_add (mq->subq[qindex], rn); |
route_lock_node (rn); |
route_lock_node (rn); |
mq->size++; |
mq->size++; |
Line 1271 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
Line 1420 rib_meta_queue_add (struct meta_queue *mq, struct rout
|
static void |
static void |
rib_queue_add (struct zebra_t *zebra, struct route_node *rn) |
rib_queue_add (struct zebra_t *zebra, struct route_node *rn) |
{ |
{ |
|
char buf[INET_ADDRSTRLEN]; |
|
assert (zebra && rn); |
|
|
if (IS_ZEBRA_DEBUG_RIB_Q) |
if (IS_ZEBRA_DEBUG_RIB_Q) |
|
inet_ntop (AF_INET, &rn->p.u.prefix, buf, INET_ADDRSTRLEN); |
|
|
|
/* Pointless to queue a route_node with no RIB entries to add or remove */ |
|
if (!rnode_to_ribs (rn)) |
{ |
{ |
char buf[INET6_ADDRSTRLEN]; | zlog_debug ("%s: called for route_node (%p, %d) with no ribs", |
| __func__, rn, rn->lock); |
| zlog_backtrace(LOG_DEBUG); |
| return; |
| } |
|
|
zlog_info ("%s: %s/%d: work queue added", __func__, | if (IS_ZEBRA_DEBUG_RIB_Q) |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN), | zlog_info ("%s: %s/%d: work queue added", __func__, buf, rn->p.prefixlen); |
rn->p.prefixlen); | |
| assert (zebra); |
| |
| if (zebra->ribq == NULL) |
| { |
| zlog_err ("%s: work_queue does not exist!", __func__); |
| return; |
} |
} |
|
|
/* |
/* |
Line 1293 rib_queue_add (struct zebra_t *zebra, struct route_nod
|
Line 1458 rib_queue_add (struct zebra_t *zebra, struct route_nod
|
work_queue_add (zebra->ribq, zebra->mq); |
work_queue_add (zebra->ribq, zebra->mq); |
|
|
rib_meta_queue_add (zebra->mq, rn); |
rib_meta_queue_add (zebra->mq, rn); |
|
|
|
if (IS_ZEBRA_DEBUG_RIB_Q) |
|
zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn); |
|
|
|
return; |
} |
} |
|
|
/* Create new meta queue. |
/* Create new meta queue. |
Line 1320 meta_queue_new (void)
|
Line 1490 meta_queue_new (void)
|
static void |
static void |
rib_queue_init (struct zebra_t *zebra) |
rib_queue_init (struct zebra_t *zebra) |
{ |
{ |
|
assert (zebra); |
|
|
if (! (zebra->ribq = work_queue_new (zebra->master, |
if (! (zebra->ribq = work_queue_new (zebra->master, |
"route_node processing"))) |
"route_node processing"))) |
{ |
{ |
Line 1335 rib_queue_init (struct zebra_t *zebra)
|
Line 1507 rib_queue_init (struct zebra_t *zebra)
|
zebra->ribq->spec.hold = rib_process_hold_time; |
zebra->ribq->spec.hold = rib_process_hold_time; |
|
|
if (!(zebra->mq = meta_queue_new ())) |
if (!(zebra->mq = meta_queue_new ())) |
|
{ |
zlog_err ("%s: could not initialise meta queue!", __func__); |
zlog_err ("%s: could not initialise meta queue!", __func__); |
|
return; |
|
} |
|
return; |
} |
} |
|
|
/* RIB updates are processed via a queue of pointers to route_nodes. |
/* RIB updates are processed via a queue of pointers to route_nodes. |
Line 1360 rib_queue_init (struct zebra_t *zebra)
|
Line 1536 rib_queue_init (struct zebra_t *zebra)
|
* |-> set RIB_ENTRY_REMOVE | |
* |-> set RIB_ENTRY_REMOVE | |
* rib_delnode (RIB freed) |
* rib_delnode (RIB freed) |
* |
* |
* | * The 'info' pointer of a route_node points to a rib_dest_t |
* Queueing state for a route_node is kept in the head RIB entry, this | * ('dest'). Queueing state for a route_node is kept on the dest. The |
* state must be preserved as and when the head RIB entry of a | * dest is created on-demand by rib_link() and is kept around at least |
* route_node is changed by rib_unlink / rib_link. A small complication, | * as long as there are ribs hanging off it (@see rib_gc_dest()). |
* but saves having to allocate a dedicated object for this. | |
* |
* |
* Refcounting (aka "locking" throughout the GNU Zebra and Quagga code): |
* Refcounting (aka "locking" throughout the GNU Zebra and Quagga code): |
* |
* |
* - route_nodes: refcounted by: |
* - route_nodes: refcounted by: |
* - RIBs attached to route_node: | * - dest attached to route_node: |
* - managed by: rib_link/unlink | * - managed by: rib_link/rib_gc_dest |
* - route_node processing queue |
* - route_node processing queue |
* - managed by: rib_addqueue, rib_process. |
* - managed by: rib_addqueue, rib_process. |
* |
* |
Line 1381 static void
|
Line 1556 static void
|
rib_link (struct route_node *rn, struct rib *rib) |
rib_link (struct route_node *rn, struct rib *rib) |
{ |
{ |
struct rib *head; |
struct rib *head; |
|
rib_dest_t *dest; |
char buf[INET6_ADDRSTRLEN]; |
char buf[INET6_ADDRSTRLEN]; |
| |
assert (rib && rn); |
assert (rib && rn); |
|
|
route_lock_node (rn); /* rn route table reference */ |
|
|
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
{ |
{ |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); |
Line 1394 rib_link (struct route_node *rn, struct rib *rib)
|
Line 1568 rib_link (struct route_node *rn, struct rib *rib)
|
buf, rn->p.prefixlen, rn, rib); |
buf, rn->p.prefixlen, rn, rib); |
} |
} |
|
|
head = rn->info; | dest = rib_dest_from_rnode (rn); |
if (head) | if (!dest) |
{ |
{ |
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: %s/%d: new head, rn_status copied over", __func__, | { |
buf, rn->p.prefixlen); | zlog_debug ("%s: %s/%d: adding dest to table", __func__, |
| buf, rn->p.prefixlen); |
| } |
| |
| dest = XCALLOC (MTYPE_RIB_DEST, sizeof (rib_dest_t)); |
| route_lock_node (rn); /* rn route table reference */ |
| rn->info = dest; |
| dest->rnode = rn; |
| } |
| |
| head = dest->routes; |
| if (head) |
| { |
head->prev = rib; |
head->prev = rib; |
/* Transfer the rn status flags to the new head RIB */ |
|
rib->rn_status = head->rn_status; |
|
} |
} |
rib->next = head; |
rib->next = head; |
rn->info = rib; | dest->routes = rib; |
rib_queue_add (&zebrad, rn); |
rib_queue_add (&zebrad, rn); |
} |
} |
|
|
Line 1430 rib_addnode (struct route_node *rn, struct rib *rib)
|
Line 1614 rib_addnode (struct route_node *rn, struct rib *rib)
|
rib_link (rn, rib); |
rib_link (rn, rib); |
} |
} |
|
|
|
/* |
|
* rib_unlink |
|
* |
|
* Detach a rib structure from a route_node. |
|
* |
|
* Note that a call to rib_unlink() should be followed by a call to |
|
* rib_gc_dest() at some point. This allows a rib_dest_t that is no |
|
* longer required to be deleted. |
|
*/ |
static void |
static void |
rib_unlink (struct route_node *rn, struct rib *rib) |
rib_unlink (struct route_node *rn, struct rib *rib) |
{ |
{ |
struct nexthop *nexthop, *next; |
struct nexthop *nexthop, *next; |
char buf[INET6_ADDRSTRLEN]; |
char buf[INET6_ADDRSTRLEN]; |
|
rib_dest_t *dest; |
|
|
assert (rn && rib); |
assert (rn && rib); |
|
|
Line 1445 rib_unlink (struct route_node *rn, struct rib *rib)
|
Line 1639 rib_unlink (struct route_node *rn, struct rib *rib)
|
__func__, buf, rn->p.prefixlen, rn, rib); |
__func__, buf, rn->p.prefixlen, rn, rib); |
} |
} |
|
|
|
dest = rib_dest_from_rnode (rn); |
|
|
if (rib->next) |
if (rib->next) |
rib->next->prev = rib->prev; |
rib->next->prev = rib->prev; |
|
|
Line 1452 rib_unlink (struct route_node *rn, struct rib *rib)
|
Line 1648 rib_unlink (struct route_node *rn, struct rib *rib)
|
rib->prev->next = rib->next; |
rib->prev->next = rib->next; |
else |
else |
{ |
{ |
rn->info = rib->next; | dest->routes = rib->next; |
| |
if (rn->info) | |
{ | |
if (IS_ZEBRA_DEBUG_RIB) | |
zlog_debug ("%s: %s/%d: rn %p, rib %p, new head copy", | |
__func__, buf, rn->p.prefixlen, rn, rib); | |
rib->next->rn_status = rib->rn_status; | |
} | |
} |
} |
|
|
/* free RIB and nexthops */ |
/* free RIB and nexthops */ |
Line 1471 rib_unlink (struct route_node *rn, struct rib *rib)
|
Line 1659 rib_unlink (struct route_node *rn, struct rib *rib)
|
} |
} |
XFREE (MTYPE_RIB, rib); |
XFREE (MTYPE_RIB, rib); |
|
|
route_unlock_node (rn); /* rn route table reference */ |
|
} |
} |
|
|
static void |
static void |
Line 1492 int
|
Line 1679 int
|
rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, |
rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, |
struct in_addr *gate, struct in_addr *src, |
struct in_addr *gate, struct in_addr *src, |
unsigned int ifindex, u_int32_t vrf_id, |
unsigned int ifindex, u_int32_t vrf_id, |
u_int32_t metric, u_char distance) | u_int32_t metric, u_char distance, safi_t safi) |
{ |
{ |
struct rib *rib; |
struct rib *rib; |
struct rib *same = NULL; |
struct rib *same = NULL; |
Line 1501 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
Line 1688 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
struct nexthop *nexthop; |
struct nexthop *nexthop; |
|
|
/* Lookup table. */ |
/* Lookup table. */ |
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); | table = vrf_table (AFI_IP, safi, 0); |
if (! table) |
if (! table) |
return 0; |
return 0; |
|
|
Line 1511 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
Line 1698 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
/* Set default distance by route type. */ |
/* Set default distance by route type. */ |
if (distance == 0) |
if (distance == 0) |
{ |
{ |
distance = route_info[type].distance; | if ((unsigned)type >= array_size(route_info)) |
| distance = 150; |
| else |
| distance = route_info[type].distance; |
|
|
/* iBGP distance is 200. */ |
/* iBGP distance is 200. */ |
if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) |
if (type == ZEBRA_ROUTE_BGP && CHECK_FLAG (flags, ZEBRA_FLAG_IBGP)) |
Line 1523 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
Line 1713 rib_add_ipv4 (int type, int flags, struct prefix_ipv4
|
|
|
/* If same type of route are installed, treat it as a implicit |
/* If same type of route are installed, treat it as a implicit |
withdraw. */ |
withdraw. */ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 1679 void rib_lookup_and_dump (struct prefix_ipv4 * p)
|
Line 1869 void rib_lookup_and_dump (struct prefix_ipv4 * p)
|
route_unlock_node (rn); |
route_unlock_node (rn); |
|
|
/* let's go */ |
/* let's go */ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
zlog_debug |
zlog_debug |
( |
( |
Line 1726 void rib_lookup_and_pushup (struct prefix_ipv4 * p)
|
Line 1916 void rib_lookup_and_pushup (struct prefix_ipv4 * p)
|
* RIBQ record already on head. This is necessary for proper revalidation |
* RIBQ record already on head. This is necessary for proper revalidation |
* of the rest of the RIB. |
* of the rest of the RIB. |
*/ |
*/ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) && |
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) && |
! RIB_SYSTEM_ROUTE (rib)) |
! RIB_SYSTEM_ROUTE (rib)) |
Line 1747 void rib_lookup_and_pushup (struct prefix_ipv4 * p)
|
Line 1937 void rib_lookup_and_pushup (struct prefix_ipv4 * p)
|
} |
} |
|
|
int |
int |
rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib) | rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) |
{ |
{ |
struct route_table *table; |
struct route_table *table; |
struct route_node *rn; |
struct route_node *rn; |
Line 1755 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
Line 1945 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
struct nexthop *nexthop; |
struct nexthop *nexthop; |
|
|
/* Lookup table. */ |
/* Lookup table. */ |
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); | table = vrf_table (AFI_IP, safi, 0); |
if (! table) |
if (! table) |
return 0; |
return 0; |
|
|
/* Make it sure prefixlen is applied to the prefix. */ |
/* Make it sure prefixlen is applied to the prefix. */ |
apply_mask_ipv4 (p); |
apply_mask_ipv4 (p); |
|
|
Line 1777 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
Line 1968 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
|
|
/* If same type of route are installed, treat it as a implicit |
/* If same type of route are installed, treat it as a implicit |
withdraw. */ |
withdraw. */ |
for (same = rn->info; same; same = same->next) | RNODE_FOREACH_RIB (rn, same) |
{ |
{ |
if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (same->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 1820 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
Line 2011 rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct
|
/* XXX factor with rib_delete_ipv6 */ |
/* XXX factor with rib_delete_ipv6 */ |
int |
int |
rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, |
rib_delete_ipv4 (int type, int flags, struct prefix_ipv4 *p, |
struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id) | struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi) |
{ |
{ |
struct route_table *table; |
struct route_table *table; |
struct route_node *rn; |
struct route_node *rn; |
Line 1832 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
Line 2023 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
char buf2[INET_ADDRSTRLEN]; |
char buf2[INET_ADDRSTRLEN]; |
|
|
/* Lookup table. */ |
/* Lookup table. */ |
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); | table = vrf_table (AFI_IP, safi, 0); |
if (! table) |
if (! table) |
return 0; |
return 0; |
|
|
Line 1868 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
Line 2059 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
} |
} |
|
|
/* Lookup same type route. */ |
/* Lookup same type route. */ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 1879 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
Line 2070 rib_delete_ipv4 (int type, int flags, struct prefix_ip
|
if (rib->type != type) |
if (rib->type != type) |
continue; |
continue; |
if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && |
if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && |
nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) | nexthop->type == NEXTHOP_TYPE_IFINDEX) |
{ |
{ |
|
if (nexthop->ifindex != ifindex) |
|
continue; |
if (rib->refcnt) |
if (rib->refcnt) |
{ |
{ |
rib->refcnt--; |
rib->refcnt--; |
Line 1959 static_install_ipv4 (struct prefix *p, struct static_i
|
Line 2152 static_install_ipv4 (struct prefix *p, struct static_i
|
|
|
/* Lookup existing route */ |
/* Lookup existing route */ |
rn = route_node_get (table, p); |
rn = route_node_get (table, p); |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 1995 static_install_ipv4 (struct prefix *p, struct static_i
|
Line 2188 static_install_ipv4 (struct prefix *p, struct static_i
|
rib->type = ZEBRA_ROUTE_STATIC; |
rib->type = ZEBRA_ROUTE_STATIC; |
rib->distance = si->distance; |
rib->distance = si->distance; |
rib->metric = 0; |
rib->metric = 0; |
|
rib->table = zebrad.rtm_table_default; |
rib->nexthop_num = 0; |
rib->nexthop_num = 0; |
|
|
switch (si->type) |
switch (si->type) |
Line 2054 static_uninstall_ipv4 (struct prefix *p, struct static
|
Line 2248 static_uninstall_ipv4 (struct prefix *p, struct static
|
if (! rn) |
if (! rn) |
return; |
return; |
|
|
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 2281 rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
|
Line 2475 rib_bogus_ipv6 (int type, struct prefix_ipv6 *p,
|
int |
int |
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, |
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, |
struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, |
struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, |
u_int32_t metric, u_char distance) | u_int32_t metric, u_char distance, safi_t safi) |
{ |
{ |
struct rib *rib; |
struct rib *rib; |
struct rib *same = NULL; |
struct rib *same = NULL; |
Line 2290 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
Line 2484 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
struct nexthop *nexthop; |
struct nexthop *nexthop; |
|
|
/* Lookup table. */ |
/* Lookup table. */ |
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); | table = vrf_table (AFI_IP6, safi, 0); |
if (! table) |
if (! table) |
return 0; |
return 0; |
|
|
Line 2313 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
Line 2507 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
|
|
/* If same type of route are installed, treat it as a implicit |
/* If same type of route are installed, treat it as a implicit |
withdraw. */ |
withdraw. */ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 2375 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
Line 2569 rib_add_ipv6 (int type, int flags, struct prefix_ipv6
|
/* XXX factor with rib_delete_ipv6 */ |
/* XXX factor with rib_delete_ipv6 */ |
int |
int |
rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, |
rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p, |
struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id) | struct in6_addr *gate, unsigned int ifindex, u_int32_t vrf_id, safi_t safi) |
{ |
{ |
struct route_table *table; |
struct route_table *table; |
struct route_node *rn; |
struct route_node *rn; |
Line 2390 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
Line 2584 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
apply_mask_ipv6 (p); |
apply_mask_ipv6 (p); |
|
|
/* Lookup table. */ |
/* Lookup table. */ |
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); | table = vrf_table (AFI_IP6, safi, 0); |
if (! table) |
if (! table) |
return 0; |
return 0; |
|
|
Line 2416 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
Line 2610 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
} |
} |
|
|
/* Lookup same type route. */ |
/* Lookup same type route. */ |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 2427 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
Line 2621 rib_delete_ipv6 (int type, int flags, struct prefix_ip
|
if (rib->type != type) |
if (rib->type != type) |
continue; |
continue; |
if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && |
if (rib->type == ZEBRA_ROUTE_CONNECT && (nexthop = rib->nexthop) && |
nexthop->type == NEXTHOP_TYPE_IFINDEX && nexthop->ifindex == ifindex) | nexthop->type == NEXTHOP_TYPE_IFINDEX) |
{ |
{ |
|
if (nexthop->ifindex != ifindex) |
|
continue; |
if (rib->refcnt) |
if (rib->refcnt) |
{ |
{ |
rib->refcnt--; |
rib->refcnt--; |
Line 2507 static_install_ipv6 (struct prefix *p, struct static_i
|
Line 2703 static_install_ipv6 (struct prefix *p, struct static_i
|
|
|
/* Lookup existing route */ |
/* Lookup existing route */ |
rn = route_node_get (table, p); |
rn = route_node_get (table, p); |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 2604 static_uninstall_ipv6 (struct prefix *p, struct static
|
Line 2800 static_uninstall_ipv6 (struct prefix *p, struct static
|
if (! rn) |
if (! rn) |
return; |
return; |
|
|
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
Line 2800 rib_update (void)
|
Line 2996 rib_update (void)
|
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
table = vrf_table (AFI_IP, SAFI_UNICAST, 0); |
if (table) |
if (table) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
if (rn->info) | if (rnode_to_ribs (rn)) |
rib_queue_add (&zebrad, rn); |
rib_queue_add (&zebrad, rn); |
|
|
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); |
if (table) |
if (table) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
if (rn->info) | if (rnode_to_ribs (rn)) |
rib_queue_add (&zebrad, rn); |
rib_queue_add (&zebrad, rn); |
} |
} |
|
|
Line 2821 rib_weed_table (struct route_table *table)
|
Line 3017 rib_weed_table (struct route_table *table)
|
|
|
if (table) |
if (table) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rib = rn->info; rib; rib = next) | RNODE_FOREACH_RIB_SAFE (rn, rib, next) |
{ |
{ |
next = rib->next; |
|
|
|
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
|
|
Line 2853 rib_sweep_table (struct route_table *table)
|
Line 3047 rib_sweep_table (struct route_table *table)
|
|
|
if (table) |
if (table) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rib = rn->info; rib; rib = next) | RNODE_FOREACH_RIB_SAFE (rn, rib, next) |
{ |
{ |
next = rib->next; |
|
|
|
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
continue; |
continue; |
|
|
Line 2877 rib_sweep_route (void)
|
Line 3069 rib_sweep_route (void)
|
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); |
rib_sweep_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); |
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); |
rib_sweep_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); |
} |
} |
| |
| /* Remove specific by protocol routes from 'table'. */ |
| static unsigned long |
| rib_score_proto_table (u_char proto, struct route_table *table) |
| { |
| struct route_node *rn; |
| struct rib *rib; |
| struct rib *next; |
| unsigned long n = 0; |
| |
| if (table) |
| for (rn = route_top (table); rn; rn = route_next (rn)) |
| RNODE_FOREACH_RIB_SAFE (rn, rib, next) |
| { |
| if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) |
| continue; |
| if (rib->type == proto) |
| { |
| rib_delnode (rn, rib); |
| n++; |
| } |
| } |
| |
| return n; |
| } |
| |
| /* Remove specific by protocol routes. */ |
| unsigned long |
| rib_score_proto (u_char proto) |
| { |
| return rib_score_proto_table (proto, vrf_table (AFI_IP, SAFI_UNICAST, 0)) |
| +rib_score_proto_table (proto, vrf_table (AFI_IP6, SAFI_UNICAST, 0)); |
| } |
| |
/* Close RIB and clean up kernel routes. */ |
/* Close RIB and clean up kernel routes. */ |
static void |
static void |
rib_close_table (struct route_table *table) |
rib_close_table (struct route_table *table) |
Line 2887 rib_close_table (struct route_table *table)
|
Line 3112 rib_close_table (struct route_table *table)
|
|
|
if (table) |
if (table) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rn = route_top (table); rn; rn = route_next (rn)) |
for (rib = rn->info; rib; rib = rib->next) | RNODE_FOREACH_RIB (rn, rib) |
{ |
{ |
if (! RIB_SYSTEM_ROUTE (rib) | if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) |
&& CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) | continue; |
rib_uninstall_kernel (rn, rib); | |
| zfpm_trigger_update (rn, NULL); |
| |
| if (! RIB_SYSTEM_ROUTE (rib)) |
| rib_uninstall_kernel (rn, rib); |
} |
} |
} |
} |
|
|
Line 2910 rib_init (void)
|
Line 3139 rib_init (void)
|
rib_queue_init (&zebrad); |
rib_queue_init (&zebrad); |
/* VRF initialization. */ |
/* VRF initialization. */ |
vrf_init (); |
vrf_init (); |
|
} |
|
|
|
/* |
|
* vrf_id_get_next |
|
* |
|
* Get the first vrf id that is greater than the given vrf id if any. |
|
* |
|
* Returns TRUE if a vrf id was found, FALSE otherwise. |
|
*/ |
|
static inline int |
|
vrf_id_get_next (uint32_t id, uint32_t *next_id_p) |
|
{ |
|
while (++id < vector_active (vrf_vector)) |
|
{ |
|
if (vrf_lookup (id)) |
|
{ |
|
*next_id_p = id; |
|
return 1; |
|
} |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
|
* rib_tables_iter_next |
|
* |
|
* Returns the next table in the iteration. |
|
*/ |
|
struct route_table * |
|
rib_tables_iter_next (rib_tables_iter_t *iter) |
|
{ |
|
struct route_table *table; |
|
|
|
/* |
|
* Array that helps us go over all AFI/SAFI combinations via one |
|
* index. |
|
*/ |
|
static struct { |
|
afi_t afi; |
|
safi_t safi; |
|
} afi_safis[] = { |
|
{ AFI_IP, SAFI_UNICAST }, |
|
{ AFI_IP, SAFI_MULTICAST }, |
|
{ AFI_IP6, SAFI_UNICAST }, |
|
{ AFI_IP6, SAFI_MULTICAST }, |
|
}; |
|
|
|
table = NULL; |
|
|
|
switch (iter->state) |
|
{ |
|
|
|
case RIB_TABLES_ITER_S_INIT: |
|
iter->vrf_id = 0; |
|
iter->afi_safi_ix = -1; |
|
|
|
/* Fall through */ |
|
|
|
case RIB_TABLES_ITER_S_ITERATING: |
|
iter->afi_safi_ix++; |
|
while (1) |
|
{ |
|
|
|
while (iter->afi_safi_ix < (int) ZEBRA_NUM_OF (afi_safis)) |
|
{ |
|
table = vrf_table (afi_safis[iter->afi_safi_ix].afi, |
|
afi_safis[iter->afi_safi_ix].safi, |
|
iter->vrf_id); |
|
if (table) |
|
break; |
|
|
|
iter->afi_safi_ix++; |
|
} |
|
|
|
/* |
|
* Found another table in this vrf. |
|
*/ |
|
if (table) |
|
break; |
|
|
|
/* |
|
* Done with all tables in the current vrf, go to the next |
|
* one. |
|
*/ |
|
if (!vrf_id_get_next (iter->vrf_id, &iter->vrf_id)) |
|
break; |
|
|
|
iter->afi_safi_ix = 0; |
|
} |
|
|
|
break; |
|
|
|
case RIB_TABLES_ITER_S_DONE: |
|
return NULL; |
|
} |
|
|
|
if (table) |
|
iter->state = RIB_TABLES_ITER_S_ITERATING; |
|
else |
|
iter->state = RIB_TABLES_ITER_S_DONE; |
|
|
|
return table; |
} |
} |