bgpd, zebra: Use next hop tracking for connected routes too

Allow next hop tracking to work with connected routes
And cleanup obsolete code in bgp_scan and bgp_import.

Signed-off-by: Dinesh Dutt <ddutt@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Edits: Paul Jakma <paul.jakma@hpe.com> Rebase re-ordering conflicts with
       NHT route-map, potential errors.
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 066637b..a88a022 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -55,7 +55,7 @@
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_vty.h"
 #include "bgpd/bgp_mpath.h"
-#include "bgpd/bgp_nht.c"
+#include "bgpd/bgp_nht.h"
 
 /* Extern from bgp_dump.c */
 extern const char *bgp_origin_str[];
@@ -998,7 +998,7 @@
 	   || (NEXTHOP_IS_V6 &&
                IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
 	   || (peer->sort == BGP_PEER_EBGP
-	       && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0))
+               && (bgp_multiaccess_check_v4 (attr->nexthop, peer) == 0)))
     {
       /* Set IPv4 nexthop. */
       if (NEXTHOP_IS_V4)
@@ -2129,6 +2129,7 @@
   struct bgp_info *new;
   const char *reason;
   char buf[SU_ADDRSTRLEN];
+  int connected = 0;
 
   memset (&new_attr, 0, sizeof(struct attr));
   memset (&new_extra, 0, sizeof(struct attr_extra));
@@ -2209,17 +2210,6 @@
   /* IPv4 unicast next hop check.  */
   if (afi == AFI_IP && safi == SAFI_UNICAST)
     {
-      /* If the peer is EBGP and nexthop is not on connected route,
-	 discard it.  */
-      if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
-	  && ! bgp_nexthop_onlink (afi, &new_attr)
-	  && ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
-	{
-	  reason = "non-connected next-hop;";
-	  bgp_attr_flush (&new_attr);
-	  goto filtered;
-	}
-
       /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
 	 must not be my own address.  */
       if (new_attr.nexthop.s_addr == 0
@@ -2347,20 +2337,29 @@
 	}
 
       /* Nexthop reachability check. */
-      if ((afi == AFI_IP || afi == AFI_IP6)
-	  && safi == SAFI_UNICAST 
-	  && (peer->sort == BGP_PEER_IBGP
-              || peer->sort == BGP_PEER_CONFED
-	      || (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
-	      || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
+      if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
 	{
-	  if (bgp_find_or_add_nexthop (afi, ri, NULL, NULL))
+	  if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
+	      ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
+	    connected = 1;
+	  else
+	    connected = 0;
+
+	  if (bgp_find_or_add_nexthop (afi, ri, NULL, connected))
 	    bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
 	  else
-	    bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
+	    {
+	      if (BGP_DEBUG(nht, NHT))
+		{
+		  char buf1[INET6_ADDRSTRLEN];
+		  inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN);
+		  zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+		}
+	      bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
+	    }
 	}
       else
-        bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
+	bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
 
       bgp_attr_flush (&new_attr);
 
@@ -2390,17 +2389,26 @@
     memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
 
   /* Nexthop reachability check. */
-  if ((afi == AFI_IP || afi == AFI_IP6)
-      && safi == SAFI_UNICAST
-      && (peer->sort == BGP_PEER_IBGP
-          || peer->sort == BGP_PEER_CONFED
-	  || (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
-	  || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
+  if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
     {
-      if (bgp_find_or_add_nexthop (afi, new, NULL, NULL))
+      if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
+	  ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
+	connected = 1;
+      else
+	connected = 0;
+
+      if (bgp_find_or_add_nexthop (afi, new, NULL, connected))
 	bgp_info_set_flag (rn, new, BGP_INFO_VALID);
       else
-        bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
+	{
+	  if (BGP_DEBUG(nht, NHT))
+	    {
+	      char buf1[INET6_ADDRSTRLEN];
+	      inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1, INET6_ADDRSTRLEN);
+	      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+	    }
+	  bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
+	}
     }
   else
     bgp_info_set_flag (rn, new, BGP_INFO_VALID);
@@ -3532,6 +3540,23 @@
           ri->attr = attr_new;
           ri->uptime = bgp_clock ();
 
+	  /* Nexthop reachability check. */
+	  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+	    {
+	      if (bgp_find_or_add_nexthop (afi, ri, NULL, 0))
+		bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
+	      else
+		{
+		  if (BGP_DEBUG(nht, NHT))
+		    {
+		      char buf1[INET6_ADDRSTRLEN];
+		      inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
+				buf1, INET6_ADDRSTRLEN);
+		      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+		    }
+		  bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
+		}
+	    }
           /* Process change. */
           bgp_process (bgp, rn, afi, safi);
           bgp_unlock_node (rn);
@@ -3544,7 +3569,25 @@
   /* Make new BGP info. */
   new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self,
 		  attr_new, rn);
-  SET_FLAG (new->flags, BGP_INFO_VALID);
+  /* Nexthop reachability check. */
+  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+    {
+      if (bgp_find_or_add_nexthop (afi, new, NULL, 0))
+	bgp_info_set_flag (rn, new, BGP_INFO_VALID);
+      else
+	{
+	  if (BGP_DEBUG(nht, NHT))
+	    {
+	      char buf1[INET6_ADDRSTRLEN];
+	      inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
+			buf1, INET6_ADDRSTRLEN);
+	      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+	    }
+	  bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
+	}
+    }
+  else
+    bgp_info_set_flag (rn, new, BGP_INFO_VALID);
 
   /* Register new BGP information. */
   bgp_info_add (rn, new);
@@ -3562,7 +3605,7 @@
 
 static void
 bgp_static_update_main (struct bgp *bgp, struct prefix *p,
-		   struct bgp_static *bgp_static, afi_t afi, safi_t safi)
+			struct bgp_static *bgp_static, afi_t afi, safi_t safi)
 {
   struct bgp_node *rn;
   struct bgp_info *ri;
@@ -3646,6 +3689,23 @@
 	  ri->attr = attr_new;
 	  ri->uptime = bgp_clock ();
 
+	  /* Nexthop reachability check. */
+	  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+	    {
+	      if (bgp_find_or_add_nexthop (afi, ri, NULL, 0))
+		bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
+	      else
+		{
+		  if (BGP_DEBUG(nht, NHT))
+		    {
+		      char buf1[INET6_ADDRSTRLEN];
+		      inet_ntop(AF_INET, (const void *)&attr_new->nexthop,
+				buf1, INET6_ADDRSTRLEN);
+		      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+		    }
+		  bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
+		}
+	    }
 	  /* Process change. */
 	  bgp_aggregate_increment (bgp, p, ri, afi, safi);
 	  bgp_process (bgp, rn, afi, safi);
@@ -3659,7 +3719,25 @@
   /* Make new BGP info. */
   new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, bgp->peer_self, attr_new,
 		  rn);
-  SET_FLAG (new->flags, BGP_INFO_VALID);
+  /* Nexthop reachability check. */
+  if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+    {
+      if (bgp_find_or_add_nexthop (afi, new, NULL, 0))
+	bgp_info_set_flag (rn, new, BGP_INFO_VALID);
+      else
+	{
+	  if (BGP_DEBUG(nht, NHT))
+	    {
+	      char buf1[INET6_ADDRSTRLEN];
+	      inet_ntop(AF_INET, (const void *)&attr_new->nexthop, buf1,
+			INET6_ADDRSTRLEN);
+	      zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1);
+	    }
+	  bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
+	}
+    }
+  else
+    bgp_info_set_flag (rn, new, BGP_INFO_VALID);
 
   /* Aggregate address increment. */
   bgp_aggregate_increment (bgp, p, new, afi, safi);
@@ -3720,6 +3798,7 @@
   if (ri)
     {
       bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+      bgp_unlink_nexthop(ri);
       bgp_info_delete (rn, ri);
       bgp_process (bgp, rn, afi, safi);
     }
@@ -3978,17 +4057,12 @@
       rn->info = bgp_static;
     }
 
-  /* If BGP scan is not enabled, we should install this route here.  */
-  if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
-    {
-      bgp_static->valid = 1;
+  bgp_static->valid = 1;
+  if (need_update)
+    bgp_static_withdraw (bgp, &p, afi, safi);
 
-      if (need_update)
-	bgp_static_withdraw (bgp, &p, afi, safi);
-
-      if (! bgp_static->backdoor)
-	bgp_static_update (bgp, &p, bgp_static, afi, safi);
-    }
+  if (! bgp_static->backdoor)
+    bgp_static_update (bgp, &p, bgp_static, afi, safi);
 
   return CMD_SUCCESS;
 }