diff --git a/zebra/connected.c b/zebra/connected.c index 3b9ebe14a4..8c4ba163bd 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -393,10 +393,10 @@ void connected_down(struct interface *ifp, struct connected *ifc) * head. */ rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, - 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false); + 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false, true); rib_delete(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false); + 0, 0, &p, NULL, &nh, 0, zvrf->table_id, 0, 0, false, true); /* Schedule LSP forwarding entries for processing, if appropriate. */ if (zvrf->vrf->vrf_id == VRF_DEFAULT) { diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 4c29b999f0..02963651a0 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1136,7 +1136,7 @@ void rtm_read(struct rt_msghdr *rtm) if (rtm->rtm_type == RTM_CHANGE) rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, NULL, 0, RT_TABLE_MAIN, 0, - 0, true); + 0, true, false); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, @@ -1145,7 +1145,7 @@ void rtm_read(struct rt_msghdr *rtm) else rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, - 0, true); + 0, true, false); } /* Interface function for the kernel routing table updates. Support diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 0b97562424..c0f89e6afe 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -727,7 +727,7 @@ int zebra_del_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE, re->table, re->flags, &p, NULL, re->nhe->nhg.nexthop, re->nhe_id, zvrf->table_id, re->metric, re->distance, - false); + false, false); return 0; } diff --git a/zebra/rib.h b/zebra/rib.h index b9f4e56905..be680a112f 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -379,7 +379,7 @@ extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, unsigned short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, uint32_t nhe_id, uint32_t table_id, uint32_t metric, - uint8_t distance, bool fromkernel); + uint8_t distance, bool fromkernel, bool connected_down); extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, union g_addr *addr, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 4a6839d3b1..50b1a62d86 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -837,7 +837,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (nhe_id) { rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, &src_p, NULL, nhe_id, table, metric, - distance, true); + distance, true, false); } else { if (!tb[RTA_MULTIPATH]) { struct nexthop nh; @@ -847,13 +847,13 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, gate, afi, vrf_id); rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, &src_p, &nh, 0, table, - metric, distance, true); + metric, distance, true, false); } else { /* XXX: need to compare the entire list of * nexthops here for NLM_F_APPEND stupidity */ rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, &src_p, NULL, 0, table, - metric, distance, true); + metric, distance, true, false); } } } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index ec61be0b39..4b31b46bce 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1890,7 +1890,7 @@ static void zread_route_del(ZAPI_HANDLER_ARGS) rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance, api.flags, &api.prefix, src_p, NULL, 0, table_id, api.metric, - api.distance, false); + api.distance, false, false); /* Stats */ switch (api.prefix.family) { diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5fcb513e3c..ff30de18a3 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3041,7 +3041,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, unsigned short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, uint32_t nhe_id, uint32_t table_id, uint32_t metric, - uint8_t distance, bool fromkernel) + uint8_t distance, bool fromkernel, bool connected_down) { struct route_table *table; struct route_node *rn; @@ -3163,7 +3163,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, rn, fib, zebra_route_string(fib->type)); } - if (allow_delete) { + if (allow_delete + || CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) { UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED); /* Unset flags. */ for (rtnh = fib->nhe->nhg.nexthop; rtnh; @@ -3248,6 +3249,19 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, rib_delnode(rn, same); } + /* + * This is to force an immediate re-eval of this particular + * node via nexthop tracking. Why? Because there are scenarios + * where the interface is flapping and the normal queuing methodology + * will cause down/up events to very very rarely be combined into + * a non-event from nexthop tracking perspective. Leading + * to some fun timing situations with upper level routing protocol + * trying to and failing to install routes during this blip. Especially + * when zebra is under load. + */ + if (connected_down) + zebra_rib_evaluate_rn_nexthops(rn, + zebra_router_get_next_sequence()); route_unlock_node(rn); return; }