doc,test: clarify relationship between DHCP option 3 and 121

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2024-10-28 11:04:49 +01:00
parent dbf0fd2514
commit 710616f8c4
3 changed files with 48 additions and 27 deletions
+10 -4
View File
@@ -585,6 +585,9 @@ Multiple address assignment methods are available:
| link-local | infix-ip | Auto-assignment of IPv4 address in 169.254.x.x/16 range |
| dhcp | infix-dhcp-client | Assignment of IPv4 address by DHCP server, e.g., *10.0.1.1/24* |
> **Note:** DHCP address method is only available for *LAN* interfaces
> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.)
Supported DHCP (request) options, configurability (Cfg) and defaults,
are listed below. Configurable options can be disabled on a per client
interface basis, some options, like `clientid` and option 81, are
@@ -616,8 +619,10 @@ client is not enabled, any NTP servers provided by the DHCP server will
be ignored. For details on how to enable the NTP client, see the
[NTP Client Configuration](system.md#ntp-client-configuration) section.
> **Note:** DHCP address method is only available for *LAN* interfaces
> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.)
> **Note:** as per [RFC3442][4], if the DHCP server returns both a
> Classless Static Routes option (121) and Router option (3), the
> DHCP client *must* ignore the latter.
### IPv6 Address Assignment
@@ -1059,7 +1064,7 @@ This CLI example show the IPv6 routing table.
#### Route Preference
The operating system leverages FRRouting ([Frr][4]) as routing engine
The operating system leverages FRRouting ([Frr][0]) as routing engine
for both static and dynamic routing. Even routes injected from a DHCP
client, and IPv4 link-local (IPv4) routes, are injected into Frr to let
it weigh all routes before installing them into the kernel routing table
@@ -1113,7 +1118,8 @@ currently supported, namely `ipv4` and `ipv6`.
[1]: https://www.rfc-editor.org/rfc/rfc8343
[2]: https://www.rfc-editor.org/rfc/rfc8344
[3]: https://www.rfc-editor.org/rfc/rfc8981
[4]: https://frrouting.org/
[4]: https://www.rfc-editor.org/rfc/rfc3442
[0]: https://frrouting.org/
[^1]: Please note, link aggregates are not yet supported in Infix.
[^2]: Link-local IPv6 addresses are implicitly enabled when enabling
+17 -10
View File
@@ -1,12 +1,18 @@
=== DHCP option 121 vs option 3
==== Description
Verify DHCP option 121 (static routes) is used over option 3 and that the
routes exist in the operational datastore.
Verify that DHCP option 121 (classless static routes) is used over the
older option 3 (default gateway) in the DHCP client, when both are sent
by the server, see RFC3442. Use the routing RIB in the operational
datastore to verify.
Installing unrelated routes from a DHCP server should not affect already
existing routes. To verify this, a canary route is set up in the client
before initiating DHCP. This canary route does not need to be reachable
before a DHCP lease has been acquired.
Installing routes from a DHCP server should not affect already existing
(static) routes. To verify this, a static canary route (20.0.0.0/24 via
192.168.0.2) is installed before starting the DHCP client. As a twist,
this canary route has a next-hop (192.168.0.2) which is not reachable
until a DHCP lease has been acquired.
The DHCP server is set up to hand out both a default router (option 3)
via 192.168.0.1 and a default route (option 121) via 192.168.0.254.
==== Topology
ifdef::topdoc[]
@@ -21,10 +27,11 @@ image::topology.svg[DHCP option 121 vs option 3 topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Setting up client
. Verify 'client' has a route to 10.0.0.0/24 via 192.168.0.254
. Verify 'client' has a default route via 192.168.0.254
. Verify 'client' has a route to 20.0.0.0/24 via 192.168.0.2
. Setting up canary route, 20.0.0.0/24 via 192.168.0.2
. Enabling DHCP client, allow option 3 and 121
. Verify 'client' has a route 10.0.0.0/24 via 192.168.0.254 (option 121)
. Verify 'client' has default route via 192.168.0.254 (not use option 3)
. Verify 'client' still has canary route to 20.0.0.0/24 via 192.168.0.2
<<<
+21 -13
View File
@@ -1,14 +1,19 @@
#!/usr/bin/env python3
"""
DHCP option 121 vs option 3
"""DHCP option 121 vs option 3
Verify DHCP option 121 (static routes) is used over option 3 and that the
routes exist in the operational datastore.
Verify that DHCP option 121 (classless static routes) is used over the
older option 3 (default gateway) in the DHCP client, when both are sent
by the server, see RFC3442. Use the routing RIB in the operational
datastore to verify.
Installing unrelated routes from a DHCP server should not affect already
existing routes. To verify this, a canary route is set up in the client
before initiating DHCP. This canary route does not need to be reachable
before a DHCP lease has been acquired.
Installing routes from a DHCP server should not affect already existing
(static) routes. To verify this, a static canary route (20.0.0.0/24 via
192.168.0.2) is installed before starting the DHCP client. As a twist,
this canary route has a next-hop (192.168.0.2) which is not reachable
until a DHCP lease has been acquired.
The DHCP server is set up to hand out both a default router (option 3)
via 192.168.0.1 and a default route (option 121) via 192.168.0.254.
"""
import infamy
@@ -22,11 +27,10 @@ with infamy.Test() as test:
CANARY = '20.0.0.0/24'
CANHOP = '192.168.0.2'
with test.step("Setting up client"):
with test.step("Setting up canary route, 20.0.0.0/24 via 192.168.0.2"):
env = infamy.Env()
client = env.attach("client", "mgmt")
_, host = env.ltop.xlate("host", "data")
_, port = env.ltop.xlate("client", "data")
# Install canary route to smoke out any regressions in
# how the DHCP client installs routes in the kernel FIB
@@ -52,6 +56,9 @@ with infamy.Test() as test:
}
})
with test.step("Enabling DHCP client, allow option 3 and 121"):
_, port = env.ltop.xlate("client", "data")
client.put_config_dict("infix-dhcp-client", {
"dhcp-client": {
"client-if": [{
@@ -66,17 +73,18 @@ with infamy.Test() as test:
with infamy.IsolatedMacVlan(host) as netns:
netns.addip("192.168.0.1")
print(f"Start DHCP server {ROUTER} with option 3 and 121")
with infamy.dhcp.Server(netns, prefix=PREFIX, router=ROUTER):
with test.step("Verify 'client' has a route to 10.0.0.0/24 via 192.168.0.254"):
with test.step("Verify 'client' has a route 10.0.0.0/24 via 192.168.0.254 (option 121)"):
print("Verify client use classless routes, option 121")
until(lambda: route.ipv4_route_exist(client, PREFIX, ROUTER))
with test.step("Verify 'client' has a default route via 192.168.0.254"):
with test.step("Verify 'client' has default route via 192.168.0.254 (not use option 3)"):
print("Verify client did *not* use option 3")
if route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER):
test.fail()
with test.step("Verify 'client' has a route to 20.0.0.0/24 via 192.168.0.2"):
with test.step("Verify 'client' still has canary route to 20.0.0.0/24 via 192.168.0.2"):
until(lambda: route.ipv4_route_exist(client, CANARY,
CANHOP, pref=250))