From: vivek Date: Wed, 9 Dec 2015 00:55:43 +0000 (-0800) Subject: Zebra: Schedule RIB processing based on trigger event X-Git-Tag: frr-2.0-rc1~1169^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=1c8481370f49d491d5afe84af9bf8613b257afb2;p=mirror%2Ffrr.git 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. --- diff --git a/zebra/connected.c b/zebra/connected.c index f67b44ba80..b2fababc1b 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -215,9 +215,9 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); - - rib_update (ifp->vrf_id); + zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } /* Add connected IPv4 route to the interface. */ @@ -334,9 +334,10 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) SAFI_MULTICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update_static", __func__); + zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update_static (ifp->vrf_id); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } /* Delete connected IPv4 route to the interface. */ @@ -359,9 +360,10 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, connected_withdraw (ifc); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update_static", __func__); + zlog_debug ("%u: IF %s IPv4 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update_static(ifp->vrf_id); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } #ifdef HAVE_IPV6 @@ -388,9 +390,10 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); + zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update (ifp->vrf_id); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } /* Add connected IPv6 route to the interface. */ @@ -477,9 +480,10 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc) ifp->vrf_id, 0, SAFI_UNICAST); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update_static", __func__); + zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update_static (ifp->vrf_id); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } void @@ -501,9 +505,10 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, connected_withdraw (ifc); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update_static", __func__); + zlog_debug ("%u: IF %s IPv6 address del, scheduling RIB processing", + ifp->vrf_id, ifp->name); - rib_update_static(ifp->vrf_id); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } #endif /* HAVE_IPV6 */ diff --git a/zebra/interface.c b/zebra/interface.c index 2768e69a6d..cb4645c2f1 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -639,11 +639,9 @@ if_up (struct interface *ifp) } if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update on interface %s up", __func__, - ifp->name); - - /* Examine all static routes. */ - rib_update (ifp->vrf_id); + zlog_debug ("%u: IF %s up, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); } /* Interface goes down. We have to manage different behavior of based @@ -675,12 +673,10 @@ if_down (struct interface *ifp) } } - /* Examine all static routes which direct to the interface. */ if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update_static on interface %s down", __func__, - ifp->name); - - rib_update_static (ifp->vrf_id); + zlog_debug ("%u: IF %s down, scheduling RIB processing", + ifp->vrf_id, ifp->name); + rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE); if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp); diff --git a/zebra/rib.h b/zebra/rib.h index aefe437be2..4d5ccac606 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -371,6 +371,14 @@ typedef struct rib_tables_iter_t_ rib_tables_iter_state_t state; } rib_tables_iter_t; +/* Events/reasons triggering a RIB update. */ +typedef enum +{ + RIB_UPDATE_IF_CHANGE, + RIB_UPDATE_RMAP_CHANGE, + RIB_UPDATE_OTHER +} rib_update_event_t; + extern struct nexthop *rib_nexthop_ifindex_add (struct rib *, unsigned int); extern struct nexthop *rib_nexthop_ifname_add (struct rib *, char *); extern struct nexthop *rib_nexthop_blackhole_add (struct rib *); @@ -433,8 +441,7 @@ extern struct rib *rib_match_ipv4 (struct in_addr, vrf_id_t); extern struct rib *rib_lookup_ipv4 (struct prefix_ipv4 *, vrf_id_t); -extern void rib_update (vrf_id_t); -extern void rib_update_static (vrf_id_t); +extern void rib_update (vrf_id_t, rib_update_event_t); extern void rib_weed_tables (void); extern void rib_sweep_route (void); extern void rib_close_table (struct route_table *); 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) diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 5d16dbba4f..fbd9db1879 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -784,9 +784,10 @@ DEFUN (ip_protocol, proto_rm[AFI_IP][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); + zlog_debug ("%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, argv[0]); - rib_update(VRF_DEFAULT); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); return CMD_SUCCESS; } @@ -821,9 +822,9 @@ DEFUN (no_ip_protocol, proto_rm[AFI_IP][i] = NULL; if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); - - rib_update(VRF_DEFAULT); + zlog_debug ("%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, argv[0]); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); } return CMD_SUCCESS; } @@ -896,9 +897,10 @@ DEFUN (ipv6_protocol, proto_rm[AFI_IP6][i] = XSTRDUP (MTYPE_ROUTE_MAP_NAME, argv[1]); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); + zlog_debug ("%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", + VRF_DEFAULT, argv[0]); - rib_update(VRF_DEFAULT); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); return CMD_SUCCESS; } @@ -933,9 +935,10 @@ DEFUN (no_ipv6_protocol, proto_rm[AFI_IP6][i] = NULL; if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); + zlog_debug ("%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", + VRF_DEFAULT, argv[0]); - rib_update(VRF_DEFAULT); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); } return CMD_SUCCESS; } @@ -1611,9 +1614,10 @@ zebra_route_map_update_timer (struct thread *thread) zlog_debug("Event driven route-map update triggered"); if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug ("%s: calling rib_update", __func__); + zlog_debug ("%u: Routemap update-timer fired, scheduling RIB processing", + VRF_DEFAULT); - rib_update(VRF_DEFAULT); + rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);