]> git.puffer.fish Git - matthieu/frr.git/commitdiff
BGP: Handle interface or local address failure
authorvivek <vivek@cumulusnetworks.com>
Sat, 29 Aug 2015 18:40:32 +0000 (11:40 -0700)
committervivek <vivek@cumulusnetworks.com>
Sat, 29 Aug 2015 18:40:32 +0000 (11:40 -0700)
Ticket: CM-6883
Reviewed By: CCR-3272
Testing Done: Tested on 2.5.3-SE-1

This commit is a port of the patch bgpd-handle-peer-local-address-failure.patch
from 2.5-br.

When a peering is being established, the IPv4 and IPv6 addresses of the
local end of the connection, as applicable, are obtained and stored in
the peer's 'nexthop' structure to facilitate filling of the NEXT_HOP
field in Update messages among other things. The process of obtaining the
local address involves examination of the list of interfaces to identify
a match corresponding to the socket address of the connection.

There are timing conditions, especially when BGPD starts with a config,
where the interface may not have reached BGP from Zebra at the time a
peering reaches the state to determine the local addresses. The code does
not handle this well and the result could be Updates generated with bad
(Martian) NEXT_HOP values. Resolve the issue by bringing down the connection
in this case as not identifying the local addresses is really an error.

bgpd/bgp_network.c
bgpd/bgp_packet.c
bgpd/bgp_zebra.c

index f1ce97eff9200e8445d5a0539a527c629ec9697a..a3ad3cc9dc09314f378abe6f904684e1643ea527 100644 (file)
@@ -541,7 +541,13 @@ bgp_getsockname (struct peer *peer)
   peer->su_remote = sockunion_getpeername (peer->fd);
   if (!peer->su_remote) return -1;
 
-  bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
+  if (bgp_nexthop_set (peer->su_local, peer->su_remote,
+                       &peer->nexthop, peer))
+    {
+      zlog_err ("%s: nexthop_set failed, resetting connection - intf %p",
+                peer->host, peer->nexthop.ifp);
+      return -1;
+    }
 
   return 0;
 }
index ddc03716e35938b91d4acb2c781d5063c17cc5f5..6bc0ef5c063b687371a5b858b72775453ffd55a7 100644 (file)
@@ -1127,6 +1127,31 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
       return (ret);
     }
 
+  /* Verify valid local address present based on negotiated address-families. */
+  if (peer->afc_nego[AFI_IP][SAFI_UNICAST] ||
+      peer->afc_nego[AFI_IP][SAFI_MULTICAST] ||
+      peer->afc_nego[AFI_IP][SAFI_MPLS_VPN])
+    {
+      if (!peer->nexthop.v4.s_addr)
+        {
+          zlog_err ("%s: No local IPv4 addr resetting connection, fd %d",
+                    peer->host, peer->fd);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+          return -1;
+        }
+    }
+  if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] ||
+      peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
+    {
+      if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global))
+        {
+          zlog_err ("%s: No local IPv6 addr resetting connection, fd %d",
+                    peer->host, peer->fd);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+          return -1;
+        }
+    }
+
   if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0)
     {
       zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__,
index f96fbfa6d9021329546edc18763c16f62b3be970..1a27b195cbd87c92e9d274537d9a9c0a18d16ad1 100644 (file)
@@ -843,7 +843,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
 
   nexthop->ifp = ifp;
 
-  /* IPv4 connection. */
+  /* IPv4 connection, fetch and store IPv6 local address(es) if any. */
   if (local->sa.sa_family == AF_INET)
     {
 #ifdef HAVE_IPV6
@@ -859,7 +859,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
     }
 
 #ifdef HAVE_IPV6
-  /* IPv6 connection. */
+  /* IPv6 connection, fetch and store IPv4 local address if any. */
   if (local->sa.sa_family == AF_INET6)
     {
       struct interface *direct = NULL;
@@ -921,7 +921,9 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
     }
 #endif /* KAME */
 #endif /* HAVE_IPV6 */
-  return ret;
+
+  /* If we have identified the local interface, there is no error for now. */
+  return 0;
 }
 
 static struct in6_addr *