!
router bgp 65500 vrf vrf1
bgp router-id 192.0.2.1
+ neighbor 172.31.2.100 remote-as 65500
address-family ipv4 unicast
redistribute connected
+ aggregate-address 172.31.1.0/24
label vpn export 101
rd vpn export 444:1
rt vpn both 52:100
--- /dev/null
+{
+ "444:1":{
+ "prefix":"172.31.1.0/24",
+ "advertisedTo":{
+ "192.168.0.2":{
+ "hostname":"r2"
+ },
+ "192.168.0.3":{
+ "hostname":"r3"
+ }
+ },
+ "paths":[
+ {
+ "aspath":{
+ "string":"Local",
+ "segments":[
+ ],
+ "length":0
+ },
+ "aggregatorAs":65500,
+ "aggregatorId":"192.0.2.1",
+ "nhVrfName":"vrf1",
+ "announceNexthopSelf":true,
+ "origin":"incomplete",
+ "metric":0,
+ "weight":32768,
+ "valid":true,
+ "sourced":true,
+ "local":true,
+ "atomicAggregate":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"First path received"
+ },
+ "originatorId":"192.0.2.1",
+ "nexthops":[
+ {
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "metric":0,
+ "accessible":true,
+ "used":true
+ }
+ ],
+ "peer":{
+ "peerId":"0.0.0.0",
+ "routerId":"192.0.2.1"
+ }
+ }
+ ]
+ }
+}
log stdout
interface r1-eth1 vrf vrf1
ip address 172.31.0.1/32
+ ip address 172.31.1.1/32
+ ip address 172.31.1.2/32
+ ip address 172.31.1.3/32
+ ip address 172.31.2.1/24
!
interface r1-eth0
ip address 192.168.0.1/24
--- /dev/null
+router bgp 65500
+ bgp router-id 192.0.2.100
+ neighbor 172.31.2.1 remote-as 65500
+ address-family ipv4 unicast
+ exit-address-family
+exit
--- /dev/null
+{
+ "vrfId": 0,
+ "vrfName": "default",
+ "routerId": "192.0.2.100",
+ "defaultLocPrf": 100,
+ "localAS": 65500,
+ "routes": {
+ "172.31.0.1/32": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.0.1",
+ "prefixLen":32,
+ "network":"172.31.0.1/32",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true
+ }]
+ }],
+ "172.31.0.10/32": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.0.10",
+ "prefixLen":32,
+ "network":"172.31.0.10/32",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"65501",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true
+ }]
+ }],
+ "172.31.1.0/24": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.1.0",
+ "prefixLen":24,
+ "network":"172.31.1.0/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true
+ }]
+ }],
+ "172.31.1.1/32": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.1.1",
+ "prefixLen":32,
+ "network":"172.31.1.1/32",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true}]
+ }],
+ "172.31.1.2/32": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.1.2",
+ "prefixLen":32,
+ "network":"172.31.1.2/32",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true}]
+ }],
+ "172.31.1.3/32": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.1.3",
+ "prefixLen":32,
+ "network":"172.31.1.3/32",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true
+ }]
+ }],
+ "172.31.2.0/24": [{
+ "valid":true,
+ "bestpath":true,
+ "selectionReason":"First path received",
+ "pathFrom":"internal",
+ "prefix":"172.31.2.0",
+ "prefixLen":24,
+ "network":"172.31.2.0/24",
+ "metric":0,
+ "locPrf":100,
+ "weight":0,
+ "peerId":"172.31.2.1",
+ "path":"",
+ "origin":"incomplete",
+ "nexthops":[{
+ "ip":"172.31.2.1",
+ "afi":"ipv4",
+ "used":true}]
+ }]
+ } ,
+ "totalRoutes": 7,
+ "totalPaths": 7
+}
--- /dev/null
+log stdout
+interface r100-eth0
+ ip address 172.31.2.100/24
+!
tgen.add_router("r1")
tgen.add_router("r2")
tgen.add_router("r3")
+ tgen.add_router("r100")
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
switch = tgen.add_switch("s2")
switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r100"])
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["r2"])
assert result is None, assertmsg
+def test_aggregated_route_on_r100():
+ """
+ Check that only aggregated route on r100 is received
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r100 = tgen.gears["r100"]
+ logger.info("Checking prefixes list on R100")
+ json_file = "{}/{}/show_bgp_ipv4.json".format(CWD, r100.name)
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ r100,
+ "show bgp ipv4 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(r100.name)
+ assert result is None, assertmsg
+
+
+def test_aggregated_exported_route_on_r1():
+ """
+ Check that the aggregated route 172.31.1.0/24 is exported
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ logger.info("Checking 172.31.1.0/24 VPN prefix on R1")
+ json_file = "{}/{}/show_bgp_ipv4_172_31_1_0.json".format(CWD, r1.name)
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ r1,
+ "show bgp ipv4 vpn 172.31.1.0/24 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(r1.name)
+ assert result is None, assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()