From patchwork Fri Oct 23 10:27:42 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Lorenzo Bianconi
X-Patchwork-Id: 1386645
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org
(client-ip=140.211.166.137; helo=fraxinus.osuosl.org;
envelope-from=ovs-dev-bounces@openvswitch.org; receiver=)
Authentication-Results: ozlabs.org;
dmarc=fail (p=none dis=none) header.from=redhat.com
Authentication-Results: ozlabs.org;
dkim=fail reason="signature verification failed" (1024-bit key;
unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256
header.s=mimecast20190719 header.b=b1/tgVP8;
dkim-atps=neutral
Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 4CHgRb0XPXz9sSs
for ; Fri, 23 Oct 2020 21:28:11 +1100 (AEDT)
Received: from localhost (localhost [127.0.0.1])
by fraxinus.osuosl.org (Postfix) with ESMTP id E08BA87399;
Fri, 23 Oct 2020 10:28:08 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from fraxinus.osuosl.org ([127.0.0.1])
by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id GrQeidrEgCDs; Fri, 23 Oct 2020 10:28:06 +0000 (UTC)
Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])
by fraxinus.osuosl.org (Postfix) with ESMTP id 3187B8725A;
Fri, 23 Oct 2020 10:28:06 +0000 (UTC)
Received: from lf-lists.osuosl.org (localhost [127.0.0.1])
by lists.linuxfoundation.org (Postfix) with ESMTP id 1C7F8C0893;
Fri, 23 Oct 2020 10:28:06 +0000 (UTC)
X-Original-To: ovs-dev@openvswitch.org
Delivered-To: ovs-dev@lists.linuxfoundation.org
Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])
by lists.linuxfoundation.org (Postfix) with ESMTP id 85495C0052
for ; Fri, 23 Oct 2020 10:28:04 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by whitealder.osuosl.org (Postfix) with ESMTP id 7A69B86A27
for ; Fri, 23 Oct 2020 10:28:04 +0000 (UTC)
X-Virus-Scanned: amavisd-new at osuosl.org
Received: from whitealder.osuosl.org ([127.0.0.1])
by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id fDzex-WNbf2z for ;
Fri, 23 Oct 2020 10:28:02 +0000 (UTC)
X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6
Received: from us-smtp-delivery-124.mimecast.com
(us-smtp-delivery-124.mimecast.com [63.128.21.124])
by whitealder.osuosl.org (Postfix) with ESMTPS id E069886793
for ; Fri, 23 Oct 2020 10:28:01 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;
s=mimecast20190719; t=1603448880;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding;
bh=TWZWiTuUt1L48NjH9FNJlGzqjsTm6Bkzbh2+PvaXYEc=;
b=b1/tgVP8e/GIcWHgDbP73x6fcfZZ+te7Bf+5TEDSoYB9R1lQgzB+HpW3FwzX4wRlkI+LHK
fm3+4+6UooIM2NDpuGNfZIYBNJfC49oqVnJtxoKqFQ8H9fVcgav1V0J6CzuCk4ms8keUR+
5OZ6rcxzyiAaRNSMxi6jh5yO76ceUKg=
Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com
[209.85.128.72]) (Using TLS) by relay.mimecast.com with ESMTP id
us-mta-40-Rocubw1MNPmbHEeLEJm0yA-1; Fri, 23 Oct 2020 06:27:55 -0400
X-MC-Unique: Rocubw1MNPmbHEeLEJm0yA-1
Received: by mail-wm1-f72.google.com with SMTP id z62so362869wmb.1
for ; Fri, 23 Oct 2020 03:27:55 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version
:content-transfer-encoding;
bh=TWZWiTuUt1L48NjH9FNJlGzqjsTm6Bkzbh2+PvaXYEc=;
b=s0nysxcNrSfC4HORnGLw2VJ/k4/f4PWRw8Ir1q5K5TAX5Wmq4iPWM63s+/D8UGrYCe
CLcTFQinor/IufEw/2PSaVR/xprlmx09+fs+e/uh4whHUpPfRt45j5HBBVKPFyUFeDQV
AQzaDdsKCxNZ3ugDmhhB28u3Atg1KRR+E68wwGGckpc2FClS6FjZQvQEo3dlkwMjpnUD
L/flG8wT4CZbTCz48dPGy1HxSrDZB5B4kPyswDIpId1SGnUWspapAvaJ5UKzeKu76O8g
O5hiTpVFVnCRErYxcPzw5fezZkK03dsH5FOTr8pDsdCy8h11CNej7TQ9eysn3Tul4Rop
1Whg==
X-Gm-Message-State: AOAM530G92rzBzBD4BU/avR/lBp1ub4hNATkk4DW7wktqJfbq8Zra9St
84mTsFa1t4KHjkcPPZ25TQkoJtwN+KLM92qsXGPEVPoZcB3eefvxCxzWRMbbkGbVeG5CVQ7LNcP
Bq6/QG3g0Wnb6FnbzBQ==
X-Received: by 2002:adf:a51d:: with SMTP id i29mr1861360wrb.409.1603448873197;
Fri, 23 Oct 2020 03:27:53 -0700 (PDT)
X-Google-Smtp-Source:
ABdhPJx0vaIITx/mz85NLVQfevP/+R++Jb7kJmNA20YqLl/JL1mvTcWDzAAKcrXaJ4VFzNRv+DI08w==
X-Received: by 2002:adf:a51d:: with SMTP id i29mr1861295wrb.409.1603448872613;
Fri, 23 Oct 2020 03:27:52 -0700 (PDT)
Received: from lore-desk.redhat.com ([151.66.125.178])
by smtp.gmail.com with ESMTPSA id x18sm2679034wrg.4.2020.10.23.03.27.51
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Fri, 23 Oct 2020 03:27:52 -0700 (PDT)
From: Lorenzo Bianconi
To: ovs-dev@openvswitch.org
Date: Fri, 23 Oct 2020 12:27:42 +0200
Message-Id:
X-Mailer: git-send-email 2.26.2
MIME-Version: 1.0
Authentication-Results: relay.mimecast.com;
auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com
X-Mimecast-Spam-Score: 0
X-Mimecast-Originator: redhat.com
Cc: lmartins@redhat.com
Subject: [ovs-dev] [PATCH v3 ovn] dhcp: add iPXE support to OVN
X-BeenThere: ovs-dev@openvswitch.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id:
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: ovs-dev-bounces@openvswitch.org
Sender: "dev"
Add iPXE support to OVN introducing "bootfile_name_alt" dhcp option.
"bootfile_name_alt" dhcp userdata is encoded as option 254 since
it is not currently used.
When both "bootfile_name" and "bootfile_name_alt" are provided
by the CMS, "bootfile_name" will be used for option 67 if the
dhcp request contains etherboot option (175), otherwise
"bootfile_name_alt" will be used.
"bootfile_name" and "bootfile_name_alt" are placed just after offer_ip
in userdata buffer.
Tested-by: Lucas Alvares Gomes Martins
Signed-off-by: Lorenzo Bianconi
---
Changes since v2:
- encode "bootfile_name" and "bootfile_name_alt" are placed just after
offer_ip in userdata buffer in order to avoid loops in
pinctrl_handle_put_dhcp_opts()
Changes since v1:
- encode bootfile_name_alt option as 254 in order to not increase userdata
buffer size
---
controller/pinctrl.c | 30 ++++++++++++
lib/actions.c | 33 ++++++++++---
lib/ovn-l7.h | 7 +++
northd/ovn-northd.c | 1 +
ovn-nb.xml | 10 ++++
tests/ovn.at | 110 ++++++++++++++++++++++++++++++-------------
tests/test-ovn.c | 1 +
7 files changed, 154 insertions(+), 38 deletions(-)
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index d85ba504d..6f5499f0b 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -1868,6 +1868,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) {
@@ -1900,6 +1901,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;
}
@@ -2018,6 +2022,32 @@ pinctrl_handle_put_dhcp_opts(
*| 4 Bytes padding | 1 Byte (option end 0xFF ) | 4 Bytes padding|
* --------------------------------------------------------------
*/
+ struct dhcp_opt_header *in_dhcp_opt =
+ (struct dhcp_opt_header *)reply_dhcp_opts_ptr->data;
+ if (in_dhcp_opt->code == 67) { /* DHCP_OPT_BOOTFILENAME */
+ unsigned char *ptr = (unsigned char *)in_dhcp_opt;
+ int len = sizeof *in_dhcp_opt + in_dhcp_opt->len;
+ struct dhcp_opt_header *next_dhcp_opt =
+ (struct dhcp_opt_header *)(ptr + len);
+
+ if (next_dhcp_opt->code == 254) { /* DHCP_OPT_BOOTFILE_ALT */
+ if (!ipxe_req) {
+ ofpbuf_pull(reply_dhcp_opts_ptr, len);
+ next_dhcp_opt->code = 67;
+ } else {
+ char *buf = xmalloc(len);
+
+ memcpy(buf, in_dhcp_opt, len);
+ ofpbuf_pull(reply_dhcp_opts_ptr,
+ sizeof *in_dhcp_opt + next_dhcp_opt->len);
+ memcpy(reply_dhcp_opts_ptr->data, buf, len);
+ free(buf);
+ }
+ }
+ } else if (in_dhcp_opt->code == 254) { /* DHCP_OPT_BOOTFILE_ALT */
+ in_dhcp_opt->code = 67;
+ }
+
uint16_t new_l4_size = UDP_HEADER_LEN + DHCP_HEADER_LEN + 16;
if (msg_type != DHCP_MSG_NAK) {
new_l4_size += reply_dhcp_opts_ptr->size;
diff --git a/lib/actions.c b/lib/actions.c
index 1e1bdeff2..b0d03bc96 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -2086,10 +2086,10 @@ parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o,
}
static const struct ovnact_gen_option *
-find_offerip(const struct ovnact_gen_option *options, size_t n)
+find_opt(const struct ovnact_gen_option *options, size_t n, size_t code)
{
for (const struct ovnact_gen_option *o = options; o < &options[n]; o++) {
- if (o->option->code == 0) {
+ if (o->option->code == code) {
return o;
}
}
@@ -2288,7 +2288,7 @@ parse_put_dhcp_opts(struct action_context *ctx,
parse_put_opts(ctx, dst, po, dhcp_opts, opts_type);
if (!ctx->lexer->error && po->ovnact.type == OVNACT_PUT_DHCPV4_OPTS
- && !find_offerip(po->options, po->n_options)) {
+ && !find_opt(po->options, po->n_options, 0)) {
lexer_error(ctx->lexer,
"put_dhcp_opts requires offerip to be specified.");
return;
@@ -2537,14 +2537,35 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo,
/* Encode the offerip option first, because it's a special case and needs
* to be first in the actual DHCP response, and then encode the rest
* (skipping offerip the second time around). */
- const struct ovnact_gen_option *offerip_opt = find_offerip(
- pdo->options, pdo->n_options);
+ const struct ovnact_gen_option *offerip_opt = find_opt(
+ pdo->options, pdo->n_options, 0);
ovs_be32 offerip = offerip_opt->value.values[0].value.ipv4;
ofpbuf_put(ofpacts, &offerip, sizeof offerip);
+ /* Encode and bootfile_name opt (67) */
+ const struct ovnact_gen_option *boot_opt = find_opt(
+ pdo->options, pdo->n_options, 67);
+ if (boot_opt) {
+ uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
+ const union expr_constant *c = boot_opt->value.values;
+ opt_header[0] = boot_opt->option->code;
+ opt_header[1] = strlen(c->string);
+ ofpbuf_put(ofpacts, c->string, opt_header[1]);
+ }
+ /* Encode bootfile_name_alt opt (254) */
+ const struct ovnact_gen_option *boot_alt_opt = find_opt(
+ pdo->options, pdo->n_options, 254);
+ if (boot_alt_opt) {
+ uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
+ const union expr_constant *c = boot_alt_opt->value.values;
+ opt_header[0] = boot_alt_opt->option->code;
+ opt_header[1] = strlen(c->string);
+ ofpbuf_put(ofpacts, c->string, opt_header[1]);
+ }
+
for (const struct ovnact_gen_option *o = pdo->options;
o < &pdo->options[pdo->n_options]; o++) {
- if (o != offerip_opt) {
+ if (o != offerip_opt && o != boot_alt_opt && o != boot_opt) {
encode_put_dhcpv4_option(o, ofpacts);
}
}
diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index 30a795531..a2671ddd2 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -93,6 +93,13 @@ struct gen_opts_map {
#define DHCP_OPT_DOMAIN_SEARCH_LIST \
DHCP_OPTION("domain_search_list", 119, "domains")
+/* let's use unused 254 option for iPXE bootfile_name_alt
+ * userdata dhcp option
+ */
+#define DHCP_OPT_BOOTFILE_ALT DHCP_OPTION("bootfile_name_alt", 254, "str")
+
+#define DHCP_OPT_ETHERBOOT 175
+
#define DHCP_OPT_ARP_CACHE_TIMEOUT \
DHCP_OPTION("arp_cache_timeout", 35, "uint32")
#define DHCP_OPT_TCP_KEEPALIVE_INTERVAL \
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 5b76868df..a3cdf8afc 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -12472,6 +12472,7 @@ static struct gen_opts_map supported_dhcp_opts[] = {
DHCP_OPT_ARP_CACHE_TIMEOUT,
DHCP_OPT_TCP_KEEPALIVE_INTERVAL,
DHCP_OPT_DOMAIN_SEARCH_LIST,
+ DHCP_OPT_BOOTFILE_ALT,
};
static struct gen_opts_map supported_dhcpv6_opts[] = {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 86195af34..43694535e 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -3096,6 +3096,16 @@
resolving hostnames via the Domain Name System.
+
+
+
+
+ "bootfile_name_alt" option is used to support iPXE.
+ When both "bootfile_name" and "bootfile_name_alt" are provided
+ by the CMS, "bootfile_name" will be used for option 67 if the
+ dhcp request contains etherboot option (175), otherwise
+ "bootfile_name_alt" will be used.
+
diff --git a/tests/ovn.at b/tests/ovn.at
index 27a94e64f..60066ebe2 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1280,7 +1280,7 @@ 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)
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.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.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.d2.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)
@@ -1292,10 +1292,10 @@ reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
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.42.10.74.66.74.70.5f.73.65.72.76.65.72.5f.74.65.73.74,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",domain_search_list="ovn.org,abc.ovn.org");
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", domain_search_list = "ovn.org,abc.ovn.org");
- 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.77.0f.03.6f.76.6e.03.6f.72.67.00.03.61.62.63.c0.00,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.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.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.d2.09.2f.74.66.74.70.62.6f.6f.74.77.0f.03.6f.76.6e.03.6f.72.67.00.03.61.62.63.c0.00,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",domain_search_list="ovn.org,abc.ovn.org,def.ovn.org,ovn.test,def.ovn.test,test.org,abc.com");
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", domain_search_list = "ovn.org,abc.ovn.org,def.ovn.org,ovn.test,def.ovn.test,test.org,abc.com");
- 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.77.35.03.6f.76.6e.03.6f.72.67.00.03.61.62.63.c0.00.03.64.65.66.c0.00.03.6f.76.6e.04.74.65.73.74.00.03.64.65.66.c0.15.04.74.65.73.74.c0.04.03.61.62.63.03.63.6f.6d.00,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.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.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.d2.09.2f.74.66.74.70.62.6f.6f.74.77.35.03.6f.76.6e.03.6f.72.67.00.03.61.62.63.c0.00.03.64.65.66.c0.00.03.6f.76.6e.04.74.65.73.74.00.03.64.65.66.c0.15.04.74.65.73.74.c0.04.03.61.62.63.03.63.6f.6d.00,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.
@@ -5310,10 +5310,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
@@ -5325,11 +5325,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
@@ -5370,6 +5380,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
@@ -5465,7 +5478,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`])
@@ -5491,7 +5504,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`])
@@ -5515,7 +5528,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`])
@@ -5539,7 +5552,7 @@ rm -f 2.expected
ciaddr=`ip_to_hex 0 0 0 0`
offer_ip=0
request_ip=0
-test_dhcp 2 f00000000002 09 0 $ciaddr $offer_ip $request_ip 0 1 1
+test_dhcp 2 f00000000002 09 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`])
@@ -5556,18 +5569,18 @@ 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`])
-#OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
-#OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
+OVN_CHECK_PACKETS([hv1/vif3-tx.pcap], [3.expected])
+OVN_CHECK_PACKETS([hv1/vif4-tx.pcap], [4.expected])
# Send DHCPREQUEST in the RENEWING/REBINDING state with ip4.src set to 10.0.0.6
# and ip4.dst set to 10.0.0.1.
@@ -5578,7 +5591,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`])
@@ -5604,7 +5617,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`])
@@ -5630,7 +5643,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`])
@@ -5656,7 +5669,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`])
@@ -5678,7 +5691,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`])
@@ -5697,7 +5710,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`])
@@ -5720,7 +5733,7 @@ server_ip=`ip_to_hex 10 0 0 1`
ciaddr=`ip_to_hex 10 0 0 6`
request_ip=0
expected_dhcp_opts=0
-test_dhcp 2 f00000000002 07 0 $ciaddr $offer_ip $request_ip 0 ff1000000001
+test_dhcp 2 f00000000002 07 0 $ciaddr $offer_ip $request_ip 0 0 ff1000000001
# NXT_RESUMEs should be 10.
OVS_WAIT_UNTIL([test 10 = $(cat ofctl_monitor*.log | grep -c NXT_RESUME)])
@@ -5747,7 +5760,7 @@ dst_ip=$server_ip
# In the expected_dhcp_opts we should not see 330400000e10 which is
# dhcp lease time option and 0104ffffff00 which is subnet mask option.
expected_dhcp_opts=03040a00000136040a000001
-test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
+test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
# NXT_RESUMEs should be 11.
OVS_WAIT_UNTIL([test 11 = $(cat ofctl_monitor*.log | grep -c NXT_RESUME)])
@@ -5777,7 +5790,7 @@ dst_ip=$server_ip
# In the expected_dhcp_opts we should not see 330400000e10 which is
# dhcp lease time option.
expected_dhcp_opts=3a0400000fa0330400000e100104ffffff0003040a00000136040a000001
-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 12.
OVS_WAIT_UNTIL([test 12 = $(cat ofctl_monitor*.log | grep -c NXT_RESUME)])
@@ -5804,7 +5817,7 @@ dst_ip=$server_ip
# In the expected_dhcp_opts we should not see 330400000e10 which is
# dhcp lease time option and 0104ffffff00 which is subnet mask option.
expected_dhcp_opts=03040a00000136040a000001
-test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
+test_dhcp 2 f00000000002 08 0 $ciaddr $offer_ip $request_ip 0 1 $src_ip $dst_ip ff1000000001 $server_ip 05 $expected_dhcp_opts
# NXT_RESUMEs should be 13.
OVS_WAIT_UNTIL([test 13 = $(cat ofctl_monitor*.log | grep -c NXT_RESUME)])
@@ -5835,7 +5848,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=330400000e100104ffffff0003040a00000136040a00000142040a0a0a0a
-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 14.
OVS_WAIT_UNTIL([test 14 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5866,7 +5879,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=330400000e100104ffffff0003040a00000136040a0000014210746573745f746674705f736572766572
-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 15.
OVS_WAIT_UNTIL([test 15 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5897,7 +5910,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=771305746573743103636f6d00057465737432c006330400000e100104ffffff0003040a00000136040a000001
-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 16.
OVS_WAIT_UNTIL([test 16 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
@@ -5915,9 +5928,42 @@ server_ip=`ip_to_hex 10 0 0 1`
ciaddr=`ip_to_hex 0 0 0 0`
request_ip=0
expected_dhcp_opts=""
-test_dhcp 1 f00000000001 04 0 $ciaddr $offer_ip $request_ip 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
+test_dhcp 1 f00000000001 04 0 $ciaddr $offer_ip $request_ip 0 0 ff1000000001 $server_ip 02 $expected_dhcp_opts
AT_CHECK([fgrep -iq 'DHCPDECLINE from f0:00:00:00:00:01, 10.0.0.4 duplicated' hv1/ovn-controller.log], [0], [])
+# Send Etherboot.
+
+reset_pcap_file hv1-vif1 hv1/vif1
+reset_pcap_file hv1-vif2 hv1/vif2
+rm -f 1.expected
+rm -f 2.expected
+
+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 bootfile_name_alt=\"bootfile_name_alt\" \
+ 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 d94ab025d..80d99b7a8 100644
--- a/tests/test-ovn.c
+++ b/tests/test-ovn.c
@@ -191,6 +191,7 @@ create_gen_opts(struct hmap *dhcp_opts, struct hmap *dhcpv6_opts,
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, "domain_search_list", 119, "domains");
+ dhcp_opt_add(dhcp_opts, "bootfile_name_alt", 254, "str");
/* DHCPv6 options. */
hmap_init(dhcpv6_opts);