Merge pull request #11484 from opensourcerouting/fix/allow_using_bgp_roles_for_peer_groups

bgpd: Make sure peer-groups/unnumbered work too with BGP role
This commit is contained in:
Donald Sharp 2022-06-28 14:31:48 -04:00 committed by GitHub
commit a747bf5f45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 158 additions and 41 deletions

View File

@ -1152,7 +1152,7 @@ static bool bgp_role_violation(struct peer *peer)
return true; return true;
} }
if (remote_role == ROLE_UNDEFINED && if (remote_role == ROLE_UNDEFINED &&
CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_MODE)) { CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)) {
const char *err_msg = const char *err_msg =
"Strict mode. Please set the role on your side."; "Strict mode. Please set the role on your side.";
bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR, bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,

View File

@ -6449,7 +6449,7 @@ static int peer_role_set_vty(struct vty *vty, const char *ip_str,
{ {
struct peer *peer; struct peer *peer;
peer = peer_lookup_vty(vty, ip_str); peer = peer_and_group_lookup_vty(vty, ip_str);
if (!peer) if (!peer)
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
uint8_t role = get_role_by_name(role_str); uint8_t role = get_role_by_name(role_str);
@ -6463,7 +6463,7 @@ static int peer_role_unset_vty(struct vty *vty, const char *ip_str)
{ {
struct peer *peer; struct peer *peer;
peer = peer_lookup_vty(vty, ip_str); peer = peer_and_group_lookup_vty(vty, ip_str);
if (!peer) if (!peer)
return CMD_WARNING_CONFIG_FAILED; return CMD_WARNING_CONFIG_FAILED;
return bgp_vty_return(vty, peer_role_unset(peer)); return bgp_vty_return(vty, peer_role_unset(peer));
@ -16785,13 +16785,13 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
} }
/* role */ /* role */
if (peer->local_role != ROLE_UNDEFINED) { if (peergroup_flag_check(peer, PEER_FLAG_ROLE) &&
peer->local_role != ROLE_UNDEFINED)
vty_out(vty, " neighbor %s local-role %s%s\n", addr, vty_out(vty, " neighbor %s local-role %s%s\n", addr,
bgp_get_name_by_role(peer->local_role), bgp_get_name_by_role(peer->local_role),
CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_MODE) CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)
? " strict-mode" ? " strict-mode"
: ""); : "");
}
/* ttl-security hops */ /* ttl-security hops */
if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED) { if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED) {

View File

@ -2731,6 +2731,9 @@ static void peer_group2peer_config_copy(struct peer_group *group,
} }
} }
/* role */
PEER_ATTR_INHERIT(peer, group, local_role);
/* Update GR flags for the peer. */ /* Update GR flags for the peer. */
bgp_peer_gr_flags_update(peer); bgp_peer_gr_flags_update(peer);
@ -4256,7 +4259,8 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none}, {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none}, {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
{PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset}, {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
{PEER_FLAG_STRICT_MODE, 0, peer_change_reset}, {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
{PEER_FLAG_ROLE, 0, peer_change_reset},
{0, 0, 0}}; {0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = { static const struct peer_flag_action peer_af_flag_action_list[] = {
@ -4929,18 +4933,31 @@ int peer_ebgp_multihop_unset(struct peer *peer)
/* Set Open Policy Role and check its correctness */ /* Set Open Policy Role and check its correctness */
int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode) int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
{ {
struct peer *member;
struct listnode *node, *nnode;
peer_flag_set(peer, PEER_FLAG_ROLE);
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (peer->sort != BGP_PEER_EBGP) if (peer->sort != BGP_PEER_EBGP)
return BGP_ERR_INVALID_INTERNAL_ROLE; return BGP_ERR_INVALID_INTERNAL_ROLE;
if (peer->local_role == role) { if (peer->local_role == role) {
if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_MODE) && if (CHECK_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE) &&
!strict_mode) !strict_mode)
/* TODO: Is session restart needed if it was down? */ /* TODO: Is session restart needed if it was
UNSET_FLAG(peer->flags, PEER_FLAG_STRICT_MODE); * down?
if (!CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_MODE) && */
UNSET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
if (!CHECK_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE) &&
strict_mode) { strict_mode) {
SET_FLAG(peer->flags, PEER_FLAG_STRICT_MODE); SET_FLAG(peer->flags,
/* Restart session to throw Role Mismatch Notification PEER_FLAG_ROLE_STRICT_MODE);
/* Restart session to throw Role Mismatch
* Notification
*/ */
if (peer->remote_role == ROLE_UNDEFINED) if (peer->remote_role == ROLE_UNDEFINED)
bgp_session_reset(peer); bgp_session_reset(peer);
@ -4948,17 +4965,77 @@ int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
} else { } else {
peer->local_role = role; peer->local_role = role;
if (strict_mode) if (strict_mode)
SET_FLAG(peer->flags, PEER_FLAG_STRICT_MODE); SET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
else else
UNSET_FLAG(peer->flags, PEER_FLAG_STRICT_MODE); UNSET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
bgp_session_reset(peer); bgp_session_reset(peer);
} }
return 0;
return CMD_SUCCESS;
}
peer->local_role = role;
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
if (member->sort != BGP_PEER_EBGP)
return BGP_ERR_INVALID_INTERNAL_ROLE;
if (member->local_role == role) {
if (CHECK_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE) &&
!strict_mode)
/* TODO: Is session restart needed if it was
* down?
*/
UNSET_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE);
if (!CHECK_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE) &&
strict_mode) {
SET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
SET_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE);
/* Restart session to throw Role Mismatch
* Notification
*/
if (member->remote_role == ROLE_UNDEFINED)
bgp_session_reset(member);
}
} else {
member->local_role = role;
if (strict_mode) {
SET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
SET_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE);
} else {
UNSET_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE);
}
bgp_session_reset(member);
}
}
return CMD_SUCCESS;
} }
int peer_role_unset(struct peer *peer) int peer_role_unset(struct peer *peer)
{ {
struct peer *member;
struct listnode *node, *nnode;
peer_flag_unset(peer, PEER_FLAG_ROLE);
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
return peer_role_set(peer, ROLE_UNDEFINED, 0); return peer_role_set(peer, ROLE_UNDEFINED, 0);
for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member))
peer_role_set(member, ROLE_UNDEFINED, 0);
return CMD_SUCCESS;
} }
/* Neighbor description. */ /* Neighbor description. */

