Skip to content

Commit bd86c6f

Browse files
dt-nexthopgshemesh2
authored andcommitted
Add traffic tests for static and directly connected routes in IPFWD test suite (sonic-net#17058)
What is the motivation for this PR? Additional coverage in forwarding test How did you do it? Added extra cases to the existing script to handle the cases where traffic is sent to directly connected route as well as to a prefix that is reachable through a static route. How did you verify/test it? Run on T1 topology running master Signed-off-by: Guy Shemesh <gshemesh@nvidia.com>
1 parent d6d8c38 commit bd86c6f

1 file changed

Lines changed: 285 additions & 41 deletions

File tree

tests/ipfwd/test_dip_sip.py

Lines changed: 285 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
DEFAULT_HLIM_TTL = 64
99
WAIT_EXPECTED_PACKET_TIMEOUT = 5
10+
STATIC_ROUTE = '201.1.1.1/32'
11+
STATIC_ROUTE_IPV6 = '2001:db8:1::1/128'
1012

1113
logger = logging.getLogger(__name__)
1214

@@ -23,67 +25,309 @@ def lldp_setup(duthosts, enum_rand_one_per_hwsku_frontend_hostname, patch_lldpct
2325
unpatch_lldpctl(localhost, duthost)
2426

2527

26-
def run_test_ipv6(ptfadapter, facts):
27-
logger.info("Running test with ipv6 packets")
28+
@pytest.fixture(scope="function", autouse=True)
29+
def setup_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts, request):
30+
"""
31+
Fixture to set up and tear down static routes for IPv4 and IPv6.
2832
29-
pkt = testutils.simple_udpv6_packet(
30-
eth_dst=facts['src_router_mac'],
31-
eth_src=facts['src_host_mac'],
32-
ipv6_src=facts['dst_host_ipv6'],
33-
ipv6_dst=facts['dst_host_ipv6'],
34-
ipv6_hlim=DEFAULT_HLIM_TTL
33+
This fixture performs the following actions:
34+
1. Adds IPv4 and IPv6 static routes to the DUT.
35+
2. Verifies that the routes are added correctly.
36+
3. Yields control back to the test.
37+
4. Removes the static routes after the test is complete.
3538
36-
)
37-
logger.info("\nSend Packet:\neth_dst: {}, eth_src: {}, ipv6 ip: {}".format(
38-
facts['src_router_mac'], facts['src_host_mac'], facts['dst_host_ipv6'])
39-
)
39+
Args:
40+
duthosts: Fixture providing access to DUT hosts.
41+
enum_rand_one_per_hwsku_frontend_hostname: Fixture selecting a random frontend DUT.
42+
gather_facts: Fixture providing network facts.
43+
request: Pytest request object.
4044
41-
testutils.send(ptfadapter, facts['src_port_ids'][0], pkt)
45+
Raises:
46+
pytest.fail: If any step in adding or verifying routes fails.
4247
43-
exp_pkt = testutils.simple_udpv6_packet(
44-
eth_dst=facts['dst_host_mac'],
45-
eth_src=facts['dst_router_mac'],
46-
ipv6_src=facts['dst_host_ipv6'],
47-
ipv6_dst=facts['dst_host_ipv6'],
48-
ipv6_hlim=DEFAULT_HLIM_TTL-1
48+
Yields:
49+
None
50+
"""
51+
duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
52+
53+
# Configure IPv4 static route
54+
try:
55+
result = duthost.command("ip route add {} via {}".format(STATIC_ROUTE, gather_facts['dst_host_ipv4']))
56+
if result['rc'] != 0:
57+
raise Exception("Failed to add IPv4 static route: {}".format(result['stderr']))
58+
except Exception as e:
59+
logger.error("Error occurred while adding IPv4 static route: %s", str(e))
60+
pytest.fail("IPv4 static route addition failed")
61+
62+
# Configure IPv6 static route
63+
try:
64+
result = duthost.command("ip -6 route add {} via {}".format(STATIC_ROUTE_IPV6, gather_facts['dst_host_ipv6']))
65+
if result['rc'] != 0:
66+
raise Exception("Failed to add IPv6 static route: {}".format(result['stderr']))
67+
except Exception as e:
68+
logger.error("Error occurred while adding IPv6 static route: %s", str(e))
69+
pytest.fail("IPv6 static route addition failed")
70+
71+
# Verify IPv4 route is in the routing table
72+
73+
try:
74+
result = duthost.command("ip route show {}".format(STATIC_ROUTE))
75+
assert result['rc'] == 0, "Failed to show IPv4 static route: {}".format(result['stderr'])
76+
assert "via " + gather_facts['dst_host_ipv4'] in result["stdout"], "IPv4 static route verification failed"
77+
except Exception as e:
78+
logger.error("Error occurred while verifying IPv4 static route: %s", str(e))
79+
pytest.fail("IPv4 static route verification failed")
80+
81+
# # Verify IPv6 route is in the routing table
82+
try:
83+
result = duthost.command("ip -6 route show {}".format(STATIC_ROUTE_IPV6))
84+
assert result['rc'] == 0, "Failed to show IPv6 static route: {}".format(result['stderr'])
85+
assert "via " + gather_facts['dst_host_ipv6'] in result["stdout"], "IPv6 static route verification failed"
86+
except Exception as e:
87+
logger.error("Error occurred while verifying IPv6 static route: %s", str(e))
88+
pytest.fail("IPv6 static route verification failed")
89+
90+
# Continue with the test
91+
yield
92+
93+
# Use either individual functions
94+
delete_ipv4_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts)
95+
delete_ipv6_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts)
96+
97+
# Or use the combined function
98+
# delete_static_routes(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts)
99+
100+
101+
@pytest.fixture(autouse=True)
102+
def setup_teardown(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts):
103+
yield
104+
# Teardown - delete the static routes
105+
delete_ipv4_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts)
106+
delete_ipv6_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts)
107+
108+
109+
def delete_ipv4_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts):
110+
"""
111+
Function to delete IPv4 static route from the DUT.
112+
113+
This function performs the following actions:
114+
1. Gets the correct DUT host instance
115+
2. Deletes IPv4 static route from the DUT
116+
3. Verifies that the route is removed correctly
117+
118+
Args:
119+
duthosts: Fixture providing access to DUT hosts
120+
enum_rand_one_per_hwsku_frontend_hostname: Fixture selecting a random frontend DUT
121+
gather_facts: Fixture providing network facts
122+
123+
Raises:
124+
pytest.fail: If any step in removing or verifying route fails
125+
"""
126+
duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
127+
128+
# Check if IPv4 route exists before deleting
129+
try:
130+
check_result = duthost.command("ip route show {}".format(STATIC_ROUTE))
131+
if check_result['rc'] == 0 and check_result['stdout'].strip():
132+
# Route exists, delete it
133+
result = duthost.command("ip route del {}".format(STATIC_ROUTE))
134+
if result['rc'] != 0:
135+
raise Exception("Failed to delete IPv4 static route: {}".format(result['stderr']))
136+
logger.info("Successfully deleted IPv4 static route: {}".format(STATIC_ROUTE))
137+
else:
138+
logger.info("IPv4 static route {} not present, skipping deletion".format(STATIC_ROUTE))
139+
except Exception as e:
140+
logger.error("Error occurred while handling IPv4 static route: %s", str(e))
141+
pytest.fail("IPv4 static route operation failed")
142+
143+
# Verify IPv4 route is removed from the routing table
144+
try:
145+
result = duthost.command("ip route show {}".format(STATIC_ROUTE))
146+
assert "No such process" in result['stderr'] or result['stdout'].strip() == "", \
147+
"IPv4 static route still exists in routing table"
148+
except Exception as e:
149+
logger.error("Error occurred while verifying IPv4 static route removal: %s", str(e))
150+
pytest.fail("IPv4 static route removal verification failed")
151+
152+
153+
def delete_ipv6_static_route(duthosts, enum_rand_one_per_hwsku_frontend_hostname, gather_facts):
154+
"""
155+
Function to delete IPv6 static route from the DUT.
156+
157+
This function performs the following actions:
158+
1. Gets the correct DUT host instance
159+
2. Deletes IPv6 static route from the DUT
160+
3. Verifies that the route is removed correctly
161+
162+
Args:
163+
duthosts: Fixture providing access to DUT hosts
164+
enum_rand_one_per_hwsku_frontend_hostname: Fixture selecting a random frontend DUT
165+
gather_facts: Fixture providing network facts
166+
167+
Raises:
168+
pytest.fail: If any step in removing or verifying route fails
169+
"""
170+
duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname]
171+
172+
# Check if IPv6 route exists before deleting
173+
try:
174+
check_result = duthost.command("ip -6 route show {}".format(STATIC_ROUTE_IPV6))
175+
if check_result['rc'] == 0 and check_result['stdout'].strip():
176+
# Route exists, delete it
177+
result = duthost.command("ip -6 route del {}".format(STATIC_ROUTE_IPV6))
178+
if result['rc'] != 0:
179+
raise Exception("Failed to delete IPv6 static route: {}".format(result['stderr']))
180+
logger.info("Successfully deleted IPv6 static route: {}".format(STATIC_ROUTE_IPV6))
181+
else:
182+
logger.info("IPv6 static route {} not present, skipping deletion".format(STATIC_ROUTE_IPV6))
183+
except Exception as e:
184+
logger.error("Error occurred while handling IPv6 static route: %s", str(e))
185+
pytest.fail("IPv6 static route operation failed")
186+
187+
# Verify IPv6 route is removed from the routing table
188+
try:
189+
result = duthost.command("ip -6 route show {}".format(STATIC_ROUTE_IPV6))
190+
assert "No such process" in result['stderr'] or result['stdout'].strip() == "", \
191+
"IPv6 static route still exists in routing table"
192+
except Exception as e:
193+
logger.error("Error occurred while verifying IPv6 static route removal: %s", str(e))
194+
pytest.fail("IPv6 static route removal verification failed")
195+
196+
197+
ipv4_test_cases = [
198+
pytest.param(
199+
'Same SIP and DIP',
200+
lambda facts: facts['dst_host_ipv4'],
201+
lambda facts: facts['dst_host_ipv4'],
202+
id='ipv4_same_sip_dip'
203+
),
204+
pytest.param(
205+
'Different subnet SIP/DIP - Directly connected route',
206+
lambda facts: facts['src_host_ipv4'],
207+
lambda facts: facts['dst_host_ipv4'],
208+
id='ipv4_different_sip_dip_connectedroute'
209+
),
210+
pytest.param(
211+
'Different subnet SIP/DIP - Destination not directly connected',
212+
lambda facts: facts['src_host_ipv4'],
213+
lambda facts: STATIC_ROUTE.split('/')[0],
214+
id='ipv4_different_sip_dip_staticrouteprefix'
49215
)
50-
logger.info("\nExpect Packet:\neth_dst: {}, eth_src: {}, ipv6 ip: {}".format(
51-
facts['dst_host_mac'], facts['dst_router_mac'], facts['dst_host_ipv6'])
216+
]
217+
218+
ipv6_test_cases = [
219+
pytest.param(
220+
'Same SIP and DIP',
221+
lambda facts: facts['dst_host_ipv6'],
222+
lambda facts: facts['dst_host_ipv6'],
223+
id='ipv6_same_sip_dip'
224+
),
225+
pytest.param(
226+
'Different subnet SIP/DIP - Directly connected route',
227+
lambda facts: facts['src_host_ipv6'],
228+
lambda facts: facts['dst_host_ipv6'],
229+
id='ipv6_different_sip_dip_connectedroute'
230+
),
231+
pytest.param(
232+
'Different subnet SIP/DIP - Destination not directly connected',
233+
lambda facts: facts['src_host_ipv6'],
234+
lambda facts: STATIC_ROUTE_IPV6.split('/')[0],
235+
id='ipv6_different_sip_dip_staticrouteprefix'
52236
)
237+
]
53238

54-
testutils.verify_packet_any_port(ptfadapter, exp_pkt, facts['dst_port_ids'], timeout=WAIT_EXPECTED_PACKET_TIMEOUT)
55239

240+
@pytest.mark.parametrize('test_name, get_src_ip, get_dst_ip', ipv4_test_cases)
241+
def test_ipv4_forwarding(tbinfo, ptfadapter, gather_facts, enum_rand_one_frontend_asic_index,
242+
test_name, get_src_ip, get_dst_ip):
243+
"""Test IPv4 forwarding with various source/destination IP combinations"""
244+
ptfadapter.reinit()
245+
logger.info("Testing case: {}".format(test_name))
246+
247+
ip_src = get_src_ip(gather_facts)
248+
ip_dst = get_dst_ip(gather_facts)
56249

57-
def run_test_ipv4(ptfadapter, facts):
58-
logger.info("Running test with ipv4 packets")
59250
pkt = testutils.simple_udp_packet(
60-
eth_dst=facts['src_router_mac'],
61-
eth_src=facts['src_host_mac'],
62-
ip_src=facts['dst_host_ipv4'],
63-
ip_dst=facts['dst_host_ipv4'],
251+
eth_dst=gather_facts['src_router_mac'],
252+
eth_src=gather_facts['src_host_mac'],
253+
ip_src=ip_src,
254+
ip_dst=ip_dst,
64255
ip_ttl=DEFAULT_HLIM_TTL
65256
)
66-
logger.info("\nSend Packet:\neth_dst: {}, eth_src: {}, ipv4 ip: {}".format(
67-
facts['src_router_mac'], facts['src_host_mac'], facts['dst_host_ipv4'])
257+
logger.info("\nSend Packet:\neth_dst: {}, eth_src: {}, ip_src: {}, ip_dst: {}".format(
258+
gather_facts['src_router_mac'], gather_facts['src_host_mac'],
259+
ip_src, ip_dst)
68260
)
69261

70-
testutils.send(ptfadapter, facts['src_port_ids'][0], pkt)
262+
testutils.send(ptfadapter, gather_facts['src_port_ids'][0], pkt)
71263

72264
exp_pkt = testutils.simple_udp_packet(
73-
eth_dst=facts['dst_host_mac'],
74-
eth_src=facts['dst_router_mac'],
75-
ip_src=facts['dst_host_ipv4'],
76-
ip_dst=facts['dst_host_ipv4'],
265+
eth_dst=gather_facts['dst_host_mac'],
266+
eth_src=gather_facts['dst_router_mac'],
267+
ip_src=ip_src,
268+
ip_dst=ip_dst,
77269
ip_ttl=DEFAULT_HLIM_TTL-1
78270
)
79-
logger.info("\nExpect Packet:\neth_dst: {}, eth_src: {}, ipv4 ip: {}".format(
80-
facts['dst_host_mac'], facts['dst_router_mac'], facts['dst_host_ipv4'])
271+
logger.info(
272+
"\nExpect Packet:\neth_dst: {}, eth_src: {}, ip_src: {}, ip_dst: {}".format(
273+
gather_facts['dst_host_mac'], gather_facts['dst_router_mac'],
274+
ip_src, ip_dst)
81275
)
82276

83-
testutils.verify_packet_any_port(ptfadapter, exp_pkt, facts['dst_port_ids'], timeout=WAIT_EXPECTED_PACKET_TIMEOUT)
277+
try:
278+
testutils.verify_packet_any_port(ptfadapter, exp_pkt,
279+
gather_facts['dst_port_ids'],
280+
timeout=WAIT_EXPECTED_PACKET_TIMEOUT)
281+
except AssertionError as e:
282+
logger.error("Expected packet was not received")
283+
pytest.fail("Test case failed: {} - {}".format(test_name, str(e)))
284+
285+
logger.info("Test case passed: {}\n".format(test_name))
84286

85287

86-
def test_dip_sip(tbinfo, ptfadapter, gather_facts, enum_rand_one_frontend_asic_index):
288+
@pytest.mark.parametrize('test_name, get_src_ip, get_dst_ip', ipv6_test_cases)
289+
def test_ipv6_forwarding(tbinfo, ptfadapter, gather_facts, enum_rand_one_frontend_asic_index,
290+
test_name, get_src_ip, get_dst_ip):
291+
"""Test IPv6 forwarding with various source/destination IP combinations"""
87292
ptfadapter.reinit()
88-
run_test_ipv4(ptfadapter, gather_facts)
89-
run_test_ipv6(ptfadapter, gather_facts)
293+
294+
logger.info("Testing case: {}".format(test_name))
295+
296+
ipv6_src = get_src_ip(gather_facts)
297+
ipv6_dst = get_dst_ip(gather_facts)
298+
299+
pkt = testutils.simple_udpv6_packet(
300+
eth_dst=gather_facts['src_router_mac'],
301+
eth_src=gather_facts['src_host_mac'],
302+
ipv6_src=ipv6_src,
303+
ipv6_dst=ipv6_dst,
304+
ipv6_hlim=DEFAULT_HLIM_TTL
305+
)
306+
logger.info("\nSend Packet:\neth_dst: {}, eth_src: {}, ipv6_src: {}, ipv6_dst: {}".format(
307+
gather_facts['src_router_mac'], gather_facts['src_host_mac'],
308+
ipv6_src, ipv6_dst)
309+
)
310+
311+
testutils.send(ptfadapter, gather_facts['src_port_ids'][0], pkt)
312+
313+
exp_pkt = testutils.simple_udpv6_packet(
314+
eth_dst=gather_facts['dst_host_mac'],
315+
eth_src=gather_facts['dst_router_mac'],
316+
ipv6_src=ipv6_src,
317+
ipv6_dst=ipv6_dst,
318+
ipv6_hlim=DEFAULT_HLIM_TTL-1
319+
)
320+
logger.info(
321+
"\nExpect Packet:\neth_dst: {}, eth_src: {}, ipv6_src: {}, ipv6_dst: {}".format(
322+
gather_facts['dst_host_mac'], gather_facts['dst_router_mac'],
323+
ipv6_src, ipv6_dst)
324+
)
325+
326+
try:
327+
testutils.verify_packet_any_port(ptfadapter, exp_pkt,
328+
gather_facts['dst_port_ids'],
329+
timeout=WAIT_EXPECTED_PACKET_TIMEOUT)
330+
except AssertionError as e:
331+
logger.error("Expected packet was not received")
332+
pytest.fail("Test case failed: {} - {}".format(test_name, str(e)))
333+
logger.info("Test case passed: {}\n".format(test_name))

0 commit comments

Comments
 (0)