Skip to content

Commit

Permalink
doc,test: clarify relationship between DHCP option 3 and 121
Browse files Browse the repository at this point in the history
Signed-off-by: Joachim Wiberg <[email protected]>
  • Loading branch information
troglobit committed Oct 28, 2024
1 parent dbf0fd2 commit 710616f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 27 deletions.
14 changes: 10 additions & 4 deletions doc/networking.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
27 changes: 17 additions & 10 deletions test/case/infix_dhcp/dhcp_routes/Readme.adoc
Original file line number Diff line number Diff line change
@@ -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[]
Expand All @@ -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


<<<
Expand Down
34 changes: 21 additions & 13 deletions test/case/infix_dhcp/dhcp_routes/test.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#!/usr/bin/env python3
"""
DHCP option 121 vs option 3
"""DHCP option 121 vs option 3
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.
Verify DHCP option 121 (static routes) is used over option 3 and that the
routes exist in the operational datastore.
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.
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.
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
Expand All @@ -22,11 +27,10 @@
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
Expand All @@ -52,6 +56,9 @@
}
})

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": [{
Expand All @@ -66,17 +73,18 @@

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))

Expand Down

0 comments on commit 710616f

Please sign in to comment.