--- /dev/null
+From 64e0ac29ddc43bb5b1a2999a8ebedbdff115e3ca Mon Sep 17 00:00:00 2001
+From: Paul Jakma <paul.jakma@hpe.com>
+Date: Wed, 18 Nov 2015 16:00:54 +0000
+Subject: [PATCH] bgpd: Implicit updates in BGP may require a withdrawal from
+ zebra RIB
+
+* J Yu <jackiesyu@hotmail.com> noted a problem with bgpd of routes not
+ having their nexthop updated correctly.
+
+ Martin Winter <mwinter@opensourcerouting.org> pinned this down to the
+ case where a BGP route is updated from one with a valid nexthop to an
+ invalid next-hop, using a test tool. Once the problem occurs, the incorrect
+ route may remain, even after further UPDATEs, so long as the nexthop in the
+ zebra RIB does not match the BGP route's nexthop.
+
+ Jacqueline Yu then pinned the issue down further to being due to bgpd
+ sending the DELETE for the route to zebra with the new nexthop after a
+ BGP UPDATE updates an existing route, but then is found to be invalid,
+ and zebra not finding the route as it requires a match on all attributes.
+
+* bgp_zebra.c: (bgp_zebra_withdraw) When deleting a prefix, we want it gone.
+ Do not send additional matching attributes like the nexthop, which can
+ only cause incorrect non-matches.
+Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
+---
+ bgpd/bgp_zebra.c | 46 +++++-----------------------------------------
+ 1 file changed, 5 insertions(+), 41 deletions(-)
+
+diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
+index e534bee..186657b 100644
+--- a/bgpd/bgp_zebra.c
++++ b/bgpd/bgp_zebra.c
+@@ -863,18 +863,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+ if (p->family == AF_INET)
+ {
+ struct zapi_ipv4 api;
+- struct in_addr *nexthop;
+
+ api.vrf_id = VRF_DEFAULT;
+ api.flags = flags;
+- nexthop = &info->attr->nexthop;
+
+ api.type = ZEBRA_ROUTE_BGP;
+ api.message = 0;
+ api.safi = safi;
+- SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+- api.nexthop_num = 1;
+- api.nexthop = &nexthop;
++ api.nexthop_num = 0;
+ api.ifindex_num = 0;
+ SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+ api.metric = info->attr->med;
+@@ -882,10 +878,9 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET_ADDRSTRLEN];
+- zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u",
++ zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u",
+ inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+- inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
+@@ -897,54 +892,23 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
+ if (p->family == AF_INET6)
+ {
+ struct zapi_ipv6 api;
+- unsigned int ifindex;
+- struct in6_addr *nexthop;
+-
+- assert (info->attr->extra);
+
+- ifindex = 0;
+- nexthop = NULL;
+-
+- /* Only global address nexthop exists. */
+- if (info->attr->extra->mp_nexthop_len == 16)
+- nexthop = &info->attr->extra->mp_nexthop_global;
+-
+- /* If both global and link-local address present. */
+- if (info->attr->extra->mp_nexthop_len == 32)
+- {
+- nexthop = &info->attr->extra->mp_nexthop_local;
+- if (info->peer->nexthop.ifp)
+- ifindex = info->peer->nexthop.ifp->ifindex;
+- }
+-
+- if (nexthop == NULL)
+- return;
+-
+- if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
+- if (info->peer->ifname)
+- ifindex = ifname2ifindex (info->peer->ifname);
+-
+ api.vrf_id = VRF_DEFAULT;
+ api.flags = flags;
+ api.type = ZEBRA_ROUTE_BGP;
+ api.message = 0;
+ api.safi = safi;
+- SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+- api.nexthop_num = 1;
+- api.nexthop = &nexthop;
+- SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+- api.ifindex_num = 1;
+- api.ifindex = &ifindex;
++ api.nexthop_num = 0;
++ api.ifindex_num = 0;
+ SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+ api.metric = info->attr->med;
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ {
+ char buf[2][INET6_ADDRSTRLEN];
+- zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u",
++ zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u",
+ inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
+ p->prefixlen,
+- inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])),
+ api.metric);
+ }
+
+--
+2.7.0
+