From 1c8481370f49d491d5afe84af9bf8613b257afb2 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 8 Dec 2015 16:55:43 -0800 Subject: Zebra: Schedule RIB processing based on trigger event Currently, when RIB processing is initiated (i.e., by calling rib_update()), all routes are queued for processing. This is not desirable in all situations because, sometimes the protocol may have an alternate path. In addition, with NHT tracking nexthops, there are situations when NHT should be kicked off first and that can trigger subsequent RIB processing. This patch addresses this by introducing the notion of a trigger event. This is only for the situation when the entire RIB is walked. The current triggers - based on when rib_update() is invoked - are "interface change" and "route- map change". In the former case, only the relevant routes are walked and scheduled, in the latter case, currently all routes are scheduled for processing. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: CM-7662 Reviewed By: CCR-3905 Note: The initial defect in this area was CM-7420. This was addressed in 2.5.4 with an interim change that only walked static routes upon interface down. The change was considered a bit risky to do for interface up etc. Also, this did not address scenarios like CM-7662. The current fix addresses CM-7662. --- zebra/zebra_rib.c | 89 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 31 deletions(-) (limited to 'zebra/zebra_rib.c') diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 87425cb4b9..d5b1f82343 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3545,56 +3545,83 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, return 1; } -/* RIB update function. */ -void -rib_update_static (vrf_id_t vrf_id) +/* Schedule routes of a particular table (address-family) based on event. */ +static void +rib_update_table (struct route_table *table, rib_update_event_t event) { struct route_node *rn; - struct route_table *table; struct rib *rib, *next; - 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_SAFE (rn, rib, next) - if (rib->type == ZEBRA_ROUTE_STATIC) - { - rib_queue_add (&zebrad, rn); - break; - } + /* Walk all routes and queue for processing, if appropriate for + * the trigger event. + */ + for (rn = route_top (table); rn; rn = route_next (rn)) + { + switch (event) + { + case RIB_UPDATE_IF_CHANGE: + /* Examine all routes that won't get processed by the protocol or + * triggered by nexthop evaluation (NHT). This would be system, + * kernel and certain static routes. Note that NHT will get + * triggered upon an interface event as connected routes always + * get queued for processing. + */ + RNODE_FOREACH_RIB_SAFE (rn, rib, next) + { + if (rib->type == ZEBRA_ROUTE_OSPF || + rib->type == ZEBRA_ROUTE_OSPF6 || + rib->type == ZEBRA_ROUTE_BGP) + continue; /* protocol will handle. */ + else if (rib->type == ZEBRA_ROUTE_STATIC) + { + struct nexthop *nh; + for (nh = rib->nexthop; nh; nh = nh->next) + if (!(nh->type == NEXTHOP_TYPE_IPV4 || + nh->type == NEXTHOP_TYPE_IPV6)) + break; + + /* If we only have nexthops to a gateway, NHT will + * take care. + */ + if (nh) + rib_queue_add (&zebrad, rn); + } + else + rib_queue_add (&zebrad, rn); + } + break; - 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_SAFE (rn, rib, next) - if (rib->type == ZEBRA_ROUTE_STATIC) - { + case RIB_UPDATE_RMAP_CHANGE: + case RIB_UPDATE_OTHER: + /* Right now, examine all routes. Can restrict to a protocol in + * some cases (TODO). + */ + if (rnode_to_ribs (rn)) rib_queue_add (&zebrad, rn); - break; - } + break; + + default: + break; + } + } } /* RIB update function. */ void -rib_update (vrf_id_t vrf_id) +rib_update (vrf_id_t vrf_id, rib_update_event_t event) { - struct route_node *rn; struct route_table *table; - + + /* Process routes of interested address-families. */ table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rnode_to_ribs (rn)) - rib_queue_add (&zebrad, rn); + rib_update_table (table, event); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); if (table) - for (rn = route_top (table); rn; rn = route_next (rn)) - if (rnode_to_ribs (rn)) - rib_queue_add (&zebrad, rn); + rib_update_table (table, event); } - /* Remove all routes which comes from non main table. */ static void rib_weed_table (struct route_table *table) -- cgit v1.2.3