diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 0d8644153371..78f86777f2c8 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1995,6 +1995,7 @@ static int bgp_open_receive(struct peer_connection *connection, SET_FLAG(peer->as_type, AS_EXTERNAL); UNSET_FLAG(peer->as_type, AS_INTERNAL); } + (void)peer_sort(peer); } else if (peer->as_type == AS_INTERNAL) { if (remote_as != peer->bgp->as) { if (bgp_debug_neighbor_events(peer)) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d2af262f5051..92356c3fd97b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1108,8 +1108,16 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer) assert(peer->group); peer1 = listnode_head(peer->group->peer); - if (peer1) + if (peer1) { + /* AS_AUTO without INTERNAL/EXTERNAL bits means + * the type is not yet resolved (no session up). + * Treat as unestablished so it doesn't block + * other members from being configured. + */ + if (peer1->as_type == AS_AUTO) + return BGP_PEER_INTERNAL; return peer1->sort; + } } return BGP_PEER_INTERNAL; } diff --git a/tests/topotests/bgp_remote_as_auto/r1/frr.conf b/tests/topotests/bgp_remote_as_auto/r1/frr.conf index 2f1bcd275f1a..b1c9038467e6 100644 --- a/tests/topotests/bgp_remote_as_auto/r1/frr.conf +++ b/tests/topotests/bgp_remote_as_auto/r1/frr.conf @@ -17,6 +17,9 @@ router bgp 65001 neighbor r1-eth1 interface remote-as auto neighbor r1-eth1 timers 1 3 neighbor r1-eth1 timers connect 1 + neighbor 192.168.1.5 remote-as internal + neighbor 192.168.1.5 timers 1 3 + neighbor 192.168.1.5 timers connect 1 address-family ipv4 unicast network 10.0.0.1/32 exit-address-family diff --git a/tests/topotests/bgp_remote_as_auto/r2/frr.conf b/tests/topotests/bgp_remote_as_auto/r2/frr.conf index f8d19a0bfd56..9d8dce1b6467 100644 --- a/tests/topotests/bgp_remote_as_auto/r2/frr.conf +++ b/tests/topotests/bgp_remote_as_auto/r2/frr.conf @@ -7,4 +7,7 @@ router bgp 65001 neighbor 192.168.1.1 remote-as auto neighbor 192.168.1.1 timers 1 3 neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.1.5 remote-as internal + neighbor 192.168.1.5 timers 1 3 + neighbor 192.168.1.5 timers connect 1 ! diff --git a/tests/topotests/bgp_remote_as_auto/r3/frr.conf b/tests/topotests/bgp_remote_as_auto/r3/frr.conf index fc6862764f4d..55904785c206 100644 --- a/tests/topotests/bgp_remote_as_auto/r3/frr.conf +++ b/tests/topotests/bgp_remote_as_auto/r3/frr.conf @@ -7,4 +7,7 @@ router bgp 65003 neighbor 192.168.1.1 remote-as auto neighbor 192.168.1.1 timers 1 3 neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.1.5 remote-as external + neighbor 192.168.1.5 timers 1 3 + neighbor 192.168.1.5 timers connect 1 ! diff --git a/tests/topotests/bgp_remote_as_auto/r5/frr.conf b/tests/topotests/bgp_remote_as_auto/r5/frr.conf new file mode 100644 index 000000000000..05b515b71698 --- /dev/null +++ b/tests/topotests/bgp_remote_as_auto/r5/frr.conf @@ -0,0 +1,20 @@ +! +int r5-eth0 + ip address 192.168.1.5/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor PG peer-group + neighbor 192.168.1.1 peer-group PG + neighbor 192.168.1.1 remote-as auto + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.1.2 peer-group PG + neighbor 192.168.1.2 remote-as internal + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.1.3 peer-group PG + neighbor 192.168.1.3 remote-as external + neighbor 192.168.1.3 timers 1 3 + neighbor 192.168.1.3 timers connect 1 +! diff --git a/tests/topotests/bgp_remote_as_auto/test_bgp_remote_as_auto.py b/tests/topotests/bgp_remote_as_auto/test_bgp_remote_as_auto.py index 1db6d98a42e7..35047c648ba5 100644 --- a/tests/topotests/bgp_remote_as_auto/test_bgp_remote_as_auto.py +++ b/tests/topotests/bgp_remote_as_auto/test_bgp_remote_as_auto.py @@ -23,7 +23,7 @@ def setup_module(mod): - topodef = {"s1": ("r1", "r2", "r3"), "s2": ("r1", "r4")} + topodef = {"s1": ("r1", "r2", "r3", "r5"), "s2": ("r1", "r4")} tgen = Topogen(topodef, mod.__name__) tgen.start_topology() @@ -50,6 +50,7 @@ def test_bgp_remote_as_auto(): r2 = tgen.gears["r2"] r3 = tgen.gears["r3"] r4 = tgen.gears["r4"] + r5 = tgen.gears["r5"] def _bgp_converge(): output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast summary json")) @@ -155,6 +156,40 @@ def _bgp_converge_external_unnumbered(): _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assert result is None, "Can't see automatic unnumbered eBGP peering" + def _bgp_converge_peer_group(): + output = json.loads(r5.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65001, + "state": "Established", + }, + "192.168.1.2": { + "hostname": "r2", + "remoteAs": 65001, + "localAs": 65001, + "state": "Established", + }, + "192.168.1.3": { + "hostname": "r3", + "remoteAs": 65003, + "localAs": 65001, + "state": "Established", + }, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_converge_peer_group, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert ( + result is None + ), "Peer-group with mixed remote-as auto/internal members failed to establish" + if __name__ == "__main__": args = ["-s"] + sys.argv[1:]