On Mon, Aug 22, 2022 at 3:46 PM Mark Michelson <[email protected]> wrote:
>
> From: Lucas Alvares Gomes <[email protected]>
>
> In order to PXE boot a baremetal server using the OVN DHCP server we
> need to allow users to set the "next-server" (siaddr) [0] field in the
> DHCP header.
>
> While investigating this issue by comparing the DHCPOFFER and DHCPACK
> packets sent my dnsmasq and OVN we saw that the "next-server" field
> was the problem for OVN, without it PXE booting was timing out while
> fetching the iPXE image from the TFTP server (see the bugzilla ticket
> below for reference).
>
> To confirm this problem we created a bogus patch hardcoding the TFTP
> address in the siaddr of the DHCP header (see the discussion in the
> maillist below) and with this in place we were able to deploy a
> baremetal node using the OVN DHCP end-to-end.
>
> This patch is a proper implementation that creates a new DHCP
> configuration option called "next_server" to allow users to set this
> field dynamically. This patch uses the DHCP code 253 which is a unsed
> code for DHCP specification as this is not a normal DHCP option but a
> special use case in OVN.
>
> [0]
> https://github.com/openvswitch/ovs/blob/9dd3031d2e0e9597449e95428320ccaaff7d8b3d/lib/dhcp.h#L42
>
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2083629
> Reported-at:
> https://mail.openvswitch.org/pipermail/ovs-discuss/2022-May/051821.html
> Signed-off-by: Lucas Alvares Gomes <[email protected]>
> Signed-off-by: Numan Siddique <[email protected]>
> (cherry picked from commit 0057cde2a64749bd2dbbaff525f7a1edccbd9c8a)
> Signed-off-by: Mark Michelson <[email protected]>
Is this patch still not merged to OVN 22.03 ? Since it already has
all the Acks and merged in the main branch. I think you can go ahead
and apply it.
+1 from me.
Thanks
Numan
> ---
> NEWS | 2 ++
> controller/pinctrl.c | 69 ++++++++++++++++++++++++++++++--------------
> lib/actions.c | 13 ++++++++-
> lib/ovn-l7.h | 8 +++++
> northd/ovn-northd.c | 1 +
> ovn-nb.xml | 7 +++++
> tests/ovn.at | 6 ++--
> tests/test-ovn.c | 1 +
> 8 files changed, 82 insertions(+), 25 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 73f92b447..6bd9f054d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -2,6 +2,8 @@ OVN v22.03.2 - xx xxx xxxx
> --------------------------
> - Support (LSP.options:qos_min_rate) to guarantee minimal bandwidth
> available
> for a logical port.
> + - Added support for setting the Next server IP in the DHCP header
> + using the private DHCP option - 253 in native OVN DHCPv4 responder.
>
> OVN v22.03.1 - 03 Jun 2022
> --------------------------
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 2c1dd8501..fd4d9a875 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -2206,30 +2206,56 @@ 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 == DHCP_OPT_BOOTFILE_CODE) {
> - 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 == DHCP_OPT_BOOTFILE_ALT_CODE) {
> - if (!ipxe_req) {
> - ofpbuf_pull(reply_dhcp_opts_ptr, len);
> - next_dhcp_opt->code = DHCP_OPT_BOOTFILE_CODE;
> - } else {
> - char *buf = xmalloc(len);
> + ovs_be32 next_server = in_dhcp_data->siaddr;
> + bool bootfile_name_set = false;
> + in_dhcp_ptr = reply_dhcp_opts_ptr->data;
> + end = (const char *)reply_dhcp_opts_ptr->data +
> reply_dhcp_opts_ptr->size;
> +
> + while (in_dhcp_ptr < end) {
> + struct dhcp_opt_header *in_dhcp_opt =
> + (struct dhcp_opt_header *)in_dhcp_ptr;
> +
> + switch (in_dhcp_opt->code) {
> + case DHCP_OPT_NEXT_SERVER_CODE:
> + next_server = get_unaligned_be32(DHCP_OPT_PAYLOAD(in_dhcp_opt));
> + break;
> + case DHCP_OPT_BOOTFILE_CODE: ;
> + 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 == DHCP_OPT_BOOTFILE_ALT_CODE) {
> + if (!ipxe_req) {
> + ofpbuf_pull(reply_dhcp_opts_ptr, len);
> + next_dhcp_opt->code = DHCP_OPT_BOOTFILE_CODE;
> + } 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);
> + 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);
> + }
> + }
> + bootfile_name_set = true;
> + break;
> + case DHCP_OPT_BOOTFILE_ALT_CODE:
> + if (!bootfile_name_set) {
> + in_dhcp_opt->code = DHCP_OPT_BOOTFILE_CODE;
> }
> + break;
> + }
> +
> + in_dhcp_ptr += sizeof *in_dhcp_opt;
> + if (in_dhcp_ptr > end) {
> + break;
> + }
> + in_dhcp_ptr += in_dhcp_opt->len;
> + if (in_dhcp_ptr > end) {
> + break;
> }
> - } else if (in_dhcp_opt->code == DHCP_OPT_BOOTFILE_ALT_CODE) {
> - in_dhcp_opt->code = DHCP_OPT_BOOTFILE_CODE;
> }
>
> uint16_t new_l4_size = UDP_HEADER_LEN + DHCP_HEADER_LEN + 16;
> @@ -2262,6 +2288,7 @@ pinctrl_handle_put_dhcp_opts(
>
> if (*in_dhcp_msg_type != OVN_DHCP_MSG_INFORM) {
> dhcp_data->yiaddr = (msg_type == DHCP_MSG_NAK) ? 0 : *offer_ip;
> + dhcp_data->siaddr = (msg_type == DHCP_MSG_NAK) ? 0 : next_server;
> } else {
> dhcp_data->yiaddr = 0;
> }
> diff --git a/lib/actions.c b/lib/actions.c
> index a9c27600c..24d6818c2 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -2862,10 +2862,21 @@ encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts
> *pdo,
> opt_header[1] = strlen(c->string);
> ofpbuf_put(ofpacts, c->string, opt_header[1]);
> }
> + /* Encode next_server opt (253) */
> + const struct ovnact_gen_option *next_server_opt = find_opt(
> + pdo->options, pdo->n_options, DHCP_OPT_NEXT_SERVER_CODE);
> + if (next_server_opt) {
> + uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
> + const union expr_constant *c = next_server_opt->value.values;
> + opt_header[0] = next_server_opt->option->code;
> + opt_header[1] = sizeof(ovs_be32);
> + ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
> + }
>
> for (size_t i = 0; i < pdo->n_options; i++) {
> const struct ovnact_gen_option *o = &pdo->options[i];
> - if (o != offerip_opt && o != boot_opt && o != boot_alt_opt) {
> + if (o != offerip_opt && o != boot_opt && o != boot_alt_opt && \
> + o != next_server_opt) {
> encode_put_dhcpv4_option(o, ofpacts);
> }
> }
> diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
> index 49ecea81f..0b2da9f7b 100644
> --- a/lib/ovn-l7.h
> +++ b/lib/ovn-l7.h
> @@ -145,6 +145,14 @@ struct gen_opts_map {
> #define DHCP_OPT_TCP_KEEPALIVE_INTERVAL \
> DHCP_OPTION("tcp_keepalive_interval", 38, "uint32")
>
> +/* Use unused 253 option for DHCP next-server DHCP option.
> + * This option is used for setting the "Next server IP address"
> + * field in the DHCP header.
> + */
> +#define DHCP_OPT_NEXT_SERVER_CODE 253
> +#define DHCP_OPT_NEXT_SERVER \
> + DHCP_OPTION("next_server", DHCP_OPT_NEXT_SERVER_CODE, "ipv4")
> +
> static inline uint32_t
> gen_opt_hash(char *opt_name)
> {
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index 9d191ce90..4d2baefe4 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -246,6 +246,7 @@ static struct gen_opts_map supported_dhcp_opts[] = {
> DHCP_OPT_BROADCAST_ADDRESS,
> DHCP_OPT_NETBIOS_NAME_SERVER,
> DHCP_OPT_NETBIOS_NODE_TYPE,
> + DHCP_OPT_NEXT_SERVER,
> };
>
> static struct gen_opts_map supported_dhcpv6_opts[] = {
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index db13e0ee5..765bab241 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -3549,6 +3549,13 @@
> </p>
> </column>
>
> + <column name="options" key="next_server">
> + <p>
> + The DHCPv4 option code for setting the "Next server IP
> + address" field in the DHCP header.
> + </p>
> + </column>
> +
> </group>
>
> <group title="Boolean DHCP Options">
> diff --git a/tests/ovn.at b/tests/ovn.at
> index adb64d775..71bffb8a0 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1404,9 +1404,9 @@ reg0[0] = lookup_arp_ip(inport, eth.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)
> -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.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)
> +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",
> next_server=10.0.0.9);
> + 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", next_server = 10.0.0.9);
> + 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.fd.04.0a.00.00.09.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)
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index 6704f612b..ea121efa7 100644
> --- a/tests/test-ovn.c
> +++ b/tests/test-ovn.c
> @@ -196,6 +196,7 @@ create_gen_opts(struct hmap *dhcp_opts, struct hmap
> *dhcpv6_opts,
> dhcp_opt_add(dhcp_opts, "broadcast_address", 28, "ipv4");
> dhcp_opt_add(dhcp_opts, "netbios_name_server", 44, "ipv4");
> dhcp_opt_add(dhcp_opts, "netbios_node_type", 46, "uint8");
> + dhcp_opt_add(dhcp_opts, "next_server", 253, "ipv4");
>
> /* DHCPv6 options. */
> hmap_init(dhcpv6_opts);
> --
> 2.37.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev