diff options
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r-- | zebra/zebra_rib.c | 145 |
1 files changed, 128 insertions, 17 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 50a19477..a10ca84b 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -352,6 +352,17 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, break; } + if (IS_ZEBRA_DEBUG_RIB) { + char buf[INET6_ADDRSTRLEN]; + inet_ntop(rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); + zlog_debug("%s: %s/%d: nexthop match %p: %s type=%d sel=%d int=%d", + __func__, buf, rn->p.prefixlen, match, + match ? zebra_route_string(match->type) : "<?>", + match ? match->type : -1, + match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED) : -1, + match ? CHECK_FLAG(match->flags, ZEBRA_FLAG_INTERNAL) : -1); + } + /* If there is no selected route or matched route is EGP, go up tree. */ if (! match @@ -375,7 +386,8 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, return 1; } - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) + else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) || + match->type == ZEBRA_ROUTE_KERNEL) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) @@ -756,6 +768,43 @@ rib_match_ipv6 (struct in6_addr *addr) } #endif /* HAVE_IPV6 */ +static void nexthop_dump(struct nexthop *nexthop, + char *type_str_buf, + int type_str_buf_size, + char *addr_str_buf, + int addr_str_buf_size, + char *via_str_buf, + int via_str_buf_size) +{ + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV4_IFINDEX: + snprintf(type_str_buf, type_str_buf_size, "ipv4"); + snprintf(addr_str_buf, addr_str_buf_size, "%s", inet_ntoa(nexthop->gate.ipv4)); + snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifindex ? ifindex2ifname(nexthop->ifindex) : "<?>"); + break; + case NEXTHOP_TYPE_IFINDEX: + snprintf(type_str_buf, type_str_buf_size, "connected"); + snprintf(addr_str_buf, addr_str_buf_size, "<connected>"); + snprintf(via_str_buf, via_str_buf_size, "%s", ifindex2ifname(nexthop->ifindex)); + break; + case NEXTHOP_TYPE_IFNAME: + snprintf(type_str_buf, type_str_buf_size, "connected"); + snprintf(addr_str_buf, addr_str_buf_size, "<connected>"); + snprintf(via_str_buf, via_str_buf_size, "%s", nexthop->ifname); + break; + case NEXTHOP_TYPE_BLACKHOLE: + snprintf(type_str_buf, type_str_buf_size, "blackhole"); + snprintf(addr_str_buf, addr_str_buf_size, "<blackhole>"); + snprintf(via_str_buf, via_str_buf_size, "Null0"); + break; + default: + snprintf(type_str_buf, type_str_buf_size, "unknown"); + snprintf(addr_str_buf, addr_str_buf_size, "<unknown>"); + snprintf(via_str_buf, via_str_buf_size, "<?>"); + } +} + #define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) @@ -809,10 +858,27 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: family = AFI_IP; - if (nexthop_active_ipv4 (rib, nexthop, set, rn)) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); - else - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + { + int nh_active = nexthop_active_ipv4 (rib, nexthop, set, rn); + if (IS_ZEBRA_DEBUG_RIB) { + char type_str_buf[100]; + char addr_str_buf[100]; + char via_str_buf[100]; + nexthop_dump(nexthop, + type_str_buf, sizeof(type_str_buf), + addr_str_buf, sizeof(addr_str_buf), + via_str_buf, sizeof(via_str_buf)); + zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d nexthop_active_ipv4=%d", + __func__, rib, nexthop, + nexthop->type, type_str_buf, + addr_str_buf, via_str_buf, nexthop->ifindex, + nh_active); + } + if (nh_active) + SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + else + UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: @@ -892,8 +958,23 @@ nexthop_active_update (struct route_node *rn, struct rib *rib, int set) { prev_active = CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); prev_index = nexthop->ifindex; - if ((new_active = nexthop_active_check (rn, rib, nexthop, set))) + new_active = nexthop_active_check (rn, rib, nexthop, set); + if (new_active) rib->nexthop_active_num++; + if (IS_ZEBRA_DEBUG_RIB) { + char type_str_buf[100]; + char addr_str_buf[100]; + char via_str_buf[100]; + nexthop_dump(nexthop, + type_str_buf, sizeof(type_str_buf), + addr_str_buf, sizeof(addr_str_buf), + via_str_buf, sizeof(via_str_buf)); + zlog_debug("%s: rib %p nexthop %p type=%d %s %s via %s ifindex=%d act=%d total_act=%d", + __func__, rib, nexthop, + nexthop->type, type_str_buf, + addr_str_buf, via_str_buf, nexthop->ifindex, + new_active, rib->nexthop_active_num); + } if (prev_active != new_active || prev_index != nexthop->ifindex) SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); @@ -993,6 +1074,15 @@ rib_process (struct route_node *rn) * may be passed to rib_unlink() in the middle of iteration. */ next = rib->next; + + if (IS_ZEBRA_DEBUG_RIB) { + zlog_debug("%s: %s/%d: scan rib %p: type=%d sel=%d rem=%d nh_act=%d dist=%d", + __func__, buf, rn->p.prefixlen, rib, rib->type, + CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED), + CHECK_FLAG(rib->status, RIB_ENTRY_REMOVED), + nexthop_active_update(rn, rib, 0), + rib->distance); + } /* Currently installed rib. */ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) @@ -1333,7 +1423,6 @@ rib_queue_init (struct zebra_t *zebra) zebra->ribq->spec.errorfunc = NULL; /* XXX: TODO: These should be runtime configurable via vty */ zebra->ribq->spec.max_retries = 3; - zebra->ribq->spec.hold = rib_process_hold_time; if (!(zebra->mq = meta_queue_new ())) zlog_err ("%s: could not initialise meta queue!", __func__); @@ -2856,23 +2945,45 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, #endif /* HAVE_IPV6 */ /* RIB update function. */ -void -rib_update (void) +static void +rib_update_table (struct table *table) { struct route_node *rn; - struct route_table *table; - - table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (table) for (rn = route_top (table); rn; rn = route_next (rn)) if (rn->info) rib_queue_add (&zebrad, rn); +} - table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); - if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rn->info) - rib_queue_add (&zebrad, rn); +void +rib_update (void) +{ + if (zebrad.update) + { + thread_cancel (zebrad.update); + zebrad.update = NULL; + } + + rib_update_table (vrf_table (AFI_IP, SAFI_UNICAST, 0)); + +#ifdef HAVE_IPV6 + rib_update_table (vrf_table (AFI_IP6, SAFI_UNICAST, 0)); +#endif +} + +static int +rib_update_thread (struct thread *self) +{ + rib_update (); + return 0; +} + +void +rib_update_background (void) +{ + if (!zebrad.update) + zebrad.update = thread_add_background (zebrad.master, rib_update_thread, + NULL, rib_process_hold_time); } |