RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1998448 - edk2 OVMF continues to request DHCPv6 address despite receiving option: 13 status 1 address in use
Summary: edk2 OVMF continues to request DHCPv6 address despite receiving option: 13 st...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: dnsmasq
Version: 8.2
Hardware: Unspecified
OS: Unspecified
urgent
high
Target Milestone: rc
: 8.6
Assignee: Petr Menšík
QA Contact: Petr Sklenar
URL:
Whiteboard:
Depends On:
Blocks: 1711384 1958392 2002871 2007642 2028704 2136787
TreeView+ depends on / blocked
 
Reported: 2021-08-27 09:05 UTC by Harald Jensås
Modified: 2022-10-21 10:33 UTC (History)
18 users (show)

Fixed In Version: dnsmasq-2.79-20.el8
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
: 2002871 (view as bug list)
Environment:
Last Closed: 2022-05-10 13:49:02 UTC
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
Ttraffic capture of DHCPv6 traffic with error recovery patch from comment #20 (5.58 KB, application/vnd.tcpdump.pcap)
2021-09-15 18:00 UTC, Harald Jensås
no flags Details
Traffice capture Tianocore edk2-ovmf with Kea (2.25 KB, application/vnd.tcpdump.pcap)
2021-09-16 21:10 UTC, Harald Jensås
no flags Details
Traffic capture with dnsmasq patch to reply with new address in request (2.14 KB, application/vnd.tcpdump.pcap)
2021-09-17 11:11 UTC, Harald Jensås
no flags Details
dnsmasq change proposal (3.75 KB, patch)
2021-09-24 11:09 UTC, Petr Menšík
no flags Details | Diff
option6:client-arch support, optional (897 bytes, patch)
2021-09-24 11:12 UTC, Petr Menšík
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RHELPLAN-95409 0 None None None 2021-08-27 09:07:04 UTC
Red Hat Product Errata RHBA-2022:1839 0 None None None 2022-05-10 13:49:18 UTC
TianoCore 1519 0 None None None 2021-09-10 16:09:50 UTC

Description Harald Jensås 2021-08-27 09:05:37 UTC
Description of problem:

70% failure rate when network booting using IPv6.

The EFI firmware DHCPv6 client is requesting multiple IPv6 address allocations, using different IAID's in the DHCPv6 SOLICIT message.
When the DHCPSOLICIT messages arrive at the service the server will advertise an address to the client.
In some cases the two DHCPSOLICIT's reach the server prior to any DHCPREQEST/DHCPREPLY sequence, since the server did not yet complete the address allocation it happens that it will ADVERTISE the same IPv6 address to both solicits.
Following that, the first DHCPREQUEST that arrives to the server succedes and a succesfull DHCPREPLY is sent back to the client.
NOTE: The advertised IPv6 address is now allocated and tied to the IAID of the DHCPREQEST that arrived/"was processed first".
When the second address request with the 2nd IAID comes in, the address in the request is already allocated. So the DHCP server responds with "no addresses available". The DHCP server correctly sets flags to tell the client the address you requested is already used:
 Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 nest size: 16 option: 13 status  1 address in use
 Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 24 option: 13 status  2 no addresses available

Despite the server responding to the client with "address in use", the edk2 EFI firmware continues to REQUEST the address over and over until it finally gives up and fails the network boot.



Version-Release number of selected component (if applicable):
edk2-ovmf-20190829git37eef91017ad-9.el8.noarch

How reproducible:
Close to 100% when using "dhcp-sequential-ip" option in dnsmasq.


Steps to Reproduce:
1. Configure dnsmasq as DHCPv6 server providing boot options.

FILE: dnsmasq.conf
------------------
log-dhcp
port=0
interface=br-ctlplane

dhcp-range=set:ctlplane-subnet,2620:dead:beef:4::aaaa,2620:dead:beef:4::afff,64,10m
dhcp-option-force=tag:ctlplane-subnet,option:mtu,1500
dhcp-range=set:leaf1,2620:dead:beef:5::aaaa,2620:dead:beef:5::afff,64,10m
dhcp-option-force=tag:leaf1,option:mtu,1500
dhcp-range=set:leaf2,2620:dead:beef:6::aaaa,2620:dead:beef:6::afff,64,10m
dhcp-option-force=tag:leaf2,option:mtu,1500
dhcp-sequential-ip
dhcp-match=ipxe,175
dhcp-match=set:efi,option:client-arch,7
dhcp-match=set:efi,option:client-arch,9
dhcp-match=set:efi,option:client-arch,11
# dhcpv6s for Client System Architecture Type (61)
dhcp-match=set:efi6,option6:61,0007
dhcp-match=set:efi6,option6:61,0009
dhcp-match=set:efi6,option6:61,0011
dhcp-userclass=set:ipxe6,iPXE
# Client is already running iPXE; move to next stage of chainloading
dhcp-boot=tag:ipxe,http://[2620:dead:beef:4::1]:8088/inspector.ipxe
dhcp-option=tag:ipxe6,option6:bootfile-url,http://[2620:dead:beef:4::1]:8088/inspector.ipxe
# Client is PXE booting over EFI without iPXE ROM; send EFI version of iPXE chainloader
dhcp-boot=tag:efi,tag:!ipxe,ipxe.efi
dhcp-option=tag:efi6,tag:!ipxe6,option6:bootfile-url,tftp://[2620:dead:beef:4::1]/ipxe.efi
# Client is running PXE over BIOS; send BIOS version of iPXE chainloader
dhcp-boot=undionly.kpxe,localhost.localdomain,2620:dead:beef:4::1