View File

@ -1337,9 +1337,12 @@ struct peer {
#define PEER_FLAG_EXTENDED_OPT_PARAMS (1ULL << 30) #define PEER_FLAG_EXTENDED_OPT_PARAMS (1ULL << 30)
/* BGP Open Policy flags. /* BGP Open Policy flags.
* Enforce using roles on both sides * Enforce using roles on both sides:
* `local-role ROLE strict-mode` configured.
*/ */
#define PEER_FLAG_STRICT_MODE (1ULL << 31) #define PEER_FLAG_ROLE_STRICT_MODE (1ULL << 31)
/* `local-role` configured */
#define PEER_FLAG_ROLE (1ULL << 32)
/* /*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART

View File

@ -2,18 +2,24 @@ router bgp 64501
bgp router-id 192.168.2.1 bgp router-id 192.168.2.1
network 192.0.2.0/24 network 192.0.2.0/24
! Correct role pair ! Correct role pair
neighbor 192.168.2.2 remote-as 64502 neighbor 192.168.2.2 remote-as external
neighbor 192.168.2.2 local-role provider neighbor 192.168.2.2 local-role provider
neighbor 192.168.2.2 timers 3 10 neighbor 192.168.2.2 timers 3 10
! Incorrect role pair ! Incorrect role pair
neighbor 192.168.3.2 remote-as 64503 neighbor 192.168.3.2 remote-as external
neighbor 192.168.3.2 local-role provider neighbor 192.168.3.2 local-role provider
neighbor 192.168.3.2 timers 3 10 neighbor 192.168.3.2 timers 3 10
! Missed neighbor role ! Missed neighbor role
neighbor 192.168.4.2 remote-as 64504 neighbor 192.168.4.2 remote-as external
neighbor 192.168.4.2 local-role provider neighbor 192.168.4.2 local-role provider
neighbor 192.168.4.2 timers 3 10 neighbor 192.168.4.2 timers 3 10
! Missed neighbor role with strict-mode ! Missed neighbor role with strict-mode
neighbor 192.168.5.2 remote-as 64505 neighbor 192.168.5.2 remote-as external
neighbor 192.168.5.2 local-role provider strict-mode neighbor 192.168.5.2 local-role provider strict-mode
neighbor 192.168.5.2 timers 3 10 neighbor 192.168.5.2 timers 3 10
! Testing peer-groups
neighbor PG peer-group
neighbor PG remote-as external
neighbor PG local-role provider
neighbor PG timers 3 10
neighbor 192.168.6.2 peer-group PG

View File

@ -11,5 +11,8 @@ interface r1-eth2
interface r1-eth3 interface r1-eth3
ip address 192.168.5.1/24 ip address 192.168.5.1/24
! !
interface r1-eth4
ip address 192.168.6.1/24
!
ip forwarding ip forwarding
! !

View File

@ -1,5 +1,5 @@
router bgp 64502 router bgp 64502
bgp router-id 192.168.2.2 bgp router-id 192.168.2.2
neighbor 192.168.2.1 remote-as 64501 neighbor 192.168.2.1 remote-as external
neighbor 192.168.2.1 local-role customer neighbor 192.168.2.1 local-role customer
neighbor 192.168.2.1 timers 3 10 neighbor 192.168.2.1 timers 3 10

View File

@ -1,4 +1,4 @@
router bgp 64503 router bgp 64503
neighbor 192.168.3.1 remote-as 64501 neighbor 192.168.3.1 remote-as external
neighbor 192.168.3.1 local-role peer neighbor 192.168.3.1 local-role peer
neighbor 192.168.3.1 timers 3 10 neighbor 192.168.3.1 timers 3 10

View File

@ -1,3 +1,3 @@
router bgp 64504 router bgp 64504
neighbor 192.168.4.1 remote-as 64501 neighbor 192.168.4.1 remote-as external
neighbor 192.168.4.1 timers 3 10 neighbor 192.168.4.1 timers 3 10

View File

@ -1,3 +1,3 @@
router bgp 64505 router bgp 64505
neighbor 192.168.5.1 remote-as 64501 neighbor 192.168.5.1 remote-as external
neighbor 192.168.5.1 timers 3 10 neighbor 192.168.5.1 timers 3 10

View File

@ -0,0 +1,4 @@
router bgp 64506
neighbor 192.168.6.1 remote-as external
neighbor 192.168.6.1 local-role customer
neighbor 192.168.6.1 timers 3 10

View File

@ -0,0 +1,6 @@
!
interface r6-eth0
ip address 192.168.6.2/24
!
ip forwarding
!

View File

@ -43,7 +43,7 @@ from lib.topolog import logger
pytestmark = [pytest.mark.bgpd] pytestmark = [pytest.mark.bgpd]
topodef = {f"s{i}": ("r1", f"r{i}") for i in range(2, 6)} topodef = {f"s{i}": ("r1", f"r{i}") for i in range(2, 7)}
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
@ -162,6 +162,24 @@ def test_role_strict_mode(tgen):
assert success, "Session between r1 and r5 was not correctly closed" assert success, "Session between r1 and r5 was not correctly closed"
def test_correct_pair_peer_group(tgen):
# provider-customer pair (using peer-groups)
router = tgen.gears["r1"]
neighbor_ip = "192.168.6.2"
check_r6_established = functools.partial(
check_session_established, router, neighbor_ip
)
success, _ = topotest.run_and_expect(check_r6_established, True, count=20, wait=3)
assert success, "Session with r6 is not Established"
neighbor_status = find_neighbor_status(router, neighbor_ip)
assert neighbor_status["localRole"] == "provider"
assert neighbor_status["remoteRole"] == "customer"
assert (
neighbor_status["neighborCapabilities"].get("role") == "advertisedAndReceived"
)
if __name__ == "__main__": if __name__ == "__main__":
args = ["-s"] + sys.argv[1:] args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args)) sys.exit(pytest.main(args))