Files
infix/test/case/routing/route_pref_dhcp/test.py
T
Joachim Wiberg 1bbd80d8c7 test: drop leading ietf/infix prefix from directories
Let's drop the leading IETF or Infix prefixes from tests.  Initially the
idea was to mimnic the YANG models, but it's difficult to navigate and
does not provide any real benefit to developers or end-users.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-11-20 20:23:23 +01:00

189 lines
7.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Route preference: DHCP vs Static
This test configures a device with both a DHCP-acquired route on a
dedicated interface and a static route to the same destination on
another interface.
Initially, DHCP is preferred over Static. Afterwards, the static
route takes precedence by adjusting the routing preference value
to the one lower than DHCP.
"""
import infamy
import infamy.route as route
import infamy.dhcp
from infamy.util import until, parallel
from infamy.netns import IsolatedMacVlans
def configure_interface(name, ip=None, prefix_length=None, forwarding=True, dhcp=False):
interface_config = {
"name": name,
"enabled": True,
"ipv4": {
"forwarding": forwarding,
"address": []
}
}
if ip and prefix_length:
interface_config["ipv4"]["address"].append({"ip": ip, "prefix-length": prefix_length})
if dhcp:
interface_config["ipv4"]["infix-dhcp-client:dhcp"] = {
"option": [
{"id": "broadcast"},
{"id": "dns-server"},
{"id": "domain"},
{"id": "hostname"},
{"id": "ntp-server"},
{"id": "router"},
{"id": "netmask"}
],
"route-preference": 5
}
return interface_config
def config_target1(target, data1, data2, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
configure_interface(data1, dhcp=True),
configure_interface(data2, "192.168.30.1", 24),
configure_interface(link, "192.168.50.1", 24)
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "0.0.0.0/0",
"next-hop": {"next-hop-address": "192.168.50.2"},
"route-preference": 120
}]
}
}
}
]
}
}
}
})
def config_target2(target, data, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
configure_interface(data, "192.168.20.2", 24),
configure_interface(link, "192.168.50.2", 24),
configure_interface("lo", "192.168.200.1", 32)
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "0.0.0.0/0",
"next-hop": {"next-hop-address": "192.168.50.1"}
}]
}
}
}
]
}
}
}
})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
env = infamy.Env()
R1 = env.attach("R1", "mgmt")
R2 = env.attach("R2", "mgmt")
with test.step("Configure targets. Assign higher priority to the dhcp route"):
_, R1data1 = env.ltop.xlate("R1", "data1")
_, R1data2 = env.ltop.xlate("R1", "data2")
_, R1link = env.ltop.xlate("R1", "link")
_, R2data = env.ltop.xlate("R2", "data")
_, R2link = env.ltop.xlate("R2", "link")
parallel(config_target1(R1, R1data1, R1data2, R1link),
config_target2(R2, R2data, R2link))
_, hport_data12 = env.ltop.xlate("PC", "data12")
ns0 = infamy.IsolatedMacVlan(hport_data12).start()
ns0.addip("192.168.30.3", prefix_length=24)
ns0.addroute("default", "192.168.30.1")
_, hport_data11 = env.ltop.xlate("PC", "data11")
_, hport_data2 = env.ltop.xlate("PC", "data2")
ifmap={ hport_data11: "a", hport_data2: "b" }
ns1 = IsolatedMacVlans(ifmap, False).start()
ns1.addip(ifname="b", addr="192.168.20.3", prefix_length=24)
ns1.addroute("192.168.200.1/32", "192.168.20.2")
ns1.addip(ifname="a", addr="192.168.10.3", prefix_length=24)
ns1.runsh("ip route add default dev a")
with infamy.dhcp.Server(netns=ns1, ip="192.168.10.1", netmask="255.255.255.0", router="192.168.10.3", iface="a"):
with test.step("Wait for DHCP and static routes"):
print("Waiting for DHCP and static routes...")
until(lambda: route.ipv4_route_exist(R1, "0.0.0.0/0", proto="ietf-routing:static", pref=5), attempts=200)
until(lambda: route.ipv4_route_exist(R1, "0.0.0.0/0", proto="ietf-routing:static", pref=120), attempts=200)
with test.step("Verify connectivity from PC:data12 to R2:lo via DHCP"):
dhcp_route_active = route.ipv4_route_exist(R1, "0.0.0.0/0", pref=5, active_check=True)
assert dhcp_route_active, "Failed to activate DHCP route: Expected DHCP-acquired route not found."
ns0.must_reach("192.168.200.1")
with test.step("Assign higher priority to the static route"):
R1.put_config_dicts({
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "0.0.0.0/0",
"next-hop": {"next-hop-address": "192.168.50.2"},
"route-preference": 1
}]
}
}
}
]
}
}
}
})
with test.step("Verify connectivity from PC:data12 to R2:lo via static route"):
ns0.must_reach("192.168.200.1")
static_route_active = route.ipv4_route_exist(R1, "0.0.0.0/0", pref=1, active_check=True)
assert static_route_active, "Static route activation failed: Verify route-preference adjustment on R1."
test.succeed()