Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
05379d5
Add a test to check ipv6 routes over ipv4 bgp session
pavel-shirshov Jul 21, 2020
7fe4f01
Remove debug code
pavel-shirshov Jul 21, 2020
8b9830c
Restore old code
pavel-shirshov Jul 21, 2020
487b272
Fix a bug in exabgp module
pavel-shirshov Jul 21, 2020
63cb226
Fix issues from lgtm
pavel-shirshov Jul 21, 2020
7d7be28
Add ipv6 prefixes to vlans
pavel-shirshov Jul 25, 2020
6d1edcf
Use ansible module to check existence of the file
pavel-shirshov Jul 25, 2020
dd63695
Check added nexthop routes using get_ip_route_info
pavel-shirshov Aug 3, 2020
fbb2a45
Merge branch 'master' into pavelsh/ipv6_ipv4_test
pavel-shirshov Aug 3, 2020
c41154a
Fix imports
pavel-shirshov Aug 3, 2020
06d2f22
Working for me
pavel-shirshov Aug 4, 2020
91878db
nexthop_ipv6 order could be rearranged
pavel-shirshov Aug 4, 2020
2fb3a21
Use correct number of arguments
pavel-shirshov Aug 4, 2020
b65f811
Fix lgtm warnings
pavel-shirshov Aug 4, 2020
97d24b8
Temporary. For debug
pavel-shirshov Aug 5, 2020
a0a58af
Revert "Temporary. For debug"
pavel-shirshov Aug 6, 2020
9271bf0
Merge branch 'master' into pavelsh/ipv6_ipv4_test
pavel-shirshov Aug 6, 2020
e36828a
Rename double _ to _
pavel-shirshov Aug 7, 2020
a37834b
Rename /root/bgp_speaker_route.txt to /root/bgp_speaker_v6route.txt f…
pavel-shirshov Aug 7, 2020
6b6eaeb
Add nexthop check into test_bgp_speaker_announce_routes()
pavel-shirshov Aug 7, 2020
38f08c9
Check number of received routes
pavel-shirshov Aug 8, 2020
2a8741d
Change order in yield
pavel-shirshov Aug 9, 2020
34bbeec
Extract common test body
pavel-shirshov Aug 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ansible/library/exabgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def setup_exabgp_conf(name, router_id, local_ip, peer_ip, local_asn, peer_asn, p
def remove_exabgp_conf(name):
try:
os.remove("/etc/exabgp/%s.conf" % name)
except e:
except Exception:
pass


Expand All @@ -200,7 +200,7 @@ def setup_exabgp_supervisord_conf(name):
def remove_exabgp_supervisord_conf(name):
try:
os.remove("/etc/supervisor/conf.d/exabgp-%s.conf" % name)
except e:
except Exception:
pass

def setup_exabgp_processor():
Expand Down
7 changes: 7 additions & 0 deletions ansible/roles/test/files/ptftests/fib.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ def __getitem__(self, ip):
elif ip.version is 6:
return self._ipv6_lpm_dict[str(ip)]

def __contains__(self, ip):
ip_obj = ip_address(unicode(ip))
if ip_obj.version == 4:
return self._ipv4_lpm_dict.contains(ip)
elif ip_obj.version == 6:
return self._ipv6_lpm_dict.contains(ip)

def ipv4_ranges(self):
return self._ipv4_lpm_dict.ranges()

Expand Down
5 changes: 3 additions & 2 deletions ansible/roles/test/files/ptftests/fib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ def check_ip_ranges(self, ipv4=True):
ip_ranges = self.fib.ipv6_ranges()

for ip_range in ip_ranges:
next_hop = self.fib[ip_range.get_first_ip()]
self.check_ip_range(ip_range, next_hop, ipv4)
if ip_range.get_first_ip() in self.fib:
next_hop = self.fib[ip_range.get_first_ip()]
self.check_ip_range(ip_range, next_hop, ipv4)

def check_ip_range(self, ip_range, next_hop, ipv4=True):
# Get the expected list of ports that would receive the packets
Expand Down
3 changes: 3 additions & 0 deletions ansible/roles/test/files/ptftests/lpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,6 @@ def ranges(self):
interval = self.IpInterval(sorted_boundaries[index], ip_address(u'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'))
ranges.append(interval)
return ranges

def contains(self, key):
return key in self._subnet_tree
105 changes: 84 additions & 21 deletions tests/bgp/test_bgp_speaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
import time
import logging
import requests
import ipaddress


from tests.common.fixtures.ptfhost_utils import copy_ptftests_directory # lgtm[py/unused-import]
from tests.common.fixtures.ptfhost_utils import change_mac_addresses # lgtm[py/unused-import]
from tests.common.fixtures.ptfhost_utils import remove_ip_addresses # lgtm[py/unused-import]
from tests.ptf_runner import ptf_runner
from tests.common.utilities import wait_tcp_connection


pytestmark = [
pytest.mark.topology('t0'),
pytest.mark.device_type('vs')
Expand All @@ -22,28 +25,30 @@ def generate_ips(num, prefix, exclude_ips):
prefix = IPNetwork(prefix)
exclude_ips.append(prefix.broadcast)
exclude_ips.append(prefix.network)
available_ips = list(prefix)

if len(available_ips) - len(exclude_ips)< num:
raise Exception("Not enough available IPs")

generated_ips = []
for available_ip in available_ips:
for available_ip in prefix:
if available_ip not in exclude_ips:
generated_ips.append(IPNetwork(str(available_ip) + '/' + str(prefix.prefixlen)))
if len(generated_ips) == num:
break
else:
raise Exception("Not enough available IPs")

return generated_ips


def announce_route(ptfip, neighbor, route, nexthop, port):
change_route("announce", ptfip, neighbor, route, nexthop, port)

def withdraw_route(ptfip, neighbor, route, nexthop, port):
change_route("withdraw", ptfip, neighbor, route, nexthop, port)

def change_route(operation, ptfip, neighbor, route, nexthop, port):
url = "http://%s:%d" % (ptfip, port)
data = {"command": "neighbor %s announce route %s next-hop %s" % (neighbor, route, nexthop)}
data = {"command": "neighbor %s %s route %s next-hop %s" % (neighbor, operation, route, nexthop)}
r = requests.post(url, data=data)
assert r.status_code == 200


@pytest.fixture(scope="module")
def common_setup_teardown(duthost, ptfhost, localhost):

Expand All @@ -55,7 +60,11 @@ def common_setup_teardown(duthost, ptfhost, localhost):
mg_facts = duthost.minigraph_facts(host=duthost.hostname)['ansible_facts']
interface_facts = duthost.interface_facts()['ansible_facts']

res = duthost.shell("sonic-cfggen -m -d -y /etc/sonic/constants.yml -v \"constants.deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']]\"")
constants_stat = duthost.stat(path="/etc/sonic/constants.yml")
if constants_stat["stat"]["exists"]:
res = duthost.shell("sonic-cfggen -m -d -y /etc/sonic/constants.yml -v \"constants.deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']]\"")
else:
res = duthost.shell("sonic-cfggen -m -d -y /etc/sonic/deployment_id_asn_map.yml -v \"deployment_id_asn_map[DEVICE_METADATA['localhost']['deployment_id']]\"")
bgp_speaker_asn = res['stdout']

vlan_ips = generate_ips(3, "%s/%s" % (mg_facts['minigraph_vlan_interfaces'][0]['addr'],
Expand Down Expand Up @@ -83,6 +92,19 @@ def common_setup_teardown(duthost, ptfhost, localhost):
vlan_ports.append(mg_facts['minigraph_port_indices'][mg_facts['minigraph_vlans'][mg_facts['minigraph_vlan_interfaces'][0]['attachto']]['members'][i]])
logging.info("vlan_ports: %s" % str(vlan_ports))

# Generate ipv6 nexthops
vlan_ipv6_entry = mg_facts['minigraph_vlan_interfaces'][1]
vlan_ipv6_prefix = "%s/%s" % (vlan_ipv6_entry["addr"], vlan_ipv6_entry["prefixlen"])
vlan_ipv6_address = vlan_ipv6_entry["addr"]
vlan_if_name = vlan_ipv6_entry['attachto']
nexthops_ipv6 = generate_ips(3, vlan_ipv6_prefix, [IPAddress(vlan_ipv6_address)])
logging.info("Generated nexthops_ipv6: %s" % str(nexthops_ipv6))

# Set ipv6 nexthop addresses on the ptf interfaces
for nh in nexthops_ipv6:
duthost.command("ip -6 route flush %s/64" % nh.ip)
duthost.command("ip -6 route add %s/64 dev %s" % (nh.ip, vlan_if_name))

logging.info("setup ip/routes in ptf")
ptfhost.shell("ifconfig eth%d %s" % (vlan_ports[0], vlan_ips[0]))
ptfhost.shell("ifconfig eth%d:0 %s" % (vlan_ports[0], speaker_ips[0]))
Expand All @@ -94,6 +116,10 @@ def common_setup_teardown(duthost, ptfhost, localhost):
ptfhost.shell("ip route flush %s/%d" % (lo_addr, lo_addr_prefixlen))
ptfhost.shell("ip route add %s/%d via %s" % (lo_addr, lo_addr_prefixlen, vlan_addr))

logging.info("setup ip/routes in ptf")
for i in [0, 1, 2]:
ptfhost.shell("ip -6 addr add %s dev eth%d:%d" % (nexthops_ipv6[i], vlan_ports[0], i))

logging.info("Start exabgp on ptf")
for i in range(0, 3):
local_ip = str(speaker_ips[i].ip)
Expand All @@ -115,12 +141,17 @@ def common_setup_teardown(duthost, ptfhost, localhost):

logging.info("########### Done setup for bgp speaker testing ###########")

yield ptfip, mg_facts, interface_facts, vlan_ips, speaker_ips, port_num, http_ready
yield ptfip, mg_facts, interface_facts, vlan_ips, nexthops_ipv6, vlan_if_name, speaker_ips, port_num, http_ready

logging.info("########### Teardown for bgp speaker testing ###########")

for i in range(0, 3):
ptfhost.exabgp(name="bgps%d" % i, state="absent")
logging.info("exabgp stopped")

for nh in nexthops_ipv6:
duthost.command("ip -6 route flush %s/64" % nh.ip)
logging.info("Flushed ipv6 nexthop routes from dut")

for ip in vlan_ips:
duthost.command("ip route flush %s/32" % ip.ip, module_ignore_errors=True)
Expand All @@ -131,7 +162,7 @@ def common_setup_teardown(duthost, ptfhost, localhost):
def test_bgp_speaker_bgp_sessions(common_setup_teardown, duthost, ptfhost, collect_techsupport):
"""Setup bgp speaker on T0 topology and verify bgp sessions are established
"""
ptfip, mg_facts, interface_facts, vlan_ips, speaker_ips, port_num, http_ready = common_setup_teardown
ptfip, mg_facts, interface_facts, vlan_ips, _, _, speaker_ips, port_num, http_ready = common_setup_teardown
assert http_ready

logging.info("Wait some time to verify that bgp sessions are established")
Expand All @@ -142,21 +173,20 @@ def test_bgp_speaker_bgp_sessions(common_setup_teardown, duthost, ptfhost, colle
assert str(speaker_ips[2].ip) in bgp_facts["bgp_neighbors"], "No bgp session with PTF"


@pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(True, False, 1514)])
def test_bgp_speaker_announce_routes(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, collect_techsupport):
def bgp_speaker_announce_routes_common(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, family, prefix, nexthop_ips):
"""Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR

"""
ptfip, mg_facts, interface_facts, vlan_ips, speaker_ips, port_num, http_ready = common_setup_teardown
ptfip, mg_facts, interface_facts, vlan_ips, _, vlan_if_name, speaker_ips, port_num, http_ready = common_setup_teardown
assert http_ready

logging.info("announce route")
peer_range = mg_facts['minigraph_bgp_peers_with_range'][0]['ip_range'][0]
lo_addr = mg_facts['minigraph_lo_interfaces'][0]['addr']
lo_addr_prefixlen = int(mg_facts['minigraph_lo_interfaces'][0]['prefixlen'])
prefix = '10.10.10.0/26'
announce_route(ptfip, lo_addr, prefix, vlan_ips[1].ip, port_num[0])
announce_route(ptfip, lo_addr, prefix, vlan_ips[2].ip, port_num[1])

logging.info("Announce ip%s prefixes over ipv4 bgp sessions" % family)
announce_route(ptfip, lo_addr, prefix, nexthop_ips[1].ip, port_num[0])
announce_route(ptfip, lo_addr, prefix, nexthop_ips[2].ip, port_num[1])
announce_route(ptfip, lo_addr, peer_range, vlan_ips[0].ip, port_num[2])

logging.info("Wait some time to make sure routes announced to dynamic bgp neighbors")
Expand All @@ -175,15 +205,23 @@ def test_bgp_speaker_announce_routes(common_setup_teardown, testbed, duthost, pt
for ip in speaker_ips:
assert bgp_facts['bgp_neighbors'][str(ip.ip)]['accepted prefixes'] == 1

logging.info("Verify nexthops and nexthop interfaces for accepted prefixes of the dynamic neighbors")
rtinfo = duthost.get_ip_route_info(ipaddress.ip_network(unicode(prefix)))
nexthops_ip_set = { str(nexthop.ip) for nexthop in nexthop_ips }
assert len(rtinfo["nexthops"]) == 2
for i in [0,1]:
assert str(rtinfo["nexthops"][i][0]) in nexthops_ip_set
assert rtinfo["nexthops"][i][1] == unicode(vlan_if_name)

logging.info("Generate route-port map information")
extra_vars = {'announce_prefix': '10.10.10.0/26',
extra_vars = {'announce_prefix': prefix,
'minigraph_portchannels': mg_facts['minigraph_portchannels'],
'minigraph_vlans': mg_facts['minigraph_vlans'],
'minigraph_port_indices': mg_facts['minigraph_port_indices']}
ptfhost.host.options['variable_manager'].extra_vars.update(extra_vars)
logging.info("extra_vars: %s" % str(ptfhost.host.options['variable_manager'].extra_vars))

ptfhost.template(src="bgp_speaker/bgp_speaker_route.j2", dest="/root/bgp_speaker_route.txt")
ptfhost.template(src="bgp_speaker/bgp_speaker_route.j2", dest="/root/bgp_speaker_route_%s.txt" % family)

logging.info("run ptf test")

Expand All @@ -193,9 +231,34 @@ def test_bgp_speaker_announce_routes(common_setup_teardown, testbed, duthost, pt
platform_dir="ptftests",
params={"testbed_type": testbed['topo']['name'],
"router_mac": interface_facts['ansible_interface_facts']['Ethernet0']['macaddress'],
"fib_info": "/root/bgp_speaker_route.txt",
"fib_info": "/root/bgp_speaker_route_%s.txt" % family,
"ipv4": ipv4,
"ipv6": ipv6,
"testbed_mtu": mtu },
log_file="/tmp/bgp_speaker_test.FibTest.log",
socket_recv_size=16384)

logging.info("Withdraw routes")
withdraw_route(ptfip, lo_addr, prefix, nexthop_ips[1].ip, port_num[0])
withdraw_route(ptfip, lo_addr, prefix, nexthop_ips[2].ip, port_num[1])
withdraw_route(ptfip, lo_addr, peer_range, vlan_ips[0].ip, port_num[2])

logging.info("Nexthop ip%s tests are done" % family)


@pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(True, False, 1514)])
def test_bgp_speaker_announce_routes(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, collect_techsupport):
"""Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR

"""
nexthops = common_setup_teardown[3]
bgp_speaker_announce_routes_common(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, "v4", "10.10.10.0/26", nexthops)


@pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(False, True, 1514)])
def test_bgp_speaker_announce_routes_v6(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, collect_techsupport):
"""Setup bgp speaker on T0 topology and verify routes advertised by bgp speaker is received by T0 TOR

"""
nexthops = common_setup_teardown[4]
bgp_speaker_announce_routes_common(common_setup_teardown, testbed, duthost, ptfhost, ipv4, ipv6, mtu, "v6", "fc00:10::/64", nexthops)