Commit 23a1c4820f for frr
commit 23a1c4820fdd7b4704aba95175cae18b3d9a99a7
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date: Mon Oct 12 14:16:17 2026 +0200
topotests: check aigp received from ebgp peers in bgp_aigp
The "neighbor PEER aigp" command is documented as valid only for eBGP
neighbors, but no test uses it on a plain eBGP session: it is only
configured on eBGP-OAD sessions, where AIGP is disabled by default,
and on iBGP sessions, where AIGP is already enabled. As a consequence,
nothing checks that an AIGP attribute received from an eBGP peer is
accepted with the command, and ignored without it.
bgp_attr_aigp() ignores the received AIGP attribute when
AIGP_TRANSMIT_ALLOWED() is false, i.e. for an eBGP peer without the aigp
flag.
Fix this by adding two ExaBGP eBGP peers to r7, each advertising a prefix
with an AIGP attribute. r7 has "neighbor PEER aigp" for peer1 only. Check
that the AIGP metric is kept for the peer1 prefix and dropped for the
peer2 prefix.
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
diff --git a/tests/topotests/bgp_aigp/exabgp.env b/tests/topotests/bgp_aigp/exabgp.env
new file mode 100644
index 0000000000..28e642360a
--- /dev/null
+++ b/tests/topotests/bgp_aigp/exabgp.env
@@ -0,0 +1,53 @@
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp_aigp/peer1/exabgp.cfg b/tests/topotests/bgp_aigp/peer1/exabgp.cfg
new file mode 100644
index 0000000000..0966f90fc2
--- /dev/null
+++ b/tests/topotests/bgp_aigp/peer1/exabgp.cfg
@@ -0,0 +1,14 @@
+neighbor 192.168.7.7 {
+ router-id 192.168.7.101;
+ local-address 192.168.7.101;
+ local-as 65101;
+ peer-as 65001;
+
+ static {
+ route 10.0.7.101/32 {
+ # AIGP attribute with an AIGP Metric TLV of 101
+ attribute [0x1a 0x80 0x01000b0000000000000065];
+ next-hop 192.168.7.101;
+ }
+ }
+}
diff --git a/tests/topotests/bgp_aigp/peer2/exabgp.cfg b/tests/topotests/bgp_aigp/peer2/exabgp.cfg
new file mode 100644
index 0000000000..286c66f8f0
--- /dev/null
+++ b/tests/topotests/bgp_aigp/peer2/exabgp.cfg
@@ -0,0 +1,14 @@
+neighbor 192.168.7.7 {
+ router-id 192.168.7.102;
+ local-address 192.168.7.102;
+ local-as 65102;
+ peer-as 65001;
+
+ static {
+ route 10.0.7.102/32 {
+ # AIGP attribute with an AIGP Metric TLV of 102
+ attribute [0x1a 0x80 0x01000b0000000000000066];
+ next-hop 192.168.7.102;
+ }
+ }
+}
diff --git a/tests/topotests/bgp_aigp/r7/bgpd.conf b/tests/topotests/bgp_aigp/r7/bgpd.conf
index a075714859..162aa6b75b 100644
--- a/tests/topotests/bgp_aigp/r7/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r7/bgpd.conf
@@ -4,6 +4,13 @@ router bgp 65001
neighbor 192.168.67.6 remote-as internal
neighbor 192.168.67.6 timers 1 3
neighbor 192.168.67.6 timers connect 1
+ neighbor 192.168.7.101 remote-as external
+ neighbor 192.168.7.101 timers 1 3
+ neighbor 192.168.7.101 timers connect 1
+ neighbor 192.168.7.101 aigp
+ neighbor 192.168.7.102 remote-as external
+ neighbor 192.168.7.102 timers 1 3
+ neighbor 192.168.7.102 timers connect 1
address-family ipv4
redistribute connected route-map rmap metric 71
exit-address-family
diff --git a/tests/topotests/bgp_aigp/r7/zebra.conf b/tests/topotests/bgp_aigp/r7/zebra.conf
index 30e1c8a7a8..47c9347e7e 100644
--- a/tests/topotests/bgp_aigp/r7/zebra.conf
+++ b/tests/topotests/bgp_aigp/r7/zebra.conf
@@ -8,3 +8,6 @@ interface lo
interface r7-eth0
ip address 192.168.67.7/24
!
+interface r7-eth1
+ ip address 192.168.7.7/24
+!
diff --git a/tests/topotests/bgp_aigp/test_bgp_aigp.py b/tests/topotests/bgp_aigp/test_bgp_aigp.py
index e2dac8e65e..f714d12c45 100644
--- a/tests/topotests/bgp_aigp/test_bgp_aigp.py
+++ b/tests/topotests/bgp_aigp/test_bgp_aigp.py
@@ -22,6 +22,10 @@ r1 advertises MED from AIGP (set metric aigp) to r8.
r8 does not receive the AIGP attribute, as r1 -> r8 is an eBGP session
without "neighbor PEER aigp".
+
+peer1 and peer2 are eBGP peers of r7, and both advertise a prefix with
+the AIGP attribute. r7 accepts it from peer1 ("neighbor PEER aigp"),
+and ignores it from peer2.
"""
import os
@@ -36,6 +40,7 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import retry
pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
@@ -76,6 +81,16 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r8"])
+ switch = tgen.add_switch("s9")
+ switch.add_link(tgen.gears["r7"])
+ for peern in range(1, 3):
+ peer = tgen.add_exabgp_peer(
+ "peer{}".format(peern),
+ ip="192.168.7.10{}/24".format(peern),
+ defaultRoute="via 192.168.7.7",
+ )
+ switch.add_link(peer)
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -96,12 +111,28 @@ def setup_module(mod):
tgen.start_router()
+ for peern in range(1, 3):
+ peer = tgen.gears["peer{}".format(peern)]
+ peer.start(os.path.join(CWD, peer.name), os.path.join(CWD, "exabgp.env"))
+
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
+@retry(retry_timeout=60)
+def check_aigp_metric(router, prefix, aigp):
+ output = json.loads(
+ router.vtysh_cmd("show bgp ipv4 unicast {} json".format(prefix))
+ )
+ expected = {"paths": [{"valid": True, "aigpMetric": aigp}]}
+ result = topotest.json_cmp(output, expected)
+ if result is not None:
+ return str(result)
+ return True
+
+
def test_bgp_aigp():
tgen = get_topogen()
@@ -300,6 +331,23 @@ def test_bgp_aigp():
), "MED is not derived from `set metric [a]igp`, or AIGP is received"
+def test_bgp_aigp_ebgp_peer():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r7 = tgen.gears["r7"]
+
+ # peer1 is configured with "neighbor PEER aigp"
+ result = check_aigp_metric(r7, "10.0.7.101/32", 101)
+ assert result is True, result
+
+ # peer2 is not configured with "neighbor PEER aigp"
+ result = check_aigp_metric(r7, "10.0.7.102/32", None)
+ assert result is True, result
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))