Support rapid commit option code 14 which bypass the advertise and
request state. The option is enabled by DHCP6_RAPID_COMMIT.

Signed-off-by: Yuxiao Zhang <[email protected]>
---

 cmd/Kconfig  |  8 ++++++++
 net/dhcpv6.c | 39 ++++++++++++++++++++++++++++++++-------
 net/dhcpv6.h |  2 ++
 3 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/cmd/Kconfig b/cmd/Kconfig
index ff90a87024c..b3cf3a6d8b6 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1996,6 +1996,14 @@ config DHCP6_ENTERPRISE_ID
        int "Enterprise ID to send in DHCPv6 Vendor Class Option"
        default 0
 
+config DHCP6_RAPID_COMMIT
+       bool "Request Rapid Commit (2-message exchange) from DHCPv6 server"
+       default n
+       help
+         Request the Rapid Commit option (option 14) in DHCPv6 Solicit
+         messages to enable a 2-message exchange (Solicit-Reply) rather
+         than the default 4-message exchange.
+
 endif
 
 config BOOTP_MAY_FAIL
diff --git a/net/dhcpv6.c b/net/dhcpv6.c
index 640f089a2e1..1e51e6de256 100644
--- a/net/dhcpv6.c
+++ b/net/dhcpv6.c
@@ -115,6 +115,9 @@ static int dhcp6_add_option(int option_id, uchar *pkt)
 
                opt_len = sizeof(struct dhcp6_option_ia_na);
                break;
+       case DHCP6_OPTION_RAPID_COMMIT:
+               opt_len = 0;
+               break;
        case DHCP6_OPTION_ORO:
                oro_opt = (struct dhcp6_option_oro *)dhcp_option_start;
                oro_opt->req_option_code[num_oro++] = 
htons(DHCP6_OPTION_OPT_BOOTFILE_URL);
@@ -194,6 +197,8 @@ static void dhcp6_send_solicit_packet(void)
        pkt += dhcp6_add_option(DHCP6_OPTION_ELAPSED_TIME, pkt);
        pkt += dhcp6_add_option(DHCP6_OPTION_IA_NA, pkt);
        pkt += dhcp6_add_option(DHCP6_OPTION_ORO, pkt);
+       if (IS_ENABLED(CONFIG_DHCP6_RAPID_COMMIT))
+               pkt += dhcp6_add_option(DHCP6_OPTION_RAPID_COMMIT, pkt);
        if (CONFIG_DHCP_PXE_CLIENTARCH != 0xFF)
                pkt += dhcp6_add_option(DHCP6_OPTION_CLIENT_ARCH_TYPE, pkt);
        pkt += dhcp6_add_option(DHCP6_OPTION_VENDOR_CLASS, pkt);
@@ -448,6 +453,12 @@ static void dhcp6_parse_options(uchar *rx_pkt, unsigned 
int len)
                        }
                        sm_params.rx_status.preference = *option_ptr;
                        break;
+               case DHCP6_OPTION_RAPID_COMMIT:
+                       if (IS_ENABLED(CONFIG_DHCP6_RAPID_COMMIT)) {
+                               debug("DHCP6_OPTION_RAPID_COMMIT FOUND\n");
+                               sm_params.rx_status.rapid_commit_found = true;
+                       }
+                       break;
                default:
                        debug("Unknown Option ID: %d, skipping parsing\n",
                              ntohs(option_hdr->option_id));
@@ -618,14 +629,28 @@ static void dhcp6_state_machine(bool timeout, uchar 
*rx_pkt, unsigned int len)
                break;
        case DHCP6_SOLICIT:
                if (!timeout) {
-                       /* check the rx packet and determine if we can 
transition to next
-                        * state.
-                        */
-                       if (dhcp6_check_advertise_packet(rx_pkt, len))
-                               return;
+                       struct dhcp6_hdr *dhcp6_hdr = (struct dhcp6_hdr 
*)rx_pkt;
+
+                       if (IS_ENABLED(CONFIG_DHCP6_RAPID_COMMIT) &&
+                           dhcp6_hdr && dhcp6_hdr->msg_type == 
DHCP6_MSG_REPLY) {
+                               if (dhcp6_check_reply_packet(rx_pkt, len))
+                                       return;
+                               if (!sm_params.rx_status.rapid_commit_found) {
+                                       debug("[DHCPv6] REPLY received without 
Rapid Commit option, ignoring\n");
+                                       return;
+                               }
+                               debug("REPLY (Rapid Commit) good, transition to 
DONE\n");
+                               sm_params.next_state = DHCP6_DONE;
+                       } else {
+                               /* check the rx packet and determine if we can 
transition to next
+                                * state.
+                                */
+                               if (dhcp6_check_advertise_packet(rx_pkt, len))
+                                       return;
 
-                       debug("ADVERTISE good, transition to REQUEST\n");
-                       sm_params.next_state = DHCP6_REQUEST;
+                               debug("ADVERTISE good, transition to 
REQUEST\n");
+                               sm_params.next_state = DHCP6_REQUEST;
+                       }
                } else if (sm_params.retry_cnt == 1)  {
                        /* If a server UID was received in the first SOLICIT 
period
                         * transition to REQUEST
diff --git a/net/dhcpv6.h b/net/dhcpv6.h
index d41a3c30615..49f20390730 100644
--- a/net/dhcpv6.h
+++ b/net/dhcpv6.h
@@ -24,6 +24,7 @@
 #define DHCP6_OPTION_PREFERENCE                7
 #define DHCP6_OPTION_ELAPSED_TIME      8
 #define DHCP6_OPTION_STATUS_CODE       13
+#define DHCP6_OPTION_RAPID_COMMIT      14
 #define DHCP6_OPTION_OPT_BOOTFILE_URL  59
 #define DHCP6_OPTION_OPT_BOOTFILE_PARAM        60
 #define DHCP6_OPTION_SOL_MAX_RT                82
@@ -152,6 +153,7 @@ struct dhcp6_rx_pkt_status {
        enum dhcp6_status       ia_status_code;
        enum dhcp6_status       status_code;
        u8                      preference;
+       bool                    rapid_commit_found;
 };
 
 /**
---
base-commit: 527115ef6783cec49e5610c523c124b399011361
branch: main

-- 
2.55.0.737.g08866a6d13-goog

Reply via email to