[PATCH,RFC 3/3] BGP: Don't unconditionally bounce connection for remote AS changes.

Lennert Buytenhek buytenh at wantstofly.org
Thu Mar 9 15:30:55 CET 2017


If we are using the secondary remote AS mechanism, we don't necessarily
need to restart an already established BGP connection if the remote AS
for a BGP session changes, as long as the AS number that the peer is
currently connected with is still in the list of AS numbers that we
accept from the peer.

This commit will avoid reconfiguring a BGP protocol if there is a
corresponding connection in OpenConfirm or Established state and the
only change to the protocol configuration was related to remote AS
numbers and the AS number that the peer is currently connected with is
still a permitted remote AS number.  This allows adding a secondary
remote AS number to a BGP protocol without bouncing an already
established BGP session for this protocol.
---
 proto/bgp/bgp.c | 36 +++++++++++++++++++++++++++++-------
 proto/bgp/bgp.h |  4 +++-
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index bceae4a..b969b81 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1369,17 +1369,39 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
   struct bgp_config *new = (struct bgp_config *) C;
   struct bgp_proto *p = (struct bgp_proto *) P;
   struct bgp_config *old = p->cf;
+  int same = 1;
 
   if (proto_get_router_id(C) != p->local_id)
     return 0;
 
-  int same = !memcmp(((byte *) old) + sizeof(struct proto_config),
-		     ((byte *) new) + sizeof(struct proto_config),
-		     // password item is last and must be checked separately
-		     OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
-    && ((!old->password && !new->password)
-	|| (old->password && new->password && !strcmp(old->password, new->password)))
-    && (get_igp_table(old) == get_igp_table(new));
+  struct bgp_conn *c = p->conn;
+  if (c != NULL &&
+      (c->state == BS_OPENCONFIRM || c->state == BS_ESTABLISHED) &&
+      (p->remote_as == new->remote_as || p->remote_as == new->remote_as2))
+    {
+      old->remote_as = new->remote_as;
+      old->remote_as2 = new->remote_as2;
+    }
+  else if (old->remote_as != new->remote_as || old->remote_as2 != new->remote_as2)
+    {
+      same = 0;
+    }
+
+  int start = OFFSETOF(struct bgp_config, local_as);
+  int end = OFFSETOF(struct bgp_config, password);
+  if (memcmp(((byte *) old) + start, ((byte *) new) + start, end - start))
+    same = 0;
+
+  if (old->password && new->password)
+    {
+      if (strcmp(old->password, new->password))
+	same = 0;
+    }
+  else if (old->password || new->password)
+    same = 0;
+
+  if (get_igp_table(old) != get_igp_table(new))
+    same = 0;
 
   if (same && (p->start_state > BSS_PREPARE))
     bgp_update_bfd(p, new->bfd);
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 0b69333..29b5051 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -20,8 +20,10 @@ struct eattr;
 struct bgp_config {
   struct proto_config c;
 
+  u32 remote_as, remote_as2;
+
   /* start of config vars compared using memcmp() in bgp_reconfigure() */
-  u32 local_as, remote_as, remote_as2;
+  u32 local_as;
   ip_addr remote_ip;
   ip_addr source_addr;			/* Source address to use */
   struct iface *iface;			/* Interface for link-local addresses */
-- 
2.9.3


More information about the Bird-users mailing list