dhcp-hostsdir=/var/lib/ironic-inspector/dhcp-hostsdir
------------------

2. Create libvirt VM's using edk2-ovmf firmware.
3. Attempt to boot the VM using the NIC as boot device.

Actual results:
VM fails to boot of network.

Expected results:
VM should be able to boot from network.
When the DHCPv6 client recieves "option: 13 status  1 address in use" in the DHCPREPLY after a DHCPREQUEST it should restart with a DHCPSOLICIT again, instead of continously try to grab the address that is already used and tied to a different IAID.

Additional info:
     
Following an annotated dnsmasq log showing the issue:

    ## DHCPSOLICIT/DHCPADVERTISE IAID - 2129393274 - Advertised: 2620:dead:beef:5::aaaa
     
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 available DHCP range: 2620:dead:beef:5::aaaa -- 2620:dead:beef:5::afff
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 vendor class: 343
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 client MAC address: 52:54:00:26:40:a0
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 DHCPSOLICIT(br-ctlplane) 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 DHCPADVERTISE(br-ctlplane) 2620:dead:beef:5::aaaa 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server,
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 requested options: 16:vendor-class
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 tags: leaf1, known, efi6, dhcpv6, br-ctlplane
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size: 18 option:  1 client-id  00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3...
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size: 14 option:  2 server-id  00:01:00:01:28:ba:dc:65:52:54:00:07:42:52
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size: 40 option:  3 ia-na  IAID=2129393274 T1=300 T2=525
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 nest size: 24 option:  5 iaaddr  2620:dead:beef:5::aaaa PL=600 VL=600
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size:  9 option: 13 status  0 success
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size:  1 option:  7 preference  0
    Aug 27 08:36:02 dnsmasq-dhcp[7]: 16479013 sent size: 37 option: 59 bootfile-url  tftp://[2620:dead:beef:4::1]/ipxe.efi
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 available DHCP range: 2620:dead:beef:5::aaaa -- 2620:dead:beef:5::afff
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 client MAC address: 52:54:00:26:40:a0
     
    ## DHCPSOLICIT/DHCPADVERTISE IAID - 1712781046 - Advertised: 2620:dead:beef:5::aaaa
     
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 DHCPSOLICIT(br-ctlplane) 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 DHCPADVERTISE(br-ctlplane) 2620:dead:beef:5::aaaa 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 requested options: 23:dns-server
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 tags: leaf1, known, dhcpv6, br-ctlplane
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 sent size: 18 option:  1 client-id  00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3...
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 sent size: 14 option:  2 server-id  00:01:00:01:28:ba:dc:65:52:54:00:07:42:52
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 sent size: 40 option:  3 ia-na  IAID=1712781046 T1=300 T2=525
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 nest size: 24 option:  5 iaaddr  2620:dead:beef:5::aaaa PL=600 VL=600
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 sent size:  9 option: 13 status  0 success
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16544549 sent size:  1 option:  7 preference  0
     
    DHCPREQUEST/DHCPREPLY IAID - 1712781046 - Allocates: 2620:dead:beef:5::aaaa
     
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 available DHCP range: 2620:dead:beef:5::aaaa -- 2620:dead:beef:5::afff
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 client MAC address: 52:54:00:26:40:a0
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 DHCPREQUEST(br-ctlplane) 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 DHCPREPLY(br-ctlplane) 2620:dead:beef:5::aaaa 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 requested options: 23:dns-server
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 tags: leaf1, known, dhcpv6, br-ctlplane
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 sent size: 18 option:  1 client-id  00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3...
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 sent size: 14 option:  2 server-id  00:01:00:01:28:ba:dc:65:52:54:00:07:42:52
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 sent size: 40 option:  3 ia-na  IAID=1712781046 T1=300 T2=525
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 nest size: 24 option:  5 iaaddr  2620:dead:beef:5::aaaa PL=600 VL=600
    Aug 27 08:36:03 dnsmasq-dhcp[7]: 16610085 sent size:  9 option: 13 status  0 success
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 available DHCP range: 2620:dead:beef:5::aaaa -- 2620:dead:beef:5::afff
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 vendor class: 343
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 client MAC address: 52:54:00:26:40:a0
     
    # DHCPREQUEST IADI 2129393274 - asks for address 2620:dead:beef:5::aaaa which is now used by IAID 1712781046
     
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 DHCPREQUEST(br-ctlplane) 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 DHCPREPLY(br-ctlplane) 00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3:27:98:75:fe no addresses available
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server,
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 requested options: 16:vendor-class
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 tags: known, efi6, dhcpv6, br-ctlplane
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 18 option:  1 client-id  00:04:a0:f9:67:88:01:c3:4b:4e:a7:86:8e:e3...
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 14 option:  2 server-id  00:01:00:01:28:ba:dc:65:52:54:00:07:42:52
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 32 option:  3 ia-na  IAID=2129393274 T1=4294967295 T2=4294967295
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 nest size: 16 option: 13 status  1 address in use
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 24 option: 13 status  2 no addresses available
    Aug 27 08:36:07 dnsmasq-dhcp[7]: 16675621 sent size: 37 option: 59 bootfile-url  tftp://[2620:dead:beef:4::1]/ipxe.efi

Comment 18 Gerd Hoffmann 2021-09-13 09:25:03 UTC
See also: bug 1810172

