forked from sonic-net/sonic-mgmt
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_bgp_speaker.py
More file actions
204 lines (156 loc) · 8.57 KB
/
Copy pathtest_bgp_speaker.py
File metadata and controls
204 lines (156 loc) · 8.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import pytest
from netaddr import *
import time
import logging
import requests
from common.fixtures.ptfhost_utils import copy_ptftests_directory # lgtm[py/unused-import]
from common.fixtures.ptfhost_utils import change_mac_addresses # lgtm[py/unused-import]
from ptf_runner import ptf_runner
from common.utilities import wait_tcp_connection
pytestmark = [
pytest.mark.topology('t0'),
pytest.mark.device_type('vs')
]
def generate_ips(num, prefix, exclude_ips):
"""
Generate random ips within prefix
"""
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:
if available_ip not in exclude_ips:
generated_ips.append(IPNetwork(str(available_ip) + '/' + str(prefix.prefixlen)))
if len(generated_ips) == num:
break
return generated_ips
def announce_route(ptfip, neighbor, route, nexthop, port):
url = "http://%s:%d" % (ptfip, port)
data = {"command": "neighbor %s announce route %s next-hop %s" % (neighbor, route, nexthop)}
r = requests.post(url, data=data)
assert r.status_code == 200
@pytest.fixture(scope="module")
def common_setup_teardown(duthost, ptfhost, localhost):
logging.info("########### Setup for bgp speaker testing ###########")
ptfip = ptfhost.host.options['inventory_manager'].get_host(ptfhost.hostname).vars['ansible_host']
logging.info("ptfip=%s" % ptfip)
ptfhost.script("./scripts/remove_ip.sh")
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']]\"")
bgp_speaker_asn = res['stdout']
vlan_ips = generate_ips(3, "%s/%s" % (mg_facts['minigraph_vlan_interfaces'][0]['addr'],
mg_facts['minigraph_vlan_interfaces'][0]['prefixlen']),
[IPAddress(mg_facts['minigraph_vlan_interfaces'][0]['addr'])])
logging.info("Generated vlan_ips: %s" % str(vlan_ips))
speaker_ips = generate_ips(2, mg_facts['minigraph_bgp_peers_with_range'][0]['ip_range'][0], [])
speaker_ips.append(vlan_ips[0])
logging.info("speaker_ips: %s" % str(speaker_ips))
for ip in vlan_ips:
duthost.command("ip route flush %s/32" % ip.ip)
duthost.command("ip route add %s/32 dev %s" % (ip.ip, mg_facts['minigraph_vlan_interfaces'][0]['attachto']))
port_num = [7000, 8000, 9000]
lo_addr = mg_facts['minigraph_lo_interfaces'][0]['addr']
lo_addr_prefixlen = int(mg_facts['minigraph_lo_interfaces'][0]['prefixlen'])
vlan_addr = mg_facts['minigraph_vlan_interfaces'][0]['addr']
vlan_ports = []
for i in range(0, 3):
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))
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]))
ptfhost.shell("ifconfig eth%d:1 %s" % (vlan_ports[0], speaker_ips[1]))
ptfhost.shell("ifconfig eth%d %s" % (vlan_ports[1], vlan_ips[1]))
ptfhost.shell("ifconfig eth%d %s" % (vlan_ports[2], vlan_ips[2]))
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("Start exabgp on ptf")
for i in range(0, 3):
local_ip = str(speaker_ips[i].ip)
ptfhost.exabgp(name="bgps%d" % i,
state="started",
local_ip=local_ip,
router_id=local_ip,
peer_ip=lo_addr,
local_asn=bgp_speaker_asn,
peer_asn=mg_facts['minigraph_bgp_asn'],
port=str(port_num[i]))
# check exabgp http_api port is ready
http_ready = True
for i in range(0, 3):
http_ready = wait_tcp_connection(localhost, ptfip, port_num[i])
if not http_ready:
break
logging.info("########### Done setup for bgp speaker testing ###########")
yield ptfip, mg_facts, interface_facts, vlan_ips, 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")
for ip in vlan_ips:
duthost.command("ip route flush %s/32" % ip.ip, module_ignore_errors=True)
ptfhost.script("./scripts/remove_ip.sh")
logging.info("########### Done teardown for bgp speaker testing ###########")
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
assert http_ready
logging.info("Wait some time to verify that bgp sessions are established")
time.sleep(20)
bgp_facts = duthost.bgp_facts()['ansible_facts']
assert all([v["state"] == "established" for _, v in bgp_facts["bgp_neighbors"].items()]), \
"Not all bgp sessions are established"
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):
"""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
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])
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")
time.sleep(30)
# The ping here is workaround for known issue:
# https://github.com/Azure/SONiC/issues/387 Pre-ARP support for static route config
# When there is no arp entry for next hop, routes learnt from exabgp will not be set down to ASIC
# Traffic to prefix 10.10.10.0 will be routed to vEOS VMs via default gateway.
duthost.shell("ping %s -c 3" % vlan_ips[1].ip)
duthost.shell("ping %s -c 3" % vlan_ips[2].ip)
time.sleep(5)
logging.info("Verify accepted prefixes of the dynamic neighbors are correct")
bgp_facts = duthost.bgp_facts()['ansible_facts']
for ip in speaker_ips:
assert bgp_facts['bgp_neighbors'][str(ip.ip)]['accepted prefixes'] == 1
logging.info("Generate route-port map information")
extra_vars = {'announce_prefix': '10.10.10.0/26',
'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")
logging.info("run ptf test")
ptf_runner(ptfhost,
"ptftests",
"fib_test.FibTest",
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",
"ipv4": ipv4,
"ipv6": ipv6,
"testbed_mtu": mtu },
log_file="/tmp/bgp_speaker_test.FibTest.log",
socket_recv_size=16384)