[ovs-dev] [PATCH ovn] dhcp: add iPXE support to OVN

Lorenzo Bianconi lorenzo.bianconi at redhat.com
Tue May 12 12:44:21 UTC 2020


Introduce the possibility to specify more than 255 options in
put_dhcp_opts userdata buffer. This is useful to fill even the fixed
fields of the DHCP reply header (e.g file_name used in iPXE protocol).
Express the option code using 2 bytes instead of just one in userdata
buffer. Moreover, parse userdata buffer in pinctrl_handle_put_dhcp_opts
in order to distinguish between 'variable' and 'fixed' options

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
 controller/pinctrl.c | 49 ++++++++++++++++++++++--
 lib/actions.c        | 20 +++++-----
 lib/ovn-l7.h         |  4 ++
 northd/ovn-northd.c  |  1 +
 ovn-nb.xml           |  8 ++++
 ovn-sb.ovsschema     |  4 +-
 tests/ovn.at         | 89 +++++++++++++++++++++++++++++++++-----------
 tests/test-ovn.c     |  1 +
 8 files changed, 138 insertions(+), 38 deletions(-)

diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index d976ec82b..a88f75e58 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -1762,6 +1762,7 @@ pinctrl_handle_put_dhcp_opts(
     }
     in_dhcp_ptr += sizeof magic_cookie;
 
+    bool ipxe_req = false;
     const uint8_t *in_dhcp_msg_type = NULL;
     ovs_be32 request_ip = in_dhcp_data->ciaddr;
     while (in_dhcp_ptr < end) {
@@ -1794,6 +1795,9 @@ pinctrl_handle_put_dhcp_opts(
                 request_ip = get_unaligned_be32(DHCP_OPT_PAYLOAD(in_dhcp_opt));
             }
             break;
+        case DHCP_OPT_ETHERBOOT:
+            ipxe_req = true;
+            break;
         default:
             break;
         }
