Comment 13 for bug 1937110

Revision history for this message
Mauricio Faria de Oliveira (mfo) wrote :

Reproducer with DHCP server/client on LXD. [Focal]

Bridge
---

 sudo ip link add focalbr type bridge
 sudo ip link set focalbr up

LXD container for DHCP server with classless static routes option
---

 lxc init ubuntu:focal focal-dhcpd
 lxc config device add focal-dhcpd eth0 nic nictype=bridged parent=focalbr
 lxc config device add focal-dhcpd eth1 nic nictype=bridged parent=lxdbr0

 lxc start focal-dhcpd
 lxc shell focal-dhcpd

 dhclient eth1

...

 ip addr add 10.11.12.13/24 dev eth0

 apt install -y isc-dhcp-server

 echo 'INTERFACESv4="eth0"' >>/etc/default/isc-dhcp-server

 cat <<EOF >>/etc/dhcp/dhcpd.conf
 option rfc3442-classless-static-routes code 121 = array of integer 8;

 subnet 10.11.12.0 netmask 255.255.255.0 {

   range 10.11.12.100 10.11.12.110;

   option routers 10.11.12.13;

   option rfc3442-classless-static-routes
     0, 10, 11, 12, 200,
     8, 1, 10, 11, 12, 208,
     16, 2, 1, 10, 11, 12, 216,
     24, 3, 2, 1, 10, 11, 12, 224,
     32, 4, 3, 2, 1, 10, 11, 12, 232;
 }
 EOF

 systemctl restart isc-dhcp-server.service

LXD VM for DHCP client
---

 lxc init ubuntu:focal focal-dhclient --vm
 lxc config device add focal-dhclient eth0 nic nictype=bridged parent=focalbr
 # no regular lxdbr0 bridge / internet access.

 lxc start focal-dhclient
 lxc shell focal-dhclient

 # ip link
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff

 # ip addr
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
     inet6 ::1/128 scope host
        valid_lft forever preferred_lft forever
 2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff
     inet 10.11.12.101/24 brd 10.11.12.255 scope global dynamic enp5s0
        valid_lft 582sec preferred_lft 582sec
     inet6 fe80::216:3eff:fe36:6bc8/64 scope link
        valid_lft forever preferred_lft forever

 # ip route
 default via 10.11.12.200 dev enp5s0 proto dhcp src 10.11.12.101 metric 100
 1.0.0.0/8 via 10.11.12.208 dev enp5s0 proto dhcp src 10.11.12.101 metric 100
 2.1.0.0/16 via 10.11.12.216 dev enp5s0 proto dhcp src 10.11.12.101 metric 100
 3.2.1.0/24 via 10.11.12.224 dev enp5s0 proto dhcp src 10.11.12.101 metric 100
 4.3.2.1 via 10.11.12.232 dev enp5s0 proto dhcp src 10.11.12.101 metric 100
 10.11.12.0/24 dev enp5s0 proto kernel scope link src 10.11.12.101

Ok, all good from booted system's perspective.

Let's check at initramfs time, manually.

The classless routes aren't added if you run dhclient at the current version.

 cat <<EOF >/etc/default/grub.d/99-grub-initrd.cfg
 GRUB_FORCE_PARTUUID=
 GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT console=ttyS0 break=bottom"
 EOF

 update-grub && poweroff

 lxc start --console focal-dhclient

 (initramfs) ip addr
 1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 2: enp5s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff

 (initramfs) ip route
 (initramfs)

 (initramfs) dhclient enp5s0
 sed: /etc/resolv.conf: No such file or directory

 (initramfs) ip addr
 1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff
     inet 10.11.12.102/24 brd 10.11.12.255 scope global enp5s0
        valid_lft forever preferred_lft forever
     inet6 fe80::216:3eff:fe36:6bc8/64 scope link
        valid_lft forever preferred_lft forever

 (initramfs) ip route
 10.11.12.0/24 dev enp5s0 scope link src 10.11.12.102

 (initramfs) dhclient -r enp5s0
 (initramfs) exit

Test package (download it from dhcp server container)
---

@ focal-dhcpd:
 add-apt-repository -y ppa:mfo/lp1926139
 apt download isc-dhcp-client
 python3 -m http.server

@ focal-dhclient:

 wget 10.11.12.13:8000/isc-dhcp-client_4.4.1-2.1ubuntu5.20.04.5_amd64.deb
 dpkg -i isc-dhcp-client_4.4.1-2.1ubuntu5.20.04.5_amd64.deb

Update the initramfs:

 # lsinitramfs /boot/initrd.img-$(uname -r) | grep dhclient-exit-hooks.d
 #

 update-initramfs -u

 # lsinitramfs /boot/initrd.img-$(uname -r) | grep dhclient-exit-hooks.d
 etc/dhcp/dhclient-exit-hooks.d
 etc/dhcp/dhclient-exit-hooks.d/rfc3442-classless-routes

 # poweroff

Try again:

 lxc start --console focal-dhclient

The classless routes ARE added if you run dhclient with the test package.

 (initramfs) ip addr
 1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 2: enp5s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff

 (initramfs) ip route
 (initramfs)

 (initramfs) dhclient enp5s0
 sed: /etc/resolv.conf: No such file or directory

 (initramfs) ip addr
 1: lo: <LOOPBACK> mtu 65536 qdisc noop qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
 2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff
     inet 10.11.12.103/24 brd 10.11.12.255 scope global enp5s0
        valid_lft forever preferred_lft forever
     inet6 fe80::216:3eff:fe36:6bc8/64 scope link
        valid_lft forever preferred_lft forever

 (initramfs) ip route
 default via 10.11.12.200 dev enp5s0
 1.0.0.0/8 via 10.11.12.208 dev enp5s0
 2.1.0.0/16 via 10.11.12.216 dev enp5s0
 3.2.1.0/24 via 10.11.12.224 dev enp5s0
 4.3.2.1 via 10.11.12.232 dev enp5s0
 10.11.12.0/24 dev enp5s0 scope link src 10.11.12.103

 (initramfs) dhclient -r enp5s0
 (initramfs) exit

Now let's check that `ip=dhcp` is working (break=init stops after it runs):

 cat <<EOF >/etc/default/grub.d/99-grub-initrd.cfg
 GRUB_FORCE_PARTUUID=
 GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT console=ttyS0 ip=dhcp break=init"
 EOF

 update-grub && poweroff

 lxc start --console focal-dhclient

And yes, it is.

 (initramfs) ip addr
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
     inet6 ::1/128 scope host
        valid_lft forever preferred_lft forever
 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
     link/ether 00:16:3e:36:6b:c8 brd ff:ff:ff:ff:ff:ff
     inet 10.11.12.104/24 brd 10.11.12.255 scope global eth0
        valid_lft forever preferred_lft forever
     inet6 fe80::216:3eff:fe36:6bc8/64 scope link
        valid_lft forever preferred_lft forever

 (initramfs) ip route
 default via 10.11.12.13 dev eth0
 1.0.0.0/8 via 10.11.12.208 dev eth0
 2.1.0.0/16 via 10.11.12.216 dev eth0
 3.2.1.0/24 via 10.11.12.224 dev eth0
 4.3.2.1 via 10.11.12.232 dev eth0
 10.11.12.0/24 dev eth0 scope link src 10.11.12.104
 (initramfs)

Clean up:

 lxc stop ...
 lxc delete ...
 sudo ip link del focalbr