Comment 20 Gerd Hoffmann 2021-09-14 12:23:44 UTC
Hmm, trying to improve the error handling doesn't have the intended effect.

--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
@@ -2261,6 +2261,20 @@ Dhcp6HandleReplyMsg (
       }
       break;
 
+    case Dhcp6StsNoAddrsAvail:
+      DEBUG ((DEBUG_INFO, "%a: Dhcp6StsNoAddrsAvail (%d)\n", __FUNCTION__,
+              Instance->IaCb.Ia->State));
+      if (Instance->IaCb.Ia->State == Dhcp6Requesting) {
+        //
+        // dnsmasq changed its mind, try start over
+        //
+        Status = Dhcp6InitSolicitMsg (Instance);
+        if (EFI_ERROR (Status)) {
+          return  Status;
+        }
+      }
+      break;
+
     case Dhcp6StsNotOnLink:
       if (Instance->IaCb.Ia->State == Dhcp6Confirming) {
         //

14:17:39 DEBUG| [stderr] + exec /usr/sbin/dnsmasq --no-daemon --leasefile-ro --log-dhcp --interface net0 '--dhcp-host=52:54:00:12:34:56,qemu.network,192.168.42.200,[fd42::200/126]' --dhcp-range=192.168.42.10,192.168.42.99 --dhcp-range=fd42::10,fd42::ff --dhcp-boot=/404 '--dhcp-option=option6:bootfile-url,tftp://[fd42::1]/EFI/BOOT/grub.efi' --enable-tftp --tftp-root=/home/kraxel/projects/edk2-tests/buildroot/initrd-x86_64
[ ... ]
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 available DHCP range: fd42::10 -- fd42::ff
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 vendor class: 343
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 client MAC address: 52:54:00:12:34:56
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 DHCPSOLICIT(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 DHCPADVERTISE(net0) fd42::200 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 qemu
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server, 
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 requested options: 16:vendor-class
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 tags: known, dhcpv6, net0
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size: 40 option:  3 ia-na  IAID=1917410942 T1=43200 T2=75600
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 nest size: 24 option:  5 iaaddr  fd42::200 PL=86400 VL=86400
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size:  9 option: 13 status  0 success
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size:  1 option:  7 preference  0
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size: 34 option: 59 bootfile-url  tftp://[fd42::1]/EFI/BOOT/grub.efi
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size: 16 option: 23 dns-server  fd42::1
14:17:48 DEBUG| [stderr] dnsmasq-dhcp: 14547842 sent size:  6 option: 39 FQDN  qemu
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 available DHCP range: fd42::10 -- fd42::ff
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 client MAC address: 52:54:00:12:34:56
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 DHCPSOLICIT(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 DHCPADVERTISE(net0) fd42::200 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 qemu
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 requested options: 23:dns-server
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 tags: known, dhcpv6, net0
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size: 40 option:  3 ia-na  IAID=2066765558 T1=43200 T2=75600
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 nest size: 24 option:  5 iaaddr  fd42::200 PL=86400 VL=86400
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size:  9 option: 13 status  0 success
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size:  1 option:  7 preference  0
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size: 16 option: 23 dns-server  fd42::1
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14613378 sent size:  6 option: 39 FQDN  qemu
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 available DHCP range: fd42::10 -- fd42::ff
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 client MAC address: 52:54:00:12:34:56
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 DHCPREQUEST(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: Ignoring domain network for DHCP host name qemu
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 DHCPREPLY(net0) fd42::200 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 qemu
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 
14:17:49 DEBUG| [stderr] 14678914 requested options: 23:dns-server
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 tags: known, dhcpv6, net0
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size: 40 option:  3 ia-na  IAID=2066765558 T1=43200 T2=75600
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 nest size: 24 option:  5 iaaddr  fd42::200 PL=86400 VL=86400
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size:  9 option: 13 status  0 success
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size: 16 option: 23 dns-server  fd42::1
14:17:49 DEBUG| [stderr] dnsmasq-dhcp: 14678914 sent size:  6 option: 39 FQDN  qemu
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 available DHCP range: fd42::10 -- fd42::ff
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 vendor class: 343
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 client MAC address: 52:54:00:12:34:56
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 DHCPREQUEST(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 DHCPREPLY(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 no addresses available
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server, 
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 requested options: 16:vendor-class
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 tags: known, dhcpv6, net0
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 32 option:  3 ia-na  IAID=1917410942 T1=4294967295 T2=4294967295
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 nest size: 16 option: 13 status  1 address in use
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 24 option: 13 status  2 no addresses available

failure ...

14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 34 option: 59 bootfile-url  tftp://[fd42::1]/EFI/BOOT/grub.efi
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 16 option: 23 dns-server  fd42::1
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size:  6 option: 39 FQDN  qemu
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 available DHCP range: fd42::10 -- fd42::ff
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 vendor class: 343
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 client MAC address: 52:54:00:12:34:56
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 DHCPSOLICIT(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 DHCPADVERTISE(net0) fd42::201 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 qemu

try ask for an ip again, getting a different one now ...

14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server, 
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 requested options: 16:vendor-class
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 tags: known, dhcpv6, net0
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size: 40 option:  3 ia-na  IAID=1917410942 T1=43200 T2=75600
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 nest size: 24 option:  5 iaaddr  fd42::201 PL=86400 VL=86400
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size:  9 option: 13 status  0 success
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size:  1 option:  7 preference  0
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size: 34 option: 59 bootfile-url  tftp://[fd42::1]/EFI/BOOT/grub.efi
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size: 16 option: 23 dns-server  fd42::1
14:17:52 DEBUG| [stderr] dnsmasq-dhcp: 14809986 sent size:  6 option: 39 FQDN  qemu
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 available DHCP range: fd42::10 -- fd42::ff
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 vendor class: 343
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 client MAC address: 52:54:00:12:34:56
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 DHCPREQUEST(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 DHCPREPLY(net0) 00:01:00:01:28:3d:04:67:52:54:00:12:34:56 no addresses available
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 requested options: 59:bootfile-url, 60:bootfile-param, 23:dns-server, 
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 requested options: 16:vendor-class
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 tags: known, dhcpv6, net0
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 14 option:  1 client-id  00:01:00:01:28:3d:04:67:52:54:00:12:34:56
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 10 option:  2 server-id  00:03:00:01:b6:fe:38:22:4e:b7
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 32 option:  3 ia-na  IAID=1917410942 T1=4294967295 T2=4294967295
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 nest size: 16 option: 13 status  1 address in use
14:17:54 DEBUG| [stderr] dnsmasq-dhcp: 14744450 sent size: 24 option: 13 status  2 no addresses available

nope.  still nacked by dnsmasq

Comment 23 Harald Jensås 2021-09-14 15:01:08 UTC
I raised the issue seen with recovery added as in comment #20 to the dnsmasq-discuss mailing list:
  https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q3/015585.html

Comment 25 Harald Jensås 2021-09-15 17:55:40 UTC
(In reply to Gerd Hoffmann from comment #20)
> Hmm, trying to improve the error handling doesn't have the intended effect.
> 
> --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
> +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
> @@ -2261,6 +2261,20 @@ Dhcp6HandleReplyMsg (
>        }
>        break;
>  
> +    case Dhcp6StsNoAddrsAvail:
> +      DEBUG ((DEBUG_INFO, "%a: Dhcp6StsNoAddrsAvail (%d)\n", __FUNCTION__,
> +              Instance->IaCb.Ia->State));
> +      if (Instance->IaCb.Ia->State == Dhcp6Requesting) {
> +        //
> +        // dnsmasq changed its mind, try start over
> +        //
> +        Status = Dhcp6InitSolicitMsg (Instance);
> +        if (EFI_ERROR (Status)) {
> +          return  Status;
> +        }
> +      }
> +      break;
> +
>      case Dhcp6StsNotOnLink:
>        if (Instance->IaCb.Ia->State == Dhcp6Confirming) {
>          //
> 

Hi Greg,

I tested this patch and did a traffic capture.
The IP address in the REQUEST happining after recovery is still the initially advertised address.

19	73.362476	fe80::2057:f8ff:fedd:fe3b	fe80::284:edff:fe01:10	DHCPv6	208	Advertise XID: 0x1646c1 CID: 00010001283e92480084ed010010 IAA: 2001::22
22	75.360796	fe80::284:edff:fe01:10	ff02::1:2	DHCPv6	219	Request XID: 0x1546c1 CID: 00010001283e92480084ed010010 IAA: 2001::23 

I think we need to reset more than the "Status" ?

I will attach my traffic capture in a subsequent comment.

Comment 26 Harald Jensås 2021-09-15 18:00:55 UTC
Created attachment 1823410 [details]
Ttraffic capture of DHCPv6 traffic with error recovery patch from comment #20

Applying the patch from comment #20 to add error recovery, the traffic capture shows that despite a new address being present in the ADVERTISE message the subsequent REQUEST messages are still requesting the initial address which is leased to the other DHCPv6 client instance.

Comment 27 Gerd Hoffmann 2021-09-15 21:37:49 UTC
> I tested this patch and did a traffic capture.
> The IP address in the REQUEST happining after recovery is still the
> initially advertised address.

ACK. Noticed that too meanwhile.

> I think we need to reset more than the "Status" ?

Yep.  Seems edk2 has the initial response cached somewhere and continues reusing that.
Still debugging, stay tuned ...

Comment 28 Gerd Hoffmann 2021-09-16 04:58:28 UTC
> Still debugging, stay tuned ...

Ok, found it.  There is one extra level of indirection.

The dhcp6 driver (Dhcp6Dxe) will notify the caller (UefiPxeBcDxe)
about all offers it got, and allows the caller to pick the offer
to be accepted.  Which allows UefiPxeBcDxe to pick the best offer
in case multiple offers did arrive, for example select the one
which has bootfile set.

There are a bunch of notifications (see EFI_DHCP6_EVENT), but there
isn't one for "oops, that offer turned out to be not valid, please
drop it from the list".  So UefiPxeBcDxe continues to ask for the
offer it initially got.

I don't see an easy way out ...

Comment 32 Petr Menšík 2021-09-16 17:40:35 UTC
It seems to me there is pretty bad design of DHCP requests. According to first message, client requests first address with some IAID. Dnsmasq responds immediately with DHCPADVERTISE, but client does not wait for it. Instead it requests a new address with different IAID for PXE (!!). This time it waits for it.

After it confirms first address it requested the second time, it continues with attempt to finish the first request only after that. But because sequential assignments are used, this address were already offered the second (now finished) request. I think with demand for sequential assignments, it would advertise first not allocated address. Because they overlap, it succeeds only once. That seems predictable to me.

It is unclear, why it requests address(es) separate way. It seems to me it should just note router advertisement but do not send Solicitation until it knows, whether and what PXE parameters should be sent. Then it should send them only once.

Alternative way might be, delay sending second PXE request until it processes answer and request for original IP. That way, offered IP would change, because the first one were already confirmed.

Gerd, is there strong reason for current way of implementation? Why does it need to request multiple addresses before it even tries to use the first one requested? Fixed ordering would make this problem disappear. Alternative way might be omitting dhcp-sequential-ip (mentioned in comment #16). It might then offer different addresses for the request. If not, that perhaps might be modified. It requests still address solicited the first time, when it was not yet assigned. It did not update the address according to dump in comment #26.

From the RFC it seems the server might send different IP than it got from client request [1]. Would such change work to you? If the prefix is still the same, it might find the same IP it would find on the next Solicit message. I guess someone more experimenced with DHCPv6 might answer such question.

1. https://datatracker.ietf.org/doc/html/rfc8415#section-18.3.2

Comment 33 Petr Menšík 2021-09-16 17:53:44 UTC
(In reply to Harald Jensås from comment #26)
> Created attachment 1823410 [details]
> Ttraffic capture of DHCPv6 traffic with error recovery patch from comment #20
> 
> Applying the patch from comment #20 to add error recovery, the traffic
> capture shows that despite a new address being present in the ADVERTISE
> message the subsequent REQUEST messages are still requesting the initial
> address which is leased to the other DHCPv6 client instance.

Can we make this attachment public? It seems there is no any internal information we need to hide. Geert on upstream discuss list [1] requested exactly this. I doubt we can get any real help from upstream without detailed communications. I don't think current public comments are sufficient. IAIDs are not always logged, but can be seen in wireshark. In your original post to upstream (comment #23) you said it is still nacked by the server. But different address than offered were nacked, which is not visible just from dnsmasq logs.

Comment 35 Petr Menšík 2021-09-16 18:48:06 UTC
According to RFC 8415, section 18.2.10.1 [1], start of page 70, it appears correct resolution on client side would be to restart the request with empty addresses. But I doubt Renew [2] or Rebind is correct when such address were just advertised, but never committed for the IAID.

1. https://datatracker.ietf.org/doc/html/rfc8415#section-18.2.10.1
2. https://datatracker.ietf.org/doc/html/rfc8415#section-18.3.4

Comment 36 Harald Jensås 2021-09-16 21:10:46 UTC
Created attachment 1823674 [details]
Traffice capture Tianocore edk2-ovmf with Kea

As an experiment I tried kea-dhcp6 in Fedora 34:

2021-09-16 22:43:10.102 INFO  [kea-dhcp6.alloc-engine/11530.139835009403008] ALLOC_ENGINE_V6_HR_ADDR_GRANTED reserved address 2001::20 was assigned to client duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1cf708
2021-09-16 22:43:10.102 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_LEASE_ADVERT duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1cf708: lease for address 2001::20 and iaid=3083853311 will be advertised
2021-09-16 22:43:11.000 INFO  [kea-dhcp6.alloc-engine/11530.139835009403008] ALLOC_ENGINE_V6_HR_ADDR_GRANTED reserved address 2001::20 was assigned to client duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1df708
2021-09-16 22:43:11.000 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_LEASE_ADVERT duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1df708: lease for address 2001::20 and iaid=3068264439 will be advertised
2021-09-16 22:43:11.001 INFO  [kea-dhcp6.alloc-engine/11530.139835009403008] ALLOC_ENGINE_V6_HR_ADDR_GRANTED reserved address 2001::20 was assigned to client duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1ef708

Initially 2001::20 is advertised to both iaid=3083853311 and iaid=3068264439.

2021-09-16 22:43:11.001 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_LEASE_ALLOC duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1ef708: lease for address 2001::20 and iaid=3068264439 has been allocated for 4000 seconds

iaid=3068264439 got the 2001::20 lease

2021-09-16 22:43:15.100 INFO  [kea-dhcp6.alloc-engine/11530.139835009403008] ALLOC_ENGINE_V6_HR_ADDR_GRANTED reserved address 2001::21 was assigned to client duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1ff708
2021-09-16 22:43:15.100 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_LEASE_ALLOC duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x1ff708: lease for address 2001::21 and iaid=3083853311 has been allocated for 4000 seconds

2001::21 is assigned, and iaid=3083853311 got that, NOTE that there was no ADVERTISE. The server simply replied: "you can have this address instead".

2021-09-16 22:43:15.100 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_RELEASE_NA duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x20f708: binding for address 2001::20 and iaid=3068264439 was released properly
2021-09-16 22:43:16.920 INFO  [kea-dhcp6.leases/11530.139835009403008] DHCP6_RELEASE_NA duid=[00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc], tid=0x21f708: binding for address 2001::21 and iaid=3083853311 was released properly


Looking at the traffic capture you can see that Kea DHCP6 server does a reply with a different address, from the one in the request. Not setting error flags.

7	4.997525	fe80::5054:ff:fe92:a499	ff02::1:2	DHCPv6	223	Request XID: 0x1ff708 CID: 0004e20ad1ed6c7aec4b99d94da08f6c26cc IAA: 2001::20 
8	4.997914	fe80::5054:ff:fe2d:3c77	fe80::5054:ff:fe92:a499	DHCPv6	182	Reply XID: 0x1ff708 CID: 0004e20ad1ed6c7aec4b99d94da08f6c26cc IAA: 2001::21 


It seems this might be ok based on rfc8415 18.3.2 [1].
"""
   The server MAY assign different addresses and/or delegated prefixes
   to an IA than those included within the IA of the client's Request
   message.
"""


The Kea DHCP6 config I used:
{
  "Dhcp6": {
    "valid-lifetime": 4000,
    "renew-timer": 1000,
    "rebind-timer": 2000,
    "preferred-lifetime": 3000,
    "interfaces-config": {
       "interfaces": [ "enp2s0" ]
    },
    "lease-database": {
      "type": "memfile",
      "persist": true,
      "name": "/var/lib/kea/dhcp6.leases"
    },
    "subnet6": [
      {
        "subnet": "2001::/64",
        "interface": "enp2s0",
        "pools": [
          { 
            "pool": "2001::10-2001::100",
            "option-data": [
              { "name": "bootfile-url", "code": 59, "data": "tftp://[2001::1]/shimx64.efi" }
            ]
          }
        ],
        "reservations": [
          { "duid": "00:04:e2:0a:d1:ed:6c:7a:ec:4b:99:d9:4d:a0:8f:6c:26:cc",
            "ip-addresses": [ "2001::20", "2001::21", "2001::22", "2001::23" ] }
        ]
      }
    ]
  }
}



[1] https://datatracker.ietf.org/doc/html/rfc8415#section-18.3.2

Comment 38 Gerd Hoffmann 2021-09-17 08:19:53 UTC
> It is unclear, why it requests address(es) separate way. It seems to me it
> should just note router advertisement but do not send Solicitation until it
> knows, whether and what PXE parameters should be sent. Then it should send
> them only once.

It's two completely separate dhcpv6 client instances.  One created by the
pxe boot driver (that is the one which requests the bootfile url).  The other
created by ipv6 interface configuration code.  The latter is only send in case
the router advertisement says clients should ask for an address via dhcp.
See comment 19 for more details.

> From the RFC it seems the server might send different IP than it got from
> client request [1]. Would such change work to you?

Probably it would, but I don't know for sure.
I happily test patches.

Comment 39 Petr Menšík 2021-09-17 09:43:40 UTC
It seems somehow similar situation occurs on bug #1969908 for IPv4. Not sure DHCPv4 should behave the same way.

Comment 40 Petr Menšík 2021-09-17 10:25:57 UTC
(In reply to Gerd Hoffmann from comment #38)
> It's two completely separate dhcpv6 client instances.  One created by the
> pxe boot driver (that is the one which requests the bootfile url).  The other
> created by ipv6 interface configuration code.  The latter is only send in
> case
> the router advertisement says clients should ask for an address via dhcp.
> See comment 19 for more details.
> 
I don't understand why it uses separate IPv6 client instances for the same hosts. It requires bigger allocation units, just because it tries to request separate address for each subsystem during boot. All of those at the same time, not sequentially. I think no real system ever requests two separate addresses from the same range. I understand it might be easier to implement without internal coordination. It seems basic cooperation should be done within boot firmware. Why is pxe boot driver separate? I know, it needs some options to request correct boot file. What is purpose of reacting to router advertisement then? It should know it already asked for an address on that interface, so it should reuse any response for PXE boot. It seems like multiple "processes" in boot firmware do communicate between themselves and DHCP server has to solve it for them. I do not think every process on normal system should request address for it communication. Why does boot firmware need that?

There are multiple steps boot firmware has to do. I think they should appear more integrated. I would understand if they were sequential, but not when they run at the same time. But I guess that cannot be changed in RHEL8 lifetime. But definitely one address should be enough for a booting process.

> > From the RFC it seems the server might send different IP than it got from
> > client request [1]. Would such change work to you?
> 
> Probably it would, but I don't know for sure.
> I happily test patches.

Comment 41 Harald Jensås 2021-09-17 11:11:33 UTC
Created attachment 1823867 [details]
Traffic capture with dnsmasq patch to reply with new address in request

With the below patch I got dnsmasq to reply with a new address to the request with the already leased address.
This makes dnsmasq behave similar to kea-dhcp6, see comment: #36

I testet this with both static, and dynamic range with "sequential-ip", it seems to work.
The traffic capture attached is with the static only configuration.

If I change the 'dhcp-host' entry in the static config to contain just *one* address, it fails as expected with:
Sep 17 07:09:51 server dnsmasq-dhcp[1841]: 10083164 nest size: 21 option: 13 status  2 address unavailable                                                                                                
Sep 17 07:09:51 server dnsmasq-dhcp[1841]: 10083164 sent size: 24 option: 13 status  2 no addresses available 


Static config
-------------
log-dhcp
port=0
dhcp-range=set:range0,2001::,static,64,10m
dhcp-host=00:84:ed:01:00:10,tag:dhcpv6,client.localdomain,[2001::20],[2001::21],[2001::22],[2001::23]
dhcp-sequential-ip
# dhcpv6s for Client System Architecture Type (61)
dhcp-match=set:efi6,option6:61,0007
dhcp-match=set:efi6,option6:61,0009
dhcp-match=set:efi6,option6:61,0011
dhcp-option=tag:efi6,option6:bootfile-url,tftp://[2001::2]/shimx64.efi

Dynamic config with sequential-ip:
---------------------------------
log-dhcp
port=0

dhcp-range=set:range0,2001::10,2001::100,64,10m
dhcp-sequential-ip
# dhcpv6s for Client System Architecture Type (61)
dhcp-match=set:efi6,option6:61,0007
dhcp-match=set:efi6,option6:61,0009
dhcp-match=set:efi6,option6:61,0011
dhcp-option=tag:efi6,option6:bootfile-url,tftp://[2001::2]/shimx64.efi



diff --git a/src/rfc3315.c b/src/rfc3315.c
index 5c2ff97..90fb77f 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -847,7 +847,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
                memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
                
                if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
-                 config_ok = (config_implies(config, c, &req_addr) != NULL);
+                 if (check_address(state, &req_addr)) {
+                   config_ok = (config_implies(config, c, &req_addr) != NULL);
+                 }
+                 else {
+                       /* If the address is already leased to another DUID/IAID, treat it like
+                          a SOLICIT with rapid commit set. I.e try to assign a different address
+                          if available. */
+                        save_counter(start);
+                        goto request_no_address; 
+                 }
                
                if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
                  {

Comment 42 Gerd Hoffmann 2021-09-17 11:44:39 UTC
> It requires bigger allocation units, just because it tries to request
> separate address for each subsystem during boot.

Well, dhcpd seems to happily hand out the same ip address multiple
times (as long as the DUID is the same).

> It seems like
> multiple "processes" in boot firmware do communicate between themselves and
> DHCP server has to solve it for them. I do not think every process on normal
> system should request address for it communication. Why does boot firmware
> need that?

With ipv4 the pxe driver needs both ip address and bootfile.
With ipv6 bootfile should be enough thanks to autoconfiguration.

Speculation: Changing UEFI spec is hard, so they fitted ipv6 pxe support into
the existing ipv4 pxe interfaces without changing the underlying workflow.

Looking through the dhcpv6 rfc it looks legit to ask for the bootfile url using
an InfoRequest.  The concept of an InfoRequest (aka stateless configuration)
doesn't exist in dhcpv4 though, so that's how we ended up with the pxe driver
asking for an ipv6 address.

It's not ideal, but I think not fixable without an UEFI spec update.
Which I suspect can easily take months if not years.

Given the code is also shipped in the edk development toolkit for
hardware OEMs I'd expect you can see physical hardware show the
same behavior.

Comment 44 Petr Menšík 2021-09-21 22:33:16 UTC
What I did for testing this issue:

IFACE=host0 # change to whatever is used in the environment

ip address add 2620:dead:beef:4::1/64 dev host0

cat << EOF > /etc/dnsmasq.d/bz1998448.conf
log-dhcp
port=0
interface=host0

dhcp-sequential-ip
dhcp-range=::,static
dhcp-match=ipxe,175
# dhcpv6s for Client System Architecture Type (61)
dhcp-match=set:efi6,option6:61,0007
dhcp-match=set:efi6,option6:61,0009
dhcp-match=set:efi6,option6:61,0011
dhcp-userclass=set:ipxe6,iPXE
# Client is PXE booting over EFI without iPXE ROM; send EFI version of iPXE chainloader
dhcp-option=tag:efi6,tag:!ipxe6,option6:bootfile-url,tftp://[2620:dead:beef:4::1]/shimx64.efi

enable-tftp
tftp-root=/tftproot # use /var/lib/tftproot as alternative, tftp-server package

# Use static allocated only, replace with MAC of your client VM
dhcp-host=52:54:00:06:57:c3,tag:dhcpv6,netboot.test,[2620:dead:beef:4::d1],[2620:dead:beef:4::d2],[2620:dead:beef:4::d3],120
EOF

mkdir /tftproot
dnf install -y radvd shim-x64 && cp /boot/efi/EFI/redhat/shimx64.efi /tftproot/ && chmod a+r /tftproot/*.efi

cat << EOF > /etc/radvd.conf
interface host0
{
        AdvSendAdvert on;
        AdvManagedFlag on;
        prefix 2620:dead:beef:4::/64;
};
EOF

systemctl restart dnsmasq radvd

Now try to boot your VM few times. It would fail sometimes without modified version. It should pass always with a new version.

dnsmasq logs each tftp access, so it can be used to verify machine got an address, downloaded it. I kept missing grub.efi to check first step on booting, which is enough. Does not matter IPXE6 boot fails, but it tries needed steps.

Comment 46 Petr Menšík 2021-09-24 11:09:37 UTC
Created attachment 1825881 [details]
dnsmasq change proposal

Comment 47 Petr Menšík 2021-09-24 11:12:43 UTC
Created attachment 1825882 [details]
option6:client-arch support, optional

Optional option6 support for option6:client-arch,7 and option6:client-interface-id,01:03:01, useful especially for dhcp-match parameter. Not usually sent as requested option.

Comment 49 Harald Jensås 2021-09-24 11:51:01 UTC
(In reply to Gerd Hoffmann from comment #42)
> > It requires bigger allocation units, just because it tries to request
> > separate address for each subsystem during boot.
> 
> Well, dhcpd seems to happily hand out the same ip address multiple
> times (as long as the DUID is the same).
> 

I think dhcpd is breaking the DHCPv6 specification when it is doing this.
While it is "helpful" for this usecase, it also means a client that actually want to allocate multiple addresses to the same DUID won't be able to.

Over time I assume ISC will deprecate ISC-DHCP in favor of it's new Kea DHCP implementation.

> > It seems like
> > multiple "processes" in boot firmware do communicate between themselves and
> > DHCP server has to solve it for them. I do not think every process on normal
> > system should request address for it communication. Why does boot firmware
> > need that?
> 
> With ipv4 the pxe driver needs both ip address and bootfile.
> With ipv6 bootfile should be enough thanks to autoconfiguration.
> 
> Speculation: Changing UEFI spec is hard, so they fitted ipv6 pxe support into
> the existing ipv4 pxe interfaces without changing the underlying workflow.
> 
> Looking through the dhcpv6 rfc it looks legit to ask for the bootfile url
> using
> an InfoRequest.  The concept of an InfoRequest (aka stateless configuration)
> doesn't exist in dhcpv4 though, so that's how we ended up with the pxe driver
> asking for an ipv6 address.
> 
> It's not ideal, but I think not fixable without an UEFI spec update.
> Which I suspect can easily take months if not years.
> 

I think it should be a long-term goal to update the UEFI spec.

It is quite unfortunate that UEFI requires IP address from a DHCP server.
It would be a nice improvement to UEFI if it would support address autoconfiguration and using InfoRequest only for the boot file.

Even with managed addresses from DHCP, it would be good if the firmware would:
 1. Configure the interface based on M flag in RA's.
 2. Use InfoRequest for options (i.e bootfile url)

> Given the code is also shipped in the edk development toolkit for
> hardware OEMs I'd expect you can see physical hardware show the
> same behavior.

I can confirm that we do see same behavior with physical hardware.
On the positive side, if the edk development toolkit is improved, the improvements would end up on actual hardware as well.

Comment 50 Petr Menšík 2021-09-24 12:24:21 UTC
(In reply to Gerd Hoffmann from comment #42)
> Well, dhcpd seems to happily hand out the same ip address multiple
> times (as long as the DUID is the same).
> 
> With ipv4 the pxe driver needs both ip address and bootfile.
> With ipv6 bootfile should be enough thanks to autoconfiguration.

I do not think DHCP request for bootfile it the problem here. I think main difference between IPv4 and IPv6 is that router announcement may arrive before PXE request. Because firmware reacts on it straight away by sending separate DHCP solicitation request, there may be two simultaneous DHCP sessions for the single host. Can DHCPv4 request multiple times IP address in some case?
> 
> Speculation: Changing UEFI spec is hard, so they fitted ipv6 pxe support into
> the existing ipv4 pxe interfaces without changing the underlying workflow.
> 
> Looking through the dhcpv6 rfc it looks legit to ask for the bootfile url
> using
> an InfoRequest.  The concept of an InfoRequest (aka stateless configuration)
> doesn't exist in dhcpv4 though, so that's how we ended up with the pxe driver
> asking for an ipv6 address.
> 
> It's not ideal, but I think not fixable without an UEFI spec update.
> Which I suspect can easily take months if not years.

Does UEFI spec define, when should be EFI_DHCP6_PROTOCOL.Configure() called and with which options? I think the main problem here is PXE boot and router advertisement reactions are separate, unrelated actions. If all those submodules could first gather requested options and only once actually request address, it would work just fine. Much like on IPv4. It should work also with just InfoRequest, if address handling remained on router announce reaction.

It seems InfoRequest is already part of UEFI 2.7 spec [1], 29.3.2 DHCP6 protocol. I have no idea, how hard would it be using it from the edk firmware code. I guess you know how it is. Can we request changing it for RHEL9, maybe also RHEL 10? Because it always uses release after booting, I think no unusual expectation would be just single address should work for booting over PXE.

> 
> Given the code is also shipped in the edk development toolkit for
> hardware OEMs I'd expect you can see physical hardware show the
> same behavior.

I have checked shortly DHCP packets from Lenovo laptop seem similar. I have no native IPv6 booting configured in my real network, haven't tested this case on real devices.

There are already some uses of InfoRequest on iSCSI and DNS modules [2]. Whereas Configure requests are used from PXE and HTTP boots [3] in addition to Stateful router advertisement reaction. It seems to me all required parts should be already present on edk2 upstream. Just are used different way.

1. https://uefi.org/sites/default/files/resources/UEFI_Spec_2_7.pdf
2. https://github.com/tianocore/edk2/search?q=Dhcp6-%3EInfoRequest
3. https://github.com/tianocore/edk2/search?q=Dhcp6-%3EConfigure

Comment 51 Petr Menšík 2021-09-24 13:01:08 UTC
I have checked edk2 a bit. It seems to me EfiDhcp6GetModeData can be used to fetch existing DHCPv6 session. If that exist, the same IAID should be extracted and only EfiDhcp6InfoRequest could be used to fetch missing boot parameters. It could request address in the other case by EfiDhcp6Configure, as it does now.

I think dnsmasq should be fixed anyway, but I filled new bug #2007642 on RHEL9. I think there are already ways to improve current booting without standards update.

Comment 52 Petr Menšík 2021-09-24 14:00:53 UTC
(In reply to Harald Jensås from comment #49)
> I think dhcpd is breaking the DHCPv6 specification when it is doing this.
> While it is "helpful" for this usecase, it also means a client that actually
> want to allocate multiple addresses to the same DUID won't be able to.
> 
> Over time I assume ISC will deprecate ISC-DHCP in favor of it's new Kea DHCP
> implementation.
> 

Sure, DHCP client and relay would be deprecated by the end of this year [1]. Server part would be maintained for some longer time, but eventually should be replaced by kea.

1. https://lists.isc.org/pipermail/dhcp-announce/2021-June/000433.html

Comment 77 errata-xmlrpc 2022-05-10 13:49:02 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (dnsmasq bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:1839


Note You need to log in before you can comment on or make changes to this bug.