@@ -1844,9 +1848,40 @@ pinctrl_handle_put_dhcp_opts(
      *| 4 Bytes padding | 1 Byte (option end 0xFF ) | 4 Bytes padding|
      * --------------------------------------------------------------
      */
+    /* compute opt len */
+    unsigned char *boot_filename = NULL, *filename = NULL;
+    unsigned char *ptr = (unsigned char *)userdata->data;
+    uint16_t boot_filename_len = 0, filename_len = 0;
+    unsigned char *buf = xmalloc(userdata->size);
+    uint16_t len = 0, opt_len = 0;
+
+    while (len < userdata->size) {
+        int cur_len = ptr[len + 2];
+        uint16_t code;
+
+        memcpy(&code, &ptr[len], 2);
+        switch (code) {
+        case 300: /* DHCP_OPT_FILENAME */
+          filename = &ptr[len + 3];
+          filename_len = cur_len;
+          break;
+        case 67: /* DHCP_OPT_BOOTFILENAME */
+          boot_filename = &buf[opt_len + 2];
+          boot_filename_len = cur_len;
+          /* fall through */
+        default:
+          /* code < 255 */
+          buf[opt_len] = code;
+          memcpy(buf + 1 + opt_len, &ptr[len + 2], cur_len + 1);
+          opt_len += 2 + cur_len;
+          break;
+        }
+        len += 3 + cur_len;
+    }
+
     uint16_t new_l4_size = UDP_HEADER_LEN + DHCP_HEADER_LEN + 16;
     if (msg_type != DHCP_MSG_NAK) {
-        new_l4_size += userdata->size;
+        new_l4_size += opt_len;
     }
     size_t new_packet_size = pkt_in->l4_ofs + new_l4_size;
 
@@ -1876,7 +1911,7 @@ pinctrl_handle_put_dhcp_opts(
 
     uint16_t out_dhcp_opts_size = 12;
     if (msg_type != DHCP_MSG_NAK) {
-      out_dhcp_opts_size += userdata->size;
+      out_dhcp_opts_size += opt_len;
     }
     uint8_t *out_dhcp_opts = dp_packet_put_zeros(&pkt_out,
                                                  out_dhcp_opts_size);
@@ -1886,9 +1921,14 @@ pinctrl_handle_put_dhcp_opts(
     out_dhcp_opts[2] = msg_type;
     out_dhcp_opts += 3;
 
+    if (filename && boot_filename && !ipxe_req) {
+        memset(boot_filename, 0, boot_filename_len);
+        memcpy(boot_filename, filename, filename_len);
+    }
+
     if (msg_type != DHCP_MSG_NAK) {
-      memcpy(out_dhcp_opts, userdata->data, userdata->size);
-      out_dhcp_opts += userdata->size;
+      memcpy(out_dhcp_opts, buf, opt_len);
+      out_dhcp_opts += opt_len;
     }
 
     /* Padding */
@@ -1926,6 +1966,7 @@ pinctrl_handle_put_dhcp_opts(
                  ETH_ADDR_ARGS(l2->eth_src), IP_ARGS(*offer_ip));
 
     success = 1;
+    free(buf);
 exit:
     if (!ofperr) {
         union mf_subvalue sv;
diff --git a/lib/actions.c b/lib/actions.c
index c50615177..4959aa3b3 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -2236,23 +2236,23 @@ static void
 encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
                          struct ofpbuf *ofpacts)
 {
-    uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
-    opt_header[0] = o->option->code;
+    uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 3);
 
+    memcpy(opt_header, &o->option->code, 2);
     const union expr_constant *c = o->value.values;
     size_t n_values = o->value.n_values;
     if (!strcmp(o->option->type, "bool") ||
         !strcmp(o->option->type, "uint8")) {
-        opt_header[1] = 1;
+        opt_header[2] = 1;
         ofpbuf_put(ofpacts, &c->value.u8_val, 1);
     } else if (!strcmp(o->option->type, "uint16")) {
-        opt_header[1] = 2;
+        opt_header[2] = 2;
         ofpbuf_put(ofpacts, &c->value.be16_int, 2);
     } else if (!strcmp(o->option->type, "uint32")) {
-        opt_header[1] = 4;
+        opt_header[2] = 4;
         ofpbuf_put(ofpacts, &c->value.be32_int, 4);
     } else if (!strcmp(o->option->type, "ipv4")) {
-        opt_header[1] = n_values * sizeof(ovs_be32);
+        opt_header[2] = n_values * sizeof(ovs_be32);
         for (size_t i = 0; i < n_values; i++) {
             ofpbuf_put(ofpacts, &c[i].value.ipv4, sizeof(ovs_be32));
         }
@@ -2261,7 +2261,7 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
         if (no_of_routes % 2) {
             no_of_routes -= 1;
         }
-        opt_header[1] = 0;
+        opt_header[2] = 0;
 
         /* Calculating the length of this option first because when
          * we call ofpbuf_put, it might reallocate the buffer if the
@@ -2273,7 +2273,7 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
             if (c[i].masked) {
                 plen = (uint8_t) ip_count_cidr_bits(c[i].mask.ipv4);
             }
-            opt_header[1] += (1 + DIV_ROUND_UP(plen, 8) + sizeof(ovs_be32));
+            opt_header[2] += (1 + DIV_ROUND_UP(plen, 8) + sizeof(ovs_be32));
         }
 
         /* Copied from RFC 3442. Please refer to this RFC for the format of
@@ -2303,8 +2303,8 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
                        sizeof(ovs_be32));
         }
     } else if (!strcmp(o->option->type, "str")) {
-        opt_header[1] = strlen(c->string);
-        ofpbuf_put(ofpacts, c->string, opt_header[1]);
+        opt_header[2] = strlen(c->string);
+        ofpbuf_put(ofpacts, c->string, opt_header[2]);
     }
 }
 
diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index cc63d822d..11d21d722 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -81,6 +81,10 @@ struct gen_opts_map {
 #define DHCP_OPT_PATH_PREFIX DHCP_OPTION("path_prefix", 210, "str")
 #define DHCP_OPT_TFTP_SERVER_ADDRESS \
     DHCP_OPTION("tftp_server_address", 150, "ipv4")
+/* fixed DHCP header */
+#define DHCP_OPT_FILENAME DHCP_OPTION("file", 300, "str")
+
+#define DHCP_OPT_ETHERBOOT	175
 
 #define DHCP_OPT_ARP_CACHE_TIMEOUT \
     DHCP_OPTION("arp_cache_timeout", 35, "uint32")
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 76b4a14ee..bb99ffa3f 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11363,6 +11363,7 @@ static struct gen_opts_map supported_dhcp_opts[] = {
     DHCP_OPT_DOMAIN_NAME,
     DHCP_OPT_ARP_CACHE_TIMEOUT,
     DHCP_OPT_TCP_KEEPALIVE_INTERVAL,
+    DHCP_OPT_FILENAME,
 };
 
 static struct gen_opts_map supported_dhcpv6_opts[] = {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 95ee4c9e6..fbb2627a4 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2938,6 +2938,14 @@
             resolving hostnames via the Domain Name System.
           </p>
         </column>
+
+        <column name="options" key="file">
+          <p>
+          </p>
+             Boot file name, null terminated string; "generic" name or null
+             in DHCPDISCOVER, fully qualified directory-path name in
+             DHCPOFFER.
+        </column>
       </group>
     </group>
 
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index d89f8dbbb..db31b4e6e 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
     "version": "2.7.0",
-    "cksum": "4286723485 21693",
+    "cksum": "1310408045 21694",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -209,7 +209,7 @@
                 "name": {"type": "string"},
                 "code": {
                     "type": {"key": {"type": "integer",
-                                     "minInteger": 0, "maxInteger": 254}}},
+                                     "minInteger": 0, "maxInteger": 1000}}},
                 "type": {
                     "type": {"key": {
                         "type": "string",
diff --git a/tests/ovn.at b/tests/ovn.at
index 52d994972..e76eed285 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1201,13 +1201,13 @@ reg0[0] = lookup_arp(inport, ip4.src, ip4.dst);
 
 # put_dhcp_opts
 reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause)
+    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.00.04.0a.00.00.01,pause)
 reg2[5] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.254.0,mtu=1400,domain_name="ovn.org",wpad="https://example.org",bootfile_name="https://127.0.0.1/boot.ipxe",path_prefix="/tftpboot");
     formats as reg2[5] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.254.0, mtu = 1400, domain_name = "ovn.org", wpad = "https://example.org", bootfile_name = "https://127.0.0.1/boot.ipxe", path_prefix = "/tftpboot");
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.fe.00.1a.02.05.78.0f.07.6f.76.6e.2e.6f.72.67.fc.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.09.2f.74.66.74.70.62.6f.6f.74,pause)
+    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.25.0a.00.00.04.03.00.04.0a.00.00.01.01.00.04.ff.ff.fe.00.1a.00.02.05.78.0f.00.07.6f.76.6e.2e.6f.72.67.fc.00.13.68.74.74.70.73.3a.2f.2f.65.78.61.6d.70.6c.65.2e.6f.72.67.43.00.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65.d2.00.09.2f.74.66.74.70.62.6f.6f.74,pause)
 reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,mtu=1400,ip_forward_enable=1,default_ttl=121,dns_server={8.8.8.8,7.7.7.7},classless_static_route={30.0.0.0/24,10.0.0.4,40.0.0.0/16,10.0.0.6,0.0.0.0/0,10.0.0.1},ethernet_encap=1,router_discovery=0,tftp_server_address={10.0.0.4,10.0.0.5},arp_cache_timeout=10,tcp_keepalive_interval=10);
     formats as reg0[15] = put_dhcp_opts(offerip = 10.0.0.4, router = 10.0.0.1, netmask = 255.255.255.0, mtu = 1400, ip_forward_enable = 1, default_ttl = 121, dns_server = {8.8.8.8, 7.7.7.7}, classless_static_route = {30.0.0.0/24, 10.0.0.4, 40.0.0.0/16, 10.0.0.6, 0.0.0.0/0, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server_address = {10.0.0.4, 10.0.0.5}, arp_cache_timeout = 10, tcp_keepalive_interval = 10);
-    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.04.0a.00.00.01.01.04.ff.ff.ff.00.1a.02.05.78.13.01.01.17.01.79.06.08.08.08.08.08.07.07.07.07.79.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.01.01.1f.01.00.96.08.0a.00.00.04.0a.00.00.05.23.04.00.00.00.0a.26.04.00.00.00.0a,pause)
+    encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.6f.0a.00.00.04.03.00.04.0a.00.00.01.01.00.04.ff.ff.ff.00.1a.00.02.05.78.13.00.01.01.17.00.01.79.06.00.08.08.08.08.08.07.07.07.07.79.00.14.18.1e.00.00.0a.00.00.04.10.28.00.0a.00.00.06.00.0a.00.00.01.24.00.01.01.1f.00.01.00.96.00.08.0a.00.00.04.0a.00.00.05.23.00.04.00.00.00.0a.26.00.04.00.00.00.0a,pause)
 
 reg1[0..1] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1);
     Cannot use 2-bit field reg1[0..1] where 1-bit field is required.
@@ -4653,10 +4653,10 @@ sleep 2
 as hv1 ovs-vsctl show
 
 # This shell function sends a DHCP request packet
-# test_dhcp INPORT SRC_MAC DHCP_TYPE BROADCAST CIADDR OFFER_IP REQUEST_IP USE_IP ...
+# test_dhcp INPORT SRC_MAC DHCP_TYPE BROADCAST CIADDR OFFER_IP REQUEST_IP ETH_BOOT USE_IP ...
 test_dhcp() {
-    local inport=$1 src_mac=$2 dhcp_type=$3 broadcast=$4 ciaddr=$5 offer_ip=$6 request_ip=$7 use_ip=$8
-    shift; shift; shift; shift; shift; shift; shift; shift;
+    local inport=$1 src_mac=$2 dhcp_type=$3 broadcast=$4 ciaddr=$5 offer_ip=$6 request_ip=$7 eth_boot=$8 use_ip=$9
+    shift; shift; shift; shift; shift; shift; shift; shift; shift;
 
     if test $use_ip != 0; then
         src_ip=$1
@@ -4668,11 +4668,21 @@ test_dhcp() {
     fi
 
     if test $request_ip != 0; then
-        ip_len=0120
-        udp_len=010b
+        if test $eth_boot != 0; then
+            ip_len=0124
+            udp_len=010f
+        else
+            ip_len=0120
+            udp_len=010b
+        fi
     else
-        ip_len=011a
-        udp_len=0106
+        if test $eth_boot != 0; then
+            ip_len=011e
+            udp_len=010a
+        else
+            ip_len=011a
+            udp_len=0106
+        fi
     fi
 
     if test $broadcast != 0; then
@@ -4709,6 +4719,9 @@ test_dhcp() {
         # dhcp requested ip
         request=${request}3204${request_ip}
     fi
+    if test $eth_boot != 0; then
+        request=${request}af020000
+    fi
     # dhcp end option
     request=${request}ff
 
@@ -4798,7 +4811,7 @@ server_ip=`ip_to_hex 10 0 0 1`
 ciaddr=`ip_to_hex 0 0 0 0`
 request_ip=0
 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000001 01 0 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
+test_dhcp 1 f00000000001 01 0 $ciaddr $offer_ip $request_ip 0 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 1.
 OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4824,7 +4837,7 @@ server_ip=`ip_to_hex 10 0 0 1`
 ciaddr=`ip_to_hex 0 0 0 0`
 request_ip=$offer_ip
 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 05 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 0 ff1000000001 $server_ip 05 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 2.
 OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4848,7 +4861,7 @@ server_ip=`ip_to_hex 10 0 0 1`
 ciaddr=`ip_to_hex 0 0 0 0`
 request_ip=`ip_to_hex 10 0 0 7`
 expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 06 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 0 ff1000000001 $server_ip 06 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 3.
 OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4872,7 +4885,7 @@ rm -f 2.expected
 ciaddr=`ip_to_hex 0 0 0 0`
 offer_ip=0
 request_ip=0
-test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 0 1 1
+test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 0 0 1 1
 
 # NXT_RESUMEs should be 4.
 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4889,12 +4902,12 @@ rm -f 2.expected
 # ls2-lp2 (vif4-tx.pcap) should receive the DHCPv4 request packet once.
 
 ciaddr=`ip_to_hex 0 0 0 0`
-test_dhcp 3 f00000000003 01 0 $ciaddr 0 0 4 0
+test_dhcp 3 f00000000003 01 0 $ciaddr 0 0 0 4 0
 
 # Send DHCPv4 packet on ls2-lp2. "router" DHCPv4 option is not defined for
 # this lport.
 ciaddr=`ip_to_hex 0 0 0 0`
-test_dhcp 4 f00000000004 01 0 $ciaddr 0 0 3 0
+test_dhcp 4 f00000000004 01 0 $ciaddr 0 0 0 3 0
 
 # NXT_RESUMEs should be 4.
 OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4911,7 +4924,7 @@ request_ip=0
 src_ip=$offer_ip
 dst_ip=$server_ip
 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 5.
 OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4937,7 +4950,7 @@ request_ip=0
 src_ip=$offer_ip
 dst_ip=`ip_to_hex 255 255 255 255`
 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 6.
 OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4963,7 +4976,7 @@ request_ip=0
 src_ip=$offer_ip
 dst_ip=`ip_to_hex 255 255 255 255`
 expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 7.
 OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -4989,7 +5002,7 @@ request_ip=0
 src_ip=$offer_ip
 dst_ip=`ip_to_hex 255 255 255 255`
 expected_dhcp_opts=""
-test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
+test_dhcp 2 f00000000002 03 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 06 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 8.
 OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5011,7 +5024,7 @@ rm -f 2.expected
 ciaddr=`ip_to_hex 0 0 0 0`
 src_ip=`ip_to_hex 10 0 0 6`
 dst_ip=`ip_to_hex 10 0 0 4`
-test_dhcp 2 f00000000002 03 0 $ciaddr 0 0 1 $src_ip $dst_ip 1
+test_dhcp 2 f00000000002 03 0 $ciaddr 0 0 0 1 $src_ip $dst_ip 1
 
 # NXT_RESUMEs should be 8.
 OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5030,7 +5043,7 @@ server_ip=`ip_to_hex 10 0 0 1`
 ciaddr=`ip_to_hex 0 0 0 0`
 request_ip=0
 expected_dhcp_opts=330400000e100104ffffff0003040a00000136040a000001
-test_dhcp 1 f00000000001 01 1 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
+test_dhcp 1 f00000000001 01 1 $ciaddr $offer_ip $request_ip 0 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
 
 # NXT_RESUMEs should be 9.
 OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5042,6 +5055,38 @@ AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
 cat 1.expected | cut -c 53- > expout
 AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
 
+reset_pcap_file hv1-vif1 hv1/vif1
+reset_pcap_file hv1-vif2 hv1/vif2
+rm -f 1.expected
+rm -f 2.expected
+
+# Send Etherboot.
+ovn-nbctl --all destroy dhcp-option
+
+ovn-nbctl dhcp-options-create 10.0.0.0/24
+d3=$(ovn-nbctl --bare --columns=_uuid find dhcp_options cidr="10.0.0.0/24")
+ovn-nbctl dhcp-options-set-options $d3 \
+   server_id=10.0.0.1 server_mac=ff:10:00:00:00:01 \
+   lease_time=3600 router=10.0.0.1 file=\"filename\" \
+   bootfile_name=\"bootfile\"
+
+ovn-nbctl lsp-set-dhcpv4-options ls1-lp1 $d3
+
+offer_ip=`ip_to_hex 10 0 0 4`
+server_ip=`ip_to_hex 10 0 0 1`
+ciaddr=`ip_to_hex 0 0 0 0`
+request_ip=0
+boofile=4308626f6f7466696c65
+expected_dhcp_opts=${boofile}330400000e100104ffffff0003040a00000136040a000001
+test_dhcp 1 f00000000001 01 0 $ciaddr $offer_ip $request_ip 1 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
+
+$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
+cat 1.expected | cut -c -48 > expout
+AT_CHECK([cat 1.packets | cut -c -48], [0], [expout])
+# Skipping the IPv4 checksum.
+cat 1.expected | cut -c 53- > expout
+AT_CHECK([cat 1.packets | cut -c 53-], [0], [expout])
+
 OVN_CLEANUP([hv1])
 
 AT_CLEANUP
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index a77d2f120..36c446067 100644
--- a/tests/test-ovn.c
+++ b/tests/test-ovn.c
@@ -189,6 +189,7 @@ create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
     dhcp_opt_add(dhcp_opts, "tftp_server_address", 150, "ipv4");
     dhcp_opt_add(dhcp_opts, "arp_cache_timeout", 35, "uint32");
     dhcp_opt_add(dhcp_opts, "tcp_keepalive_interval", 38, "uint32");
+    dhcp_opt_add(dhcp_opts, "file", 300, "str");
 
     /* DHCPv6 options. */
     hmap_init(dhcpv6_opts);
-- 
2.26.2



More information about the dev mailing list