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