mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 08:32:12 +00:00
Merge pull request #12861 from opensourcerouting/fix/bgp_confederation_with_astype
bgpd: Confederation fixes with remote-as external/internal
This commit is contained in:
commit
71286b6dcb
@ -1645,6 +1645,14 @@ static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
|
|||||||
*/
|
*/
|
||||||
struct aspath *aspath;
|
struct aspath *aspath;
|
||||||
|
|
||||||
|
/* Refresh peer's type. If we set e.g.: AS_EXTERNAL/AS_INTERNAL,
|
||||||
|
* then peer->sort remains BGP_PEER_EBGP/IBGP, hence we need to
|
||||||
|
* have an actual type before checking.
|
||||||
|
* This is especially a case for BGP confederation peers, to avoid
|
||||||
|
* receiving and treating AS_PATH as malformed.
|
||||||
|
*/
|
||||||
|
(void)peer_sort(peer);
|
||||||
|
|
||||||
/* Confederation sanity check. */
|
/* Confederation sanity check. */
|
||||||
if ((peer->sort == BGP_PEER_CONFED
|
if ((peer->sort == BGP_PEER_CONFED
|
||||||
&& !aspath_left_confed_check(attr->aspath))
|
&& !aspath_left_confed_check(attr->aspath))
|
||||||
@ -4295,8 +4303,22 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
|
|||||||
aspath = aspath_delete_confed_seq(aspath);
|
aspath = aspath_delete_confed_seq(aspath);
|
||||||
|
|
||||||
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
|
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
|
||||||
/* Stuff our path CONFED_ID on the front */
|
/* A confed member, so we need to do the
|
||||||
aspath = aspath_add_seq(aspath, bgp->confed_id);
|
* AS_CONFED_SEQUENCE thing if it's outside a common
|
||||||
|
* administration.
|
||||||
|
* Configured confederation peers MUST be validated
|
||||||
|
* under BGP_PEER_CONFED, but if we have configured
|
||||||
|
* remote-as as AS_EXTERNAL, we need to check again
|
||||||
|
* if the peer belongs to us.
|
||||||
|
*/
|
||||||
|
if (bgp_confederation_peers_check(bgp, peer->as)) {
|
||||||
|
aspath = aspath_dup(attr->aspath);
|
||||||
|
aspath = aspath_add_confed_seq(aspath,
|
||||||
|
peer->local_as);
|
||||||
|
} else {
|
||||||
|
/* Stuff our path CONFED_ID on the front */
|
||||||
|
aspath = aspath_add_seq(aspath, bgp->confed_id);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (peer->change_local_as) {
|
if (peer->change_local_as) {
|
||||||
/* If replace-as is specified, we only use the
|
/* If replace-as is specified, we only use the
|
||||||
|
@ -2041,9 +2041,9 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
|
|||||||
|
|
||||||
/* If the peer is not part of our confederation, and its not an
|
/* If the peer is not part of our confederation, and its not an
|
||||||
iBGP peer then spoof the source AS */
|
iBGP peer then spoof the source AS */
|
||||||
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)
|
if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION) &&
|
||||||
&& !bgp_confederation_peers_check(bgp, *as)
|
!bgp_confederation_peers_check(bgp, *as) && *as &&
|
||||||
&& bgp->as != *as)
|
bgp->as != *as)
|
||||||
local_as = bgp->confed_id;
|
local_as = bgp->confed_id;
|
||||||
else
|
else
|
||||||
local_as = bgp->as;
|
local_as = bgp->as;
|
||||||
|
12
tests/topotests/bgp_confederation_astype/r1/bgpd.conf
Normal file
12
tests/topotests/bgp_confederation_astype/r1/bgpd.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
router bgp 65001
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
bgp confederation identifier 65300
|
||||||
|
bgp confederation peers 65002 65003
|
||||||
|
neighbor fabric peer-group
|
||||||
|
neighbor fabric remote-as external
|
||||||
|
neighbor 192.168.1.2 peer-group fabric
|
||||||
|
neighbor 192.168.2.2 remote-as external
|
||||||
|
address-family ipv4 unicast
|
||||||
|
neighbor fabric activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
7
tests/topotests/bgp_confederation_astype/r1/zebra.conf
Normal file
7
tests/topotests/bgp_confederation_astype/r1/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
!
|
||||||
|
int r1-eth0
|
||||||
|
ip address 192.168.1.1/24
|
||||||
|
!
|
||||||
|
int r1-eth1
|
||||||
|
ip address 192.168.2.1/24
|
||||||
|
!
|
13
tests/topotests/bgp_confederation_astype/r2/bgpd.conf
Normal file
13
tests/topotests/bgp_confederation_astype/r2/bgpd.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
router bgp 65002
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
no bgp network import-check
|
||||||
|
bgp confederation identifier 65300
|
||||||
|
bgp confederation peers 65001
|
||||||
|
neighbor fabric peer-group
|
||||||
|
neighbor fabric remote-as external
|
||||||
|
neighbor 192.168.1.1 peer-group fabric
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 172.16.255.254/32
|
||||||
|
neighbor fabric activate
|
||||||
|
exit-address-family
|
||||||
|
!
|
4
tests/topotests/bgp_confederation_astype/r2/zebra.conf
Normal file
4
tests/topotests/bgp_confederation_astype/r2/zebra.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
!
|
||||||
|
int r2-eth0
|
||||||
|
ip address 192.168.1.2/24
|
||||||
|
!
|
10
tests/topotests/bgp_confederation_astype/r3/bgpd.conf
Normal file
10
tests/topotests/bgp_confederation_astype/r3/bgpd.conf
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
router bgp 65003
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
no bgp network import-check
|
||||||
|
bgp confederation identifier 65300
|
||||||
|
bgp confederation peers 65001
|
||||||
|
neighbor 192.168.2.1 remote-as external
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 172.16.255.254/32
|
||||||
|
exit-address-family
|
||||||
|
!
|
4
tests/topotests/bgp_confederation_astype/r3/zebra.conf
Normal file
4
tests/topotests/bgp_confederation_astype/r3/zebra.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
!
|
||||||
|
int r3-eth0
|
||||||
|
ip address 192.168.2.2/24
|
||||||
|
!
|
@ -0,0 +1,140 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
# Copyright (c) 2022 by
|
||||||
|
# Donatas Abraitis <donatas@opensourcerouting.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Test if BGP confederation works properly when using
|
||||||
|
remote-as internal/external.
|
||||||
|
|
||||||
|
Also, check if the same works with peer-groups as well.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import pytest
|
||||||
|
import functools
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.bgpd
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, "../"))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
|
||||||
|
pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")}
|
||||||
|
tgen = Topogen(topodef, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
|
||||||
|
for i, (rname, router) in enumerate(router_list.items(), 1):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||||
|
)
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
|
||||||
|
)
|
||||||
|
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
tgen = get_topogen()
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
def test_bgp_confederation_astype():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
r1 = tgen.gears["r1"]
|
||||||
|
|
||||||
|
def _bgp_converge():
|
||||||
|
output = json.loads(r1.vtysh_cmd("show bgp summary json"))
|
||||||
|
expected = {
|
||||||
|
"ipv4Unicast": {
|
||||||
|
"peerCount": 2,
|
||||||
|
"peers": {
|
||||||
|
"192.168.1.2": {
|
||||||
|
"hostname": "r2",
|
||||||
|
"remoteAs": 65002,
|
||||||
|
"localAs": 65001,
|
||||||
|
"pfxRcd": 1,
|
||||||
|
"state": "Established",
|
||||||
|
},
|
||||||
|
"192.168.2.2": {
|
||||||
|
"hostname": "r3",
|
||||||
|
"remoteAs": 65003,
|
||||||
|
"localAs": 65001,
|
||||||
|
"pfxRcd": 1,
|
||||||
|
"state": "Established",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_converge)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Can't converge"
|
||||||
|
|
||||||
|
def _bgp_check_neighbors():
|
||||||
|
output = json.loads(r1.vtysh_cmd("show bgp neighbors json"))
|
||||||
|
expected = {
|
||||||
|
"192.168.1.2": {
|
||||||
|
"nbrCommonAdmin": True,
|
||||||
|
"nbrConfedExternalLink": True,
|
||||||
|
"hostname": "r2",
|
||||||
|
},
|
||||||
|
"192.168.2.2": {
|
||||||
|
"nbrCommonAdmin": True,
|
||||||
|
"nbrConfedExternalLink": True,
|
||||||
|
"hostname": "r3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_check_neighbors)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Can't see neighbors to be in BGP confederation"
|
||||||
|
|
||||||
|
def _bgp_check_routes():
|
||||||
|
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
|
||||||
|
expected = {
|
||||||
|
"routes": {
|
||||||
|
"172.16.255.254/32": [
|
||||||
|
{
|
||||||
|
"valid": True,
|
||||||
|
"pathFrom": "external",
|
||||||
|
"path": "(65003)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid": True,
|
||||||
|
"pathFrom": "external",
|
||||||
|
"path": "(65002)",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_check_routes)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Can't see routes to be in BGP confederation"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
Loading…
Reference in New Issue
Block a user