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 bb2c084c47..285994c015 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -370,6 +370,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_blackhole_add (struct rib *); extern struct nexthop *rib_nexthop_ipv4_add (struct rib *, struct in_addr *, @@ -428,8 +436,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 e41d5d4fad..1859661c13 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3471,56 +3471,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; - 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) - { + /* 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; + + 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 4833fa2182..613b817481 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; } @@ -1605,9 +1608,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);