This commit is contained in:
Soumya Roy 2025-04-29 19:27:28 +00:00 committed by GitHub
commit 3c5eb76d03
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 123 additions and 10 deletions

View file

@ -11110,9 +11110,8 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
}
}
static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
int *first, const char *header,
json_object *json_adv_to)
static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer, int *first,
const char *header, json_object *json_adv_to)
{
json_object *json_peer = NULL;
@ -11129,6 +11128,10 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
json_object_string_add(json_peer, "hostname",
peer->hostname);
/* Add peerGroup information when the peer belongs to a group */
if (peer->group)
json_object_string_add(json_peer, "peerGroup", peer->group->name);
if (peer->conf_if)
json_object_object_add(json_adv_to, peer->conf_if,
json_peer);
@ -13186,17 +13189,13 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
* though then we must display Advertised to on a path-by-path basis. */
if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (peer->group)
continue;
if (bgp_adj_out_lookup(peer, dest, 0)) {
if (json && !json_adv_to)
json_adv_to = json_object_new_object();
route_vty_out_advertised_to(
vty, peer, &first,
" Advertised to non peer-group peers:\n ",
json_adv_to);
route_vty_out_advertised_to(vty, peer, &first,
" Advertised to peers:\n ",
json_adv_to);
}
}

View file

@ -17,6 +17,9 @@ import sys
import json
import pytest
import functools
from time import sleep
import re
import json
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@ -179,6 +182,117 @@ def test_bgp_peer_group_remote_as_del_readd():
assert result is None, "Failed bgp convergence in r1"
def test_bgp_peer_group_with_non_peer_group_peer():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
logger.info("Change a peer r1-eth0 to be non peer group and PG2 to have two peers")
r1.vtysh_cmd(
"""
configure terminal
router bgp 65001
no bgp ebgp-requires-policy
no neighbor 192.168.251.2 peer-group PG1
neighbor PG2 remote-as external
neighbor 192.168.251.2 peer-group PG2
no neighbor r1-eth0 interface peer-group PG
neighbor r1-eth0 interface remote-as external
address-family ipv4 unicast
redistribute connected
"""
)
# Function to check if the route is properly advertised to all expected peers
def _check_route_advertisement():
output_str = r1.vtysh_cmd("show bgp ipv4 unicast 192.168.251.0/30 json")
try:
output = json.loads(output_str)
except json.JSONDecodeError:
# If we get invalid JSON, return a difference to continue waiting
return "Invalid JSON received"
# Define the expected structure based on the exact JSON format shared
expected = {
"advertisedTo": {
"192.168.255.3": {"peerGroup": "PG"},
"192.168.251.2": {"peerGroup": "PG2"},
"192.168.252.2": {"peerGroup": "PG2"},
"r1-eth0": {}, # Just verify existence, content will vary
}
}
# Return any differences between expected and actual output
return topotest.json_cmp(output, expected)
# Wait for the route to be properly advertised to all peers
test_func = functools.partial(_check_route_advertisement)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "Route 192.168.251.0/30 not properly advertised to all peers"
# Now get the text BGP output for pattern matching
show_bgp_adv_str = r1.vtysh_cmd("show bgp ipv4 unicast 192.168.251.0/30").rstrip()
# Part 1: Check text output format
# Check for "Advertised to peers:" section
adv_to_peers_pattern = r"Advertised to peers:"
adv_to_peers_match = re.search(adv_to_peers_pattern, show_bgp_adv_str)
assert adv_to_peers_match is not None, "Missing 'Advertised to peers:' section"
# Check for specific peers
pg_peer_pattern = r"192\.168\.255\.3"
pg_peer_match = re.search(pg_peer_pattern, show_bgp_adv_str)
assert pg_peer_match is not None, "Missing peer 192.168.255.3"
pg2_peer1_pattern = r"192\.168\.251\.2"
pg2_peer1_match = re.search(pg2_peer1_pattern, show_bgp_adv_str)
assert pg2_peer1_match is not None, "Missing peer 192.168.251.2"
pg2_peer2_pattern = r"192\.168\.252\.2"
pg2_peer2_match = re.search(pg2_peer2_pattern, show_bgp_adv_str)
assert pg2_peer2_match is not None, "Missing peer 192.168.252.2"
# Check for the non-peer-group peer
non_pg_peer_pattern = r"r1-eth0"
non_pg_peer_match = re.search(non_pg_peer_pattern, show_bgp_adv_str)
assert non_pg_peer_match is not None, "Missing peer r1-eth0"
# Verify the complete advertised peers line
# Check that all peers appear after the "Advertised to peers:" line
peers_line_pattern = r"Advertised to peers:[\r\n]+\s+.*(192\.168\.255\.3).*"
peers_line_match = re.search(peers_line_pattern, show_bgp_adv_str, re.DOTALL)
assert (
peers_line_match is not None
), "The 'Advertised to peers:' section doesn't contain the peers"
# Verify all expected peers are in the peers line
all_peers_pattern = r"Advertised to peers:[\r\n]+\s+.*192\.168\.255\.3.*192\.168\.251\.2.*192\.168\.252\.2.*r1-eth0"
all_peers_match = re.search(all_peers_pattern, show_bgp_adv_str, re.DOTALL)
assert (
all_peers_match is not None
), "Not all expected peers appear in the advertised peers list"
logger.info("Rollback config change")
r1.vtysh_cmd(
"""
configure terminal
router bgp 65001
bgp ebgp-requires-policy
no neighbor 192.168.251.2 peer-group PG2
no neighbor PG2 remote-as external
neighbor 192.168.251.2 peer-group PG1
no neighbor r1-eth0 interface remote-as external
neighbor r1-eth0 interface peer-group PG
address-family ipv4 unicast
no redistribute connected
"""
)
logger.info(f"test_bgp_peer_group_with_non_peer_group_peer passed")
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))