diff mbox series

[ovs-dev,v5,2/2,ovn] Add support for DHCP domain search option (119)

Message ID 1591908281-42017-2-git-send-email-svc.mail.git@nutanix.com
State New
Headers show
Series [ovs-dev,v5,1/2,ovn] Fix the data type for DHCP option tftp_server (66) | expand

Commit Message

svc.mail.git June 11, 2020, 8:44 p.m. UTC
From: Dhathri Purohith <svc.eng.git-patch@nutanix.com>

From: Dhathri Purohith <dhathri.purohith@nutanix.com>

Domain search list is encoded according to the specifications in RFC 1035,
section 4.1.4.

Signed-off-by: Dhathri Purohith <dhathri.purohith@nutanix.com>
Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com>
---
 lib/actions.c       | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/ovn-l7.h        |  3 ++
 northd/ovn-northd.c |  1 +
 ovn-nb.xml          | 15 +++++++++-
 ovn-sb.ovsschema    |  6 ++--
 ovn-sb.xml          | 11 +++++++
 tests/ovn.at        | 36 ++++++++++++++++++++++
 tests/test-ovn.c    |  1 +
 8 files changed, 154 insertions(+), 5 deletions(-)

Comments

0-day Robot June 11, 2020, 9 p.m. UTC | #1
Bleep bloop.  Greetings Ankur Sharma, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Ankur Sharma <ankur.sharma@nutanix.com>
Lines checked: 314, Warnings: 1, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
Numan Siddique June 17, 2020, 9:56 a.m. UTC | #2
Hi Dhathri,

Please see a few comments inline.



On Fri, Jun 12, 2020 at 2:14 AM Ankur Sharma <svc.mail.git@nutanix.com>
wrote:

> From: Dhathri Purohith <svc.eng.git-patch@nutanix.com>
>

This From is causing the author to have the email -
svc.eng.git-patch@nutanix.com.
Is this intentional ? It would be great if you could fix this and remove
this first "From".

>
> From: Dhathri Purohith <dhathri.purohith@nutanix.com>
>
> Domain search list is encoded according to the specifications in RFC 1035,
> section 4.1.4.
>
> Signed-off-by: Dhathri Purohith <dhathri.purohith@nutanix.com>
> Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com>
> ---
>  lib/actions.c       | 86
> ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  lib/ovn-l7.h        |  3 ++
>  northd/ovn-northd.c |  1 +
>  ovn-nb.xml          | 15 +++++++++-
>  ovn-sb.ovsschema    |  6 ++--
>  ovn-sb.xml          | 11 +++++++
>  tests/ovn.at        | 36 ++++++++++++++++++++++
>  tests/test-ovn.c    |  1 +
>  8 files changed, 154 insertions(+), 5 deletions(-)
>
> diff --git a/lib/actions.c b/lib/actions.c
> index f21be6d..24c9043 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -1982,7 +1982,8 @@ parse_gen_opt(struct action_context *ctx, struct
> ovnact_gen_option *o,
>          return;
>      }
>
> -    if (!strcmp(o->option->type, "str")) {
> +    if (!strcmp(o->option->type, "str") ||
> +        !strcmp(o->option->type, "domains")) {
>          if (o->value.type != EXPR_C_STRING) {
>              lexer_error(ctx->lexer, "%s option %s requires string value.",
>                          opts_type, o->option->name);
> @@ -2317,6 +2318,89 @@ encode_put_dhcpv4_option(const struct
> ovnact_gen_option *o,
>             opt_header[1] = sizeof(ovs_be32);
>             ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
>          }
> +    } else if (!strcmp(o->option->type, "domains")) {
> +        /* Please refer to RFC 1035, section 4.1.4 for the format of
> encoding
> +         * domain names. Below is an example for encoding a search list
> +         * consisting of the "abc.com" and "xyz.abc.com".
> +         *
> +         *
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> +         * |119|14 | 3 |'a'|'b'|'c'| 3 |'c'|'o'|'m'| 0
> |'x'|'y'|'z'|xC0|x00|
> +         *
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> +         *
> +         * The encoding of "abc.com" ends with 0 to mark the end of the
> +         * domain name as required by RFC 1035.
> +         *
> +         * The encoding of "xyz" (for "xyz.abc.com") ends with the
> two-octet
> +         * compression pointer C000 (hex), which points to offset 0 where
> +         * another validly encoded domain name can be found to complete
> +         * the name ("abc.com").
> +         *
>

I'm not very clear on what happens if the domains are set as - "www.ovn.org",
"www.ovn.foo", "ovn.test"
for example.

For the first domain - www.ovn.org, all 3 labels will be encoded right ?

And when it encounters the first label of 2nd domain, it would retrieve the
encoded offset of "www"
and stores it in the dns_encoded buffer.

The above example, is it a valid case ? or is it will assumed that there
will never be this kind of case ?



> +         * Encoding adds 2 bytes (one for length and one for delimiter)
> for
> +         * every domain name that is unique. If all the domain names are
> unique
> +         * (which probably never happens in real world), then encoded
> string
> +         * could be longer than the original string. Just to be on the
> safer
> +         * side, allocate the (approx.) worst case length here.
> +         */
> +        uint8_t *dns_encoded = xzalloc(2 * strlen(c->string));
> +        uint16_t encode_offset = 0;
> +        struct shash label_offset_map;
> +        shash_init(&label_offset_map);
> +        char *domain_list = xstrdup(c->string), *dom_ptr = NULL;
> +        for (char *domain = strtok_r(domain_list, ",", &dom_ptr);
> +             domain != NULL;
> +             domain = strtok_r(NULL, ",", &dom_ptr)) {
> +            if (strlen(domain) > DOMAIN_NAME_MAX_LEN) {
> +                VLOG_WARN("Domain names longer than 255 characters are
> not"
> +                          "supported");
> +                goto out;
> +            }
> +            char *label_ptr = NULL, *label;
> +            for (label = strtok_r(domain, ".", &label_ptr);
> +                 label != NULL;
> +                 label = strtok_r(NULL, ".", &label_ptr)) {
> +                /* Check if we have already encoded this label. If yes,
> +                 * fill in the reference and break. */
> +                uint16_t *get_offset;
> +                get_offset  = shash_find_data(&label_offset_map, label);
> +                if (get_offset != NULL) {
> +                    ovs_be16 temp = htons(0xc000) | htons(*get_offset);
> +                    memcpy(dns_encoded + encode_offset, &temp,
> +                        sizeof(temp));

+                    encode_offset += sizeof(temp);
> +                    break;
> +                } else {
> +                    /* The label was not encoded before, encode it now
> and add
> +                     * the offset to the label_offset_map. */
> +                    uint16_t *set_offset = xzalloc(sizeof(uint16_t));
> +                    memcpy(set_offset, &encode_offset, sizeof(uint16_t));
>

I think there is no need for memcpy. The below should do

*set_offset = encode_offset



> +                    shash_add_once(&label_offset_map, label, set_offset);
> +
> +                    uint8_t len = strlen(label);
> +                    memcpy(dns_encoded + encode_offset, &len,
> sizeof(uint8_t));
> +                    encode_offset += sizeof(uint8_t);
> +                    memcpy(dns_encoded + encode_offset, label, len);
> +                    encode_offset += len;
> +                }
> +            }
> +            /* Add the end marker (0 byte) to determine the end of the
> +             * domain. */
> +            if (label == NULL) {
> +                uint8_t end = 0;
> +                memcpy(dns_encoded + encode_offset, &end,
> sizeof(uint8_t));
> +                encode_offset += sizeof(uint8_t);
> +            }
> +        }
> +        opt_header[1] = encode_offset;
> +        ofpbuf_put(ofpacts, dns_encoded, encode_offset);
> +
> +        out:
> +            free(domain_list);
> +            free(dns_encoded);
> +            struct shash_node *node, *next;
> +            SHASH_FOR_EACH_SAFE (node, next, &label_offset_map) {
> +                shash_delete(&label_offset_map, node);
> +            }
> +            shash_destroy(&label_offset_map);
>      }
>  }
>
> diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
> index 38555db..f34bc0d 100644
> --- a/lib/ovn-l7.h
> +++ b/lib/ovn-l7.h
> @@ -34,6 +34,7 @@ struct gen_opts_map {
>      size_t code;
>  };
>
> +#define DOMAIN_NAME_MAX_LEN 255
>  #define DHCP_BROADCAST_FLAG 0x8000
>
>  #define DHCP_OPTION(NAME, CODE, TYPE) \
> @@ -81,6 +82,8 @@ 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")
> +#define DHCP_OPT_DOMAIN_SEARCH_LIST \
> +    DHCP_OPTION("domain_search_list", 119, "domains")
>
>  #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 ef08414..4ec2034 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -11336,6 +11336,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_DOMAIN_SEARCH_LIST,
>  };
>
>  static struct gen_opts_map supported_dhcpv6_opts[] = {
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 54f5301..80e843c 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -2939,7 +2939,7 @@
>          </column>
>        </group>
>
> -      <group title="Host_id DHCP Options">
> +      <group title="DHCP Options of type host_id">
>

This change should be ideally part of patch 1. When committing the patch 1
of the
series, I updated it.


Thanks
Numan



>          <p>
>            These options accept either an IPv4 address or a string value.
>          </p>
> @@ -2950,6 +2950,19 @@
>            </p>
>          </column>
>        </group>
> +
> +      <group title=" DHCP Options of type domains">
> +        <p>
> +          These options accept string value which is a comma separated
> +          list of domain names. The domain names are encoded based on RFC
> 1035.
> +        </p>
> +
> +        <column name="options" key="domain_search_list">
> +          <p>
> +            The DHCPv4 option code for this option is 119.
> +          </p>
> +        </column>
> +      </group>
>      </group>
>
>      <group title="DHCPv6 options">
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index 2ec729b..99c5de8 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Southbound",
> -    "version": "2.8.1",
> -    "cksum": "236203406 21905",
> +    "version": "2.8.2",
> +    "cksum": "464326363 21916",
>      "tables": {
>          "SB_Global": {
>              "columns": {
> @@ -218,7 +218,7 @@
>                          "type": "string",
>                          "enum": ["set", ["bool", "uint8", "uint16",
> "uint32",
>                                           "ipv4", "static_routes", "str",
> -                                         "host_id"]]}}}},
> +                                         "host_id", "domains"]]}}}},
>              "isRoot": true},
>          "DHCPv6_Options": {
>              "columns": {
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 208fb93..a6da80b 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -3232,6 +3232,17 @@ tcp.flags = RST;
>            </p>
>          </dd>
>
> +        <dt><code>value: domains</code></dt>
> +        <dd>
> +          <p>
> +            This indicates that the value of the DHCP option is a domain
> name
> +            or a comma separated list of domain names.
> +          </p>
> +
> +          <p>
> +            Example. "name=domain_search_list", "code=119",
> "type=domains".
> +          </p>
> +        </dd>
>        </dl>
>      </column>
>    </table>
> diff --git a/tests/ovn.at b/tests/ovn.at
> index d3b35ac..341641b 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1218,6 +1218,9 @@ reg0[15] =
> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
>  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="tftp_server_test");
>      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 = "tftp_server_test");
>      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)
>
>  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.
> @@ -1235,6 +1238,8 @@ reg1[0] = put_dhcp_opts(offerip="xyzzy");
>      DHCPv4 option offerip requires numeric value.
>  reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>      DHCPv4 option domain_name requires string value.
> +reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
> +    DHCPv4 option domain_search_list requires string value.
>
>  # nd_ns
>  nd_ns { nd.target = xxreg0; output; };
> @@ -5614,6 +5619,37 @@ AT_CHECK([cat 2.packets | cut -c -48], [0],
> [expout])
>  cat 2.expected | cut -c 53- > expout
>  AT_CHECK([cat 2.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
> +
> +# Set domain search list option for ls1
> +echo "------ Set domain search list --------"
> +ovn-nbctl dhcp-options-set-options $d1 server_id=10.0.0.1 \
> +server_mac=ff:10:00:00:00:01 lease_time=3600 router=10.0.0.1 \
> +domain_search_list=\"test1.com,test2.com\"
> +echo "------------------------------------------"
> +
> +# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
> +# address in the Requested IP Address option.
> +offer_ip=`ip_to_hex 10 0 0 6`
> +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
> +
> +# NXT_RESUMEs should be 12.
> +OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> +
> +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
> +cat 2.expected | cut -c -48 > expout
> +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> +# Skipping the IPv4 checksum.
> +cat 2.expected | cut -c 53- > expout
> +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> +
>  OVN_CLEANUP([hv1])
>
>  AT_CLEANUP
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index 4391694..b43f67f 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, "domain_search_list", 119, "domains");
>
>      /* DHCPv6 options. */
>      hmap_init(dhcpv6_opts);
> --
> 1.8.3.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Dhathri Purohith June 22, 2020, 3:23 p.m. UTC | #3
Hi Numan,

Thank you for your comments.
I have addressed all of them in v7.
Please see responses inline.

Thanks,
Dhathri

From: Numan Siddique <numans@ovn.org>
Date: Wednesday, June 17, 2020 at 2:56 AM
To: "svc.mail.git" <svc.mail.git@nutanix.com>
Cc: ovs-dev <ovs-dev@openvswitch.org>, Dhathri Purohith <dhathri.purohith@nutanix.com>, "svc.eng.git-patch" <svc.eng.git-patch@nutanix.com>
Subject: Re: [ovs-dev] [PATCH v5 2/2 ovn] Add support for DHCP domain search option (119)

Hi Dhathri,

Please see a few comments inline.



On Fri, Jun 12, 2020 at 2:14 AM Ankur Sharma <svc.mail.git@nutanix.com<mailto:svc.mail.git@nutanix.com>> wrote:
From: Dhathri Purohith <svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>>

This From is causing the author to have the email - svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>.
Is this intentional ? It would be great if you could fix this and remove this first "From".

Dhathri: Fixed.


From: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>>

Domain search list is encoded according to the specifications in RFC 1035,
section 4.1.4.

Signed-off-by: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>>
Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com<mailto:ankur.sharma@nutanix.com>>
---
 lib/actions.c       | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/ovn-l7.h        |  3 ++
 northd/ovn-northd.c |  1 +
 ovn-nb.xml          | 15 +++++++++-
 ovn-sb.ovsschema    |  6 ++--
 ovn-sb.xml          | 11 +++++++
 tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>        | 36 ++++++++++++++++++++++
 tests/test-ovn.c    |  1 +
 8 files changed, 154 insertions(+), 5 deletions(-)

diff --git a/lib/actions.c b/lib/actions.c
index f21be6d..24c9043 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1982,7 +1982,8 @@ parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o,
         return;
     }

-    if (!strcmp(o->option->type, "str")) {
+    if (!strcmp(o->option->type, "str") ||
+        !strcmp(o->option->type, "domains")) {
         if (o->value.type != EXPR_C_STRING) {
             lexer_error(ctx->lexer, "%s option %s requires string value.",
                         opts_type, o->option->name);
@@ -2317,6 +2318,89 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
            opt_header[1] = sizeof(ovs_be32);
            ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
         }
+    } else if (!strcmp(o->option->type, "domains")) {
+        /* Please refer to RFC 1035, section 4.1.4 for the format of encoding
+         * domain names. Below is an example for encoding a search list
+         * consisting of the "abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>" and "xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=>".
+         *
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         * |119|14 | 3 |'a'|'b'|'c'| 3 |'c'|'o'|'m'| 0 |'x'|'y'|'z'|xC0|x00|
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         *
+         * The encoding of "abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>" ends with 0 to mark the end of the
+         * domain name as required by RFC 1035.
+         *
+         * The encoding of "xyz" (for "xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=>") ends with the two-octet
+         * compression pointer C000 (hex), which points to offset 0 where
+         * another validly encoded domain name can be found to complete
+         * the name ("abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>").
+         *

I'm not very clear on what happens if the domains are set as - "www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>", "www.ovn.foo", "ovn.test"
for example.

For the first domain - www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>, all 3 labels will be encoded right ?

And when it encounters the first label of 2nd domain, it would retrieve the encoded offset of "www"
and stores it in the dns_encoded buffer.

The above example, is it a valid case ? or is it will assumed that there will never be this kind of case ?

Dhathri:
The above example is a valid case and the logic in v5 does not handle this. I have modified the
logic a bit in v7 to handle this case.
Instead of storing just the label offset, I am storing the offset of the complete suffix now.
For eg., consider domain www.ovn.org<http://www.ovn.org>, the map contains offset as follows:
www.ovn.org<http://www.ovn.org> : 0, ovn.org: 4, org: 9 and so on..
So, in the example list above all the three are considered different since none of them have common suffix
and are encoded separately.
On the other hand, if u consider an example like “ovn.com, test.ovn.com”, ovn.com is encoded completely
and for test.ovn.com, we encode test and add a pointer to encode “ovn.com” at offset 0.


+         * Encoding adds 2 bytes (one for length and one for delimiter) for
+         * every domain name that is unique. If all the domain names are unique
+         * (which probably never happens in real world), then encoded string
+         * could be longer than the original string. Just to be on the safer
+         * side, allocate the (approx.) worst case length here.
+         */
+        uint8_t *dns_encoded = xzalloc(2 * strlen(c->string));
+        uint16_t encode_offset = 0;
+        struct shash label_offset_map;
+        shash_init(&label_offset_map);
+        char *domain_list = xstrdup(c->string), *dom_ptr = NULL;
+        for (char *domain = strtok_r(domain_list, ",", &dom_ptr);
+             domain != NULL;
+             domain = strtok_r(NULL, ",", &dom_ptr)) {
+            if (strlen(domain) > DOMAIN_NAME_MAX_LEN) {
+                VLOG_WARN("Domain names longer than 255 characters are not"
+                          "supported");
+                goto out;
+            }
+            char *label_ptr = NULL, *label;
+            for (label = strtok_r(domain, ".", &label_ptr);
+                 label != NULL;
+                 label = strtok_r(NULL, ".", &label_ptr)) {
+                /* Check if we have already encoded this label. If yes,
+                 * fill in the reference and break. */
+                uint16_t *get_offset;
+                get_offset  = shash_find_data(&label_offset_map, label);
+                if (get_offset != NULL) {
+                    ovs_be16 temp = htons(0xc000) | htons(*get_offset);
+                    memcpy(dns_encoded + encode_offset, &temp,
+                        sizeof(temp));
+                    encode_offset += sizeof(temp);
+                    break;
+                } else {
+                    /* The label was not encoded before, encode it now and add
+                     * the offset to the label_offset_map. */
+                    uint16_t *set_offset = xzalloc(sizeof(uint16_t));
+                    memcpy(set_offset, &encode_offset, sizeof(uint16_t));

I think there is no need for memcpy. The below should do

*set_offset = encode_offset

Dhathri: Fixed.

+                    shash_add_once(&label_offset_map, label, set_offset);
+
+                    uint8_t len = strlen(label);
+                    memcpy(dns_encoded + encode_offset, &len, sizeof(uint8_t));
+                    encode_offset += sizeof(uint8_t);
+                    memcpy(dns_encoded + encode_offset, label, len);
+                    encode_offset += len;
+                }
+            }
+            /* Add the end marker (0 byte) to determine the end of the
+             * domain. */
+            if (label == NULL) {
+                uint8_t end = 0;
+                memcpy(dns_encoded + encode_offset, &end, sizeof(uint8_t));
+                encode_offset += sizeof(uint8_t);
+            }
+        }
+        opt_header[1] = encode_offset;
+        ofpbuf_put(ofpacts, dns_encoded, encode_offset);
+
+        out:
+            free(domain_list);
+            free(dns_encoded);
+            struct shash_node *node, *next;
+            SHASH_FOR_EACH_SAFE (node, next, &label_offset_map) {
+                shash_delete(&label_offset_map, node);
+            }
+            shash_destroy(&label_offset_map);
     }
 }

diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index 38555db..f34bc0d 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -34,6 +34,7 @@ struct gen_opts_map {
     size_t code;
 };

+#define DOMAIN_NAME_MAX_LEN 255
 #define DHCP_BROADCAST_FLAG 0x8000

 #define DHCP_OPTION(NAME, CODE, TYPE) \
@@ -81,6 +82,8 @@ 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")
+#define DHCP_OPT_DOMAIN_SEARCH_LIST \
+    DHCP_OPTION("domain_search_list", 119, "domains")

 #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 ef08414..4ec2034 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11336,6 +11336,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_DOMAIN_SEARCH_LIST,
 };

 static struct gen_opts_map supported_dhcpv6_opts[] = {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 54f5301..80e843c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2939,7 +2939,7 @@
         </column>
       </group>

-      <group title="Host_id DHCP Options">
+      <group title="DHCP Options of type host_id">

This change should be ideally part of patch 1. When committing the patch 1 of the
series, I updated it.

Dhathri: Thanks for taking care of this.

Thanks
Numan


         <p>
           These options accept either an IPv4 address or a string value.
         </p>
@@ -2950,6 +2950,19 @@
           </p>
         </column>
       </group>
+
+      <group title=" DHCP Options of type domains">
+        <p>
+          These options accept string value which is a comma separated
+          list of domain names. The domain names are encoded based on RFC 1035.
+        </p>
+
+        <column name="options" key="domain_search_list">
+          <p>
+            The DHCPv4 option code for this option is 119.
+          </p>
+        </column>
+      </group>
     </group>

     <group title="DHCPv6 options">
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 2ec729b..99c5de8 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
-    "version": "2.8.1",
-    "cksum": "236203406 21905",
+    "version": "2.8.2",
+    "cksum": "464326363 21916",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -218,7 +218,7 @@
                         "type": "string",
                         "enum": ["set", ["bool", "uint8", "uint16", "uint32",
                                          "ipv4", "static_routes", "str",
-                                         "host_id"]]}}}},
+                                         "host_id", "domains"]]}}}},
             "isRoot": true},
         "DHCPv6_Options": {
             "columns": {
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 208fb93..a6da80b 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -3232,6 +3232,17 @@ tcp.flags = RST;
           </p>
         </dd>

+        <dt><code>value: domains</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is a domain name
+            or a comma separated list of domain names.
+          </p>
+
+          <p>
+            Example. "name=domain_search_list", "code=119", "type=domains".
+          </p>
+        </dd>
       </dl>
     </column>
   </table>
diff --git a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=> b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
index d3b35ac..341641b 100644
--- a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
+++ b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
@@ -1218,6 +1218,9 @@ reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
 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 [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24-2C10.0.0.4-2C40.0.0.0_16-2C10.0.0.6-2C0.0.0.0_0-2C10.0.0.1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=wdr-Bfnw1YQsMFk3lK4ISS7qkgVMM2LqtUx_wOslBgM&e=>},ethernet_encap=1,router_discovery=0,tftp_server="tftp_server_test");
     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 [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=jPzQEAy7PN42s197eBqdp9wT6EmKoGwvreQoMEwTp1k&e=>, 10.0.0.4, 40.0.0.0/16 [40.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__40.0.0.0_16&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=SMRXQUYRT5CjcQS_tqr1ZjRXX_PcABh4XZc-hL1CtWI&e=>, 10.0.0.6, 0.0.0.0/0 [0.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__0.0.0.0_0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=YIa8Shs2WH_UM_xJexbFp1DuvNVNGCP5w3_E2JSKF-g&e=>, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server = "tftp_server_test");
     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 [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>",wpad="https://example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=>",bootfile_name="https://127.0.0.1/boot.ipxe [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=>",path_prefix="/tftpboot",domain_search_list="ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>,abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=>");
+    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 [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>", wpad = "https://example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=>", bootfile_name = "https://127.0.0.1/boot.ipxe [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=>", path_prefix = "/tftpboot", domain_search_list = "ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>,abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=>");
+    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)

 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.
@@ -1235,6 +1238,8 @@ reg1[0] = put_dhcp_opts(offerip="xyzzy");
     DHCPv4 option offerip requires numeric value.
 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
     DHCPv4 option domain_name requires string value.
+reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
+    DHCPv4 option domain_search_list requires string value.

 # nd_ns
 nd_ns { nd.target = xxreg0; output; };
@@ -5614,6 +5619,37 @@ AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
 cat 2.expected | cut -c 53- > expout
 AT_CHECK([cat 2.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
+
+# Set domain search list option for ls1
+echo "------ Set domain search list --------"
+ovn-nbctl dhcp-options-set-options $d1 server_id=10.0.0.1 \
+server_mac=ff:10:00:00:00:01 lease_time=3600 router=10.0.0.1 \
+domain_search_list=\"test1.com [test1.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test1.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=krkp1wCWn04vRYNtzZulRgFiSh5iktt19NBTzZIWT2w&e=>,test2.com [test2.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test2.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=rESEUxbIJ5ifZXQDrtPa6ej3CHZ4-PlOq7iLo8gQVuA&e=>\"
+echo "------------------------------------------"
+
+# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
+# address in the Requested IP Address option.
+offer_ip=`ip_to_hex 10 0 0 6`
+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
+
+# NXT_RESUMEs should be 12.
+OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in [ovs-pcap.in]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovs-2Dpcap.in&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Qg06pjiY6Zi3rh0FEjbgKQIX9B77evnYpZpBHaFpIzU&e=>" hv1/vif2-tx.pcap > 2.packets
+cat 2.expected | cut -c -48 > expout
+AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
+# Skipping the IPv4 checksum.
+cat 2.expected | cut -c 53- > expout
+AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
+
 OVN_CLEANUP([hv1])

 AT_CLEANUP
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index 4391694..b43f67f 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, "domain_search_list", 119, "domains");

     /* DHCPv6 options. */
     hmap_init(dhcpv6_opts);
--
1.8.3.1
Numan Siddique June 22, 2020, 3:29 p.m. UTC | #4
On Mon, Jun 22, 2020 at 8:54 PM Dhathri Purohith <
dhathri.purohith@nutanix.com> wrote:

> Hi Numan,
>
> Thank you for your comments.
> I have addressed all of them in v7.
> Please see responses inline.
>

Thanks. I'll take a look.
It will be great if you could capture what changed from the previous
version for your future patches :)
This makes it a bit easier for the reviewers to figure out what changed
between versions.

One example here -
https://patchwork.ozlabs.org/project/openvswitch/patch/20200622111100.838586-1-numans@ovn.org/

Thanks
Numan


> Thanks,
> Dhathri
>
> From: Numan Siddique <numans@ovn.org>
> Date: Wednesday, June 17, 2020 at 2:56 AM
> To: "svc.mail.git" <svc.mail.git@nutanix.com>
> Cc: ovs-dev <ovs-dev@openvswitch.org>, Dhathri Purohith <
> dhathri.purohith@nutanix.com>, "svc.eng.git-patch" <
> svc.eng.git-patch@nutanix.com>
> Subject: Re: [ovs-dev] [PATCH v5 2/2 ovn] Add support for DHCP domain
> search option (119)
>
> Hi Dhathri,
>
> Please see a few comments inline.
>
>
>
> On Fri, Jun 12, 2020 at 2:14 AM Ankur Sharma <svc.mail.git@nutanix.com
> <mailto:svc.mail.git@nutanix.com>> wrote:
> From: Dhathri Purohith <svc.eng.git-patch@nutanix.com<mailto:
> svc.eng.git-patch@nutanix.com>>
>
> This From is causing the author to have the email -
> svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>.
> Is this intentional ? It would be great if you could fix this and remove
> this first "From".
>
> Dhathri: Fixed.
>
>
> From: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:
> dhathri.purohith@nutanix.com>>
>
> Domain search list is encoded according to the specifications in RFC 1035,
> section 4.1.4.
>
> Signed-off-by: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:
> dhathri.purohith@nutanix.com>>
> Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com<mailto:
> ankur.sharma@nutanix.com>>
> ---
>  lib/actions.c       | 86
> ++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  lib/ovn-l7.h        |  3 ++
>  northd/ovn-northd.c |  1 +
>  ovn-nb.xml          | 15 +++++++++-
>  ovn-sb.ovsschema    |  6 ++--
>  ovn-sb.xml          | 11 +++++++
>  tests/ovn.at [ovn.at]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
>       | 36 ++++++++++++++++++++++
>  tests/test-ovn.c    |  1 +
>  8 files changed, 154 insertions(+), 5 deletions(-)
>
> diff --git a/lib/actions.c b/lib/actions.c
> index f21be6d..24c9043 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -1982,7 +1982,8 @@ parse_gen_opt(struct action_context *ctx, struct
> ovnact_gen_option *o,
>          return;
>      }
>
> -    if (!strcmp(o->option->type, "str")) {
> +    if (!strcmp(o->option->type, "str") ||
> +        !strcmp(o->option->type, "domains")) {
>          if (o->value.type != EXPR_C_STRING) {
>              lexer_error(ctx->lexer, "%s option %s requires string value.",
>                          opts_type, o->option->name);
> @@ -2317,6 +2318,89 @@ encode_put_dhcpv4_option(const struct
> ovnact_gen_option *o,
>             opt_header[1] = sizeof(ovs_be32);
>             ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
>          }
> +    } else if (!strcmp(o->option->type, "domains")) {
> +        /* Please refer to RFC 1035, section 4.1.4 for the format of
> encoding
> +         * domain names. Below is an example for encoding a search list
> +         * consisting of the "abc.com [abc.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>"
> and "xyz.abc.com [xyz.abc.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=
> >".
> +         *
> +         *
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> +         * |119|14 | 3 |'a'|'b'|'c'| 3 |'c'|'o'|'m'| 0
> |'x'|'y'|'z'|xC0|x00|
> +         *
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> +         *
> +         * The encoding of "abc.com [abc.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>"
> ends with 0 to mark the end of the
> +         * domain name as required by RFC 1035.
> +         *
> +         * The encoding of "xyz" (for "xyz.abc.com [xyz.abc.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=>")
> ends with the two-octet
> +         * compression pointer C000 (hex), which points to offset 0 where
> +         * another validly encoded domain name can be found to complete
> +         * the name ("abc.com [abc.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=
> >").
> +         *
>
> I'm not very clear on what happens if the domains are set as - "
> www.ovn.org [ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>",
> "www.ovn.foo", "ovn.test"
> for example.
>
> For the first domain - www.ovn.org [ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>,
> all 3 labels will be encoded right ?
>
> And when it encounters the first label of 2nd domain, it would retrieve
> the encoded offset of "www"
> and stores it in the dns_encoded buffer.
>
> The above example, is it a valid case ? or is it will assumed that there
> will never be this kind of case ?
>
> Dhathri:
> The above example is a valid case and the logic in v5 does not handle
> this. I have modified the
> logic a bit in v7 to handle this case.
> Instead of storing just the label offset, I am storing the offset of the
> complete suffix now.
> For eg., consider domain www.ovn.org<http://www.ovn.org>, the map
> contains offset as follows:
> www.ovn.org<http://www.ovn.org> : 0, ovn.org: 4, org: 9 and so on..
> So, in the example list above all the three are considered different since
> none of them have common suffix
> and are encoded separately.
> On the other hand, if u consider an example like “ovn.com, test.ovn.com”,
> ovn.com is encoded completely
> and for test.ovn.com, we encode test and add a pointer to encode “ovn.com”
> at offset 0.
>
>
> +         * Encoding adds 2 bytes (one for length and one for delimiter)
> for
> +         * every domain name that is unique. If all the domain names are
> unique
> +         * (which probably never happens in real world), then encoded
> string
> +         * could be longer than the original string. Just to be on the
> safer
> +         * side, allocate the (approx.) worst case length here.
> +         */
> +        uint8_t *dns_encoded = xzalloc(2 * strlen(c->string));
> +        uint16_t encode_offset = 0;
> +        struct shash label_offset_map;
> +        shash_init(&label_offset_map);
> +        char *domain_list = xstrdup(c->string), *dom_ptr = NULL;
> +        for (char *domain = strtok_r(domain_list, ",", &dom_ptr);
> +             domain != NULL;
> +             domain = strtok_r(NULL, ",", &dom_ptr)) {
> +            if (strlen(domain) > DOMAIN_NAME_MAX_LEN) {
> +                VLOG_WARN("Domain names longer than 255 characters are
> not"
> +                          "supported");
> +                goto out;
> +            }
> +            char *label_ptr = NULL, *label;
> +            for (label = strtok_r(domain, ".", &label_ptr);
> +                 label != NULL;
> +                 label = strtok_r(NULL, ".", &label_ptr)) {
> +                /* Check if we have already encoded this label. If yes,
> +                 * fill in the reference and break. */
> +                uint16_t *get_offset;
> +                get_offset  = shash_find_data(&label_offset_map, label);
> +                if (get_offset != NULL) {
> +                    ovs_be16 temp = htons(0xc000) | htons(*get_offset);
> +                    memcpy(dns_encoded + encode_offset, &temp,
> +                        sizeof(temp));
> +                    encode_offset += sizeof(temp);
> +                    break;
> +                } else {
> +                    /* The label was not encoded before, encode it now
> and add
> +                     * the offset to the label_offset_map. */
> +                    uint16_t *set_offset = xzalloc(sizeof(uint16_t));
> +                    memcpy(set_offset, &encode_offset, sizeof(uint16_t));
>
> I think there is no need for memcpy. The below should do
>
> *set_offset = encode_offset
>
> Dhathri: Fixed.
>
> +                    shash_add_once(&label_offset_map, label, set_offset);
> +
> +                    uint8_t len = strlen(label);
> +                    memcpy(dns_encoded + encode_offset, &len,
> sizeof(uint8_t));
> +                    encode_offset += sizeof(uint8_t);
> +                    memcpy(dns_encoded + encode_offset, label, len);
> +                    encode_offset += len;
> +                }
> +            }
> +            /* Add the end marker (0 byte) to determine the end of the
> +             * domain. */
> +            if (label == NULL) {
> +                uint8_t end = 0;
> +                memcpy(dns_encoded + encode_offset, &end,
> sizeof(uint8_t));
> +                encode_offset += sizeof(uint8_t);
> +            }
> +        }
> +        opt_header[1] = encode_offset;
> +        ofpbuf_put(ofpacts, dns_encoded, encode_offset);
> +
> +        out:
> +            free(domain_list);
> +            free(dns_encoded);
> +            struct shash_node *node, *next;
> +            SHASH_FOR_EACH_SAFE (node, next, &label_offset_map) {
> +                shash_delete(&label_offset_map, node);
> +            }
> +            shash_destroy(&label_offset_map);
>      }
>  }
>
> diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
> index 38555db..f34bc0d 100644
> --- a/lib/ovn-l7.h
> +++ b/lib/ovn-l7.h
> @@ -34,6 +34,7 @@ struct gen_opts_map {
>      size_t code;
>  };
>
> +#define DOMAIN_NAME_MAX_LEN 255
>  #define DHCP_BROADCAST_FLAG 0x8000
>
>  #define DHCP_OPTION(NAME, CODE, TYPE) \
> @@ -81,6 +82,8 @@ 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")
> +#define DHCP_OPT_DOMAIN_SEARCH_LIST \
> +    DHCP_OPTION("domain_search_list", 119, "domains")
>
>  #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 ef08414..4ec2034 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -11336,6 +11336,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_DOMAIN_SEARCH_LIST,
>  };
>
>  static struct gen_opts_map supported_dhcpv6_opts[] = {
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 54f5301..80e843c 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -2939,7 +2939,7 @@
>          </column>
>        </group>
>
> -      <group title="Host_id DHCP Options">
> +      <group title="DHCP Options of type host_id">
>
> This change should be ideally part of patch 1. When committing the patch 1
> of the
> series, I updated it.
>
> Dhathri: Thanks for taking care of this.
>
> Thanks
> Numan
>
>
>          <p>
>            These options accept either an IPv4 address or a string value.
>          </p>
> @@ -2950,6 +2950,19 @@
>            </p>
>          </column>
>        </group>
> +
> +      <group title=" DHCP Options of type domains">
> +        <p>
> +          These options accept string value which is a comma separated
> +          list of domain names. The domain names are encoded based on RFC
> 1035.
> +        </p>
> +
> +        <column name="options" key="domain_search_list">
> +          <p>
> +            The DHCPv4 option code for this option is 119.
> +          </p>
> +        </column>
> +      </group>
>      </group>
>
>      <group title="DHCPv6 options">
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index 2ec729b..99c5de8 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_Southbound",
> -    "version": "2.8.1",
> -    "cksum": "236203406 21905",
> +    "version": "2.8.2",
> +    "cksum": "464326363 21916",
>      "tables": {
>          "SB_Global": {
>              "columns": {
> @@ -218,7 +218,7 @@
>                          "type": "string",
>                          "enum": ["set", ["bool", "uint8", "uint16",
> "uint32",
>                                           "ipv4", "static_routes", "str",
> -                                         "host_id"]]}}}},
> +                                         "host_id", "domains"]]}}}},
>              "isRoot": true},
>          "DHCPv6_Options": {
>              "columns": {
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 208fb93..a6da80b 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -3232,6 +3232,17 @@ tcp.flags = RST;
>            </p>
>          </dd>
>
> +        <dt><code>value: domains</code></dt>
> +        <dd>
> +          <p>
> +            This indicates that the value of the DHCP option is a domain
> name
> +            or a comma separated list of domain names.
> +          </p>
> +
> +          <p>
> +            Example. "name=domain_search_list", "code=119",
> "type=domains".
> +          </p>
> +        </dd>
>        </dl>
>      </column>
>    </table>
> diff --git a/tests/ovn.at [ovn.at]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
> b/tests/ovn.at [ovn.at]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=
> >
> index d3b35ac..341641b 100644
> --- a/tests/ovn.at [ovn.at]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=
> >
> +++ b/tests/ovn.at [ovn.at]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=
> >
> @@ -1218,6 +1218,9 @@ reg0[15] =
> put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
>  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 [30.0.0.0]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24-2C10.0.0.4-2C40.0.0.0_16-2C10.0.0.6-2C0.0.0.0_0-2C10.0.0.1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=wdr-Bfnw1YQsMFk3lK4ISS7qkgVMM2LqtUx_wOslBgM&e=
> >},ethernet_encap=1,router_discovery=0,tftp_server="tftp_server_test");
>      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 [30.0.0.0]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=jPzQEAy7PN42s197eBqdp9wT6EmKoGwvreQoMEwTp1k&e=>,
> 10.0.0.4, 40.0.0.0/16 [40.0.0.0]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__40.0.0.0_16&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=SMRXQUYRT5CjcQS_tqr1ZjRXX_PcABh4XZc-hL1CtWI&e=>,
> 10.0.0.6, 0.0.0.0/0 [0.0.0.0]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__0.0.0.0_0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=YIa8Shs2WH_UM_xJexbFp1DuvNVNGCP5w3_E2JSKF-g&e=>,
> 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server =
> "tftp_server_test");
>      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 [ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=
> >",wpad="https://example.org [example.org]<
> https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=
> >",bootfile_name="https://127.0.0.1/boot.ipxe [127.0.0.1]<
> https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=
> >",path_prefix="/tftpboot",domain_search_list="ovn.org [ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=
> >,abc.ovn.org [abc.ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=
> >");
> +    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 [
> ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>",
> wpad = "https://example.org [example.org]<
> https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=>",
> bootfile_name = "https://127.0.0.1/boot.ipxe [127.0.0.1]<
> https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=>",
> path_prefix = "/tftpboot", domain_search_list = "ovn.org [ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=
> >,abc.ovn.org [abc.ovn.org]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=
> >");
> +    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)
>
>  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.
> @@ -1235,6 +1238,8 @@ reg1[0] = put_dhcp_opts(offerip="xyzzy");
>      DHCPv4 option offerip requires numeric value.
>  reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
>      DHCPv4 option domain_name requires string value.
> +reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
> +    DHCPv4 option domain_search_list requires string value.
>
>  # nd_ns
>  nd_ns { nd.target = xxreg0; output; };
> @@ -5614,6 +5619,37 @@ AT_CHECK([cat 2.packets | cut -c -48], [0],
> [expout])
>  cat 2.expected | cut -c 53- > expout
>  AT_CHECK([cat 2.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
> +
> +# Set domain search list option for ls1
> +echo "------ Set domain search list --------"
> +ovn-nbctl dhcp-options-set-options $d1 server_id=10.0.0.1 \
> +server_mac=ff:10:00:00:00:01 lease_time=3600 router=10.0.0.1 \
> +domain_search_list=\"test1.com [test1.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__test1.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=krkp1wCWn04vRYNtzZulRgFiSh5iktt19NBTzZIWT2w&e=
> >,test2.com [test2.com]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__test2.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=rESEUxbIJ5ifZXQDrtPa6ej3CHZ4-PlOq7iLo8gQVuA&e=
> >\"
> +echo "------------------------------------------"
> +
> +# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
> +# address in the Requested IP Address option.
> +offer_ip=`ip_to_hex 10 0 0 6`
> +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
> +
> +# NXT_RESUMEs should be 12.
> +OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
> +
> +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in [ovs-pcap.in]<
> https://urldefense.proofpoint.com/v2/url?u=http-3A__ovs-2Dpcap.in&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Qg06pjiY6Zi3rh0FEjbgKQIX9B77evnYpZpBHaFpIzU&e=>"
> hv1/vif2-tx.pcap > 2.packets
> +cat 2.expected | cut -c -48 > expout
> +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
> +# Skipping the IPv4 checksum.
> +cat 2.expected | cut -c 53- > expout
> +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
> +
>  OVN_CLEANUP([hv1])
>
>  AT_CLEANUP
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index 4391694..b43f67f 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, "domain_search_list", 119, "domains");
>
>      /* DHCPv6 options. */
>      hmap_init(dhcpv6_opts);
> --
> 1.8.3.1
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org<mailto:dev@openvswitch.org>
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev [
> mail.openvswitch.org]<
> https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=d7_Dhkx2Jn_WNOojKwRYB_0E5rL53bvMsp0hKPxaTmo&e=
> >
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
Dhathri Purohith June 22, 2020, 3:34 p.m. UTC | #5
Sure, will keep that in mind for future patches 😊

Thanks,
Dhathri

From: Numan Siddique <numans@ovn.org>
Date: Monday, June 22, 2020 at 8:29 AM
To: Dhathri Purohith <dhathri.purohith@nutanix.com>
Cc: "svc.mail.git" <svc.mail.git@nutanix.com>, ovs-dev <ovs-dev@openvswitch.org>, "svc.eng.git-patch" <svc.eng.git-patch@nutanix.com>
Subject: Re: [ovs-dev] [PATCH v5 2/2 ovn] Add support for DHCP domain search option (119)



On Mon, Jun 22, 2020 at 8:54 PM Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>> wrote:
Hi Numan,

Thank you for your comments.
I have addressed all of them in v7.
Please see responses inline.

Thanks. I'll take a look.
It will be great if you could capture what changed from the previous version for your future patches :)
This makes it a bit easier for the reviewers to figure out what changed between versions.

One example here -  https://patchwork.ozlabs.org/project/openvswitch/patch/20200622111100.838586-1-numans@ovn.org/ [patchwork.ozlabs.org]<https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.ozlabs.org_project_openvswitch_patch_20200622111100.838586-2D1-2Dnumans-40ovn.org_&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=xBq--SwIxe3KNip3zK5fvVxivZhYBBta8M8Oe0rqNB4&e=>

Thanks
Numan


Thanks,
Dhathri

From: Numan Siddique <numans@ovn.org<mailto:numans@ovn.org>>
Date: Wednesday, June 17, 2020 at 2:56 AM
To: "svc.mail.git" <svc.mail.git@nutanix.com<mailto:svc.mail.git@nutanix.com>>
Cc: ovs-dev <ovs-dev@openvswitch.org<mailto:ovs-dev@openvswitch.org>>, Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>>, "svc.eng.git-patch" <svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>>
Subject: Re: [ovs-dev] [PATCH v5 2/2 ovn] Add support for DHCP domain search option (119)

Hi Dhathri,

Please see a few comments inline.



On Fri, Jun 12, 2020 at 2:14 AM Ankur Sharma <svc.mail.git@nutanix.com<mailto:svc.mail.git@nutanix.com><mailto:svc.mail.git@nutanix.com<mailto:svc.mail.git@nutanix.com>>> wrote:
From: Dhathri Purohith <svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com><mailto:svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>>>

This From is causing the author to have the email - svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com><mailto:svc.eng.git-patch@nutanix.com<mailto:svc.eng.git-patch@nutanix.com>>.
Is this intentional ? It would be great if you could fix this and remove this first "From".

Dhathri: Fixed.


From: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com><mailto:dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>>>

Domain search list is encoded according to the specifications in RFC 1035,
section 4.1.4.

Signed-off-by: Dhathri Purohith <dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com><mailto:dhathri.purohith@nutanix.com<mailto:dhathri.purohith@nutanix.com>>>
Signed-off-by: Ankur Sharma <ankur.sharma@nutanix.com<mailto:ankur.sharma@nutanix.com><mailto:ankur.sharma@nutanix.com<mailto:ankur.sharma@nutanix.com>>>
---
 lib/actions.c       | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lib/ovn-l7.h        |  3 ++
 northd/ovn-northd.c |  1 +
 ovn-nb.xml          | 15 +++++++++-
 ovn-sb.ovsschema    |  6 ++--
 ovn-sb.xml          | 11 +++++++
 tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=> [ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>        | 36 ++++++++++++++++++++++
 tests/test-ovn.c    |  1 +
 8 files changed, 154 insertions(+), 5 deletions(-)

diff --git a/lib/actions.c b/lib/actions.c
index f21be6d..24c9043 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1982,7 +1982,8 @@ parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o,
         return;
     }

-    if (!strcmp(o->option->type, "str")) {
+    if (!strcmp(o->option->type, "str") ||
+        !strcmp(o->option->type, "domains")) {
         if (o->value.type != EXPR_C_STRING) {
             lexer_error(ctx->lexer, "%s option %s requires string value.",
                         opts_type, o->option->name);
@@ -2317,6 +2318,89 @@ encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
            opt_header[1] = sizeof(ovs_be32);
            ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
         }
+    } else if (!strcmp(o->option->type, "domains")) {
+        /* Please refer to RFC 1035, section 4.1.4 for the format of encoding
+         * domain names. Below is an example for encoding a search list
+         * consisting of the "abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=> [abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>" and "xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=TxRba5c2gOMHyG5thfrdBT5eV94KevEt1qYiXHAb_p4&e=> [xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=TxRba5c2gOMHyG5thfrdBT5eV94KevEt1qYiXHAb_p4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=>".
+         *
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         * |119|14 | 3 |'a'|'b'|'c'| 3 |'c'|'o'|'m'| 0 |'x'|'y'|'z'|xC0|x00|
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         *
+         * The encoding of "abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=> [abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>" ends with 0 to mark the end of the
+         * domain name as required by RFC 1035.
+         *
+         * The encoding of "xyz" (for "xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=TxRba5c2gOMHyG5thfrdBT5eV94KevEt1qYiXHAb_p4&e=> [xyz.abc.com [xyz.abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=TxRba5c2gOMHyG5thfrdBT5eV94KevEt1qYiXHAb_p4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__xyz.abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=EQFeKZzTG2c-BfR73VtaK_JHhbrMDkhc_sc2QFRAz8I&e=>") ends with the two-octet
+         * compression pointer C000 (hex), which points to offset 0 where
+         * another validly encoded domain name can be found to complete
+         * the name ("abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=> [abc.com [abc.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=AxN-llKNspL8k62b36vwfLLCqOEYvZRcL8KOn3_6wHw&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gLDx5i1CC_LwFcQpZ0la06s2TOX3coHKM8Fa7eyYhOc&e=>").
+         *

I'm not very clear on what happens if the domains are set as - "www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>", "www.ovn.foo", "ovn.test"
for example.

For the first domain - www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=gTVqxikIUskbhkPyqlSMvGiSIkinaDnPtDXDe7R5co0&e=>, all 3 labels will be encoded right ?

And when it encounters the first label of 2nd domain, it would retrieve the encoded offset of "www"
and stores it in the dns_encoded buffer.

The above example, is it a valid case ? or is it will assumed that there will never be this kind of case ?

Dhathri:
The above example is a valid case and the logic in v5 does not handle this. I have modified the
logic a bit in v7 to handle this case.
Instead of storing just the label offset, I am storing the offset of the complete suffix now.
For eg., consider domain www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=><http://www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=>>, the map contains offset as follows:
www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=><http://www.ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__www.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ZO8JXjz_KzNwRlftIouDSirFPDN3glndtG6i6AoPBBU&e=>> : 0, ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>: 4, org: 9 and so on..
So, in the example list above all the three are considered different since none of them have common suffix
and are encoded separately.
On the other hand, if u consider an example like “ovn.com [ovn.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=L01WQPONmyp8BNe9AKMHTJ51GFdqYN3jVn9h6cqALRY&e=>, test.ovn.com [test.ovn.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test.ovn.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=70V9f-ALR2xz-v7OF_oDYhYV8S5MORXpKpGAnyQGw_Q&e=>”, ovn.com [ovn.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=L01WQPONmyp8BNe9AKMHTJ51GFdqYN3jVn9h6cqALRY&e=> is encoded completely
and for test.ovn.com [test.ovn.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test.ovn.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=70V9f-ALR2xz-v7OF_oDYhYV8S5MORXpKpGAnyQGw_Q&e=>, we encode test and add a pointer to encode “ovn.com [ovn.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=L01WQPONmyp8BNe9AKMHTJ51GFdqYN3jVn9h6cqALRY&e=>” at offset 0.


+         * Encoding adds 2 bytes (one for length and one for delimiter) for
+         * every domain name that is unique. If all the domain names are unique
+         * (which probably never happens in real world), then encoded string
+         * could be longer than the original string. Just to be on the safer
+         * side, allocate the (approx.) worst case length here.
+         */
+        uint8_t *dns_encoded = xzalloc(2 * strlen(c->string));
+        uint16_t encode_offset = 0;
+        struct shash label_offset_map;
+        shash_init(&label_offset_map);
+        char *domain_list = xstrdup(c->string), *dom_ptr = NULL;
+        for (char *domain = strtok_r(domain_list, ",", &dom_ptr);
+             domain != NULL;
+             domain = strtok_r(NULL, ",", &dom_ptr)) {
+            if (strlen(domain) > DOMAIN_NAME_MAX_LEN) {
+                VLOG_WARN("Domain names longer than 255 characters are not"
+                          "supported");
+                goto out;
+            }
+            char *label_ptr = NULL, *label;
+            for (label = strtok_r(domain, ".", &label_ptr);
+                 label != NULL;
+                 label = strtok_r(NULL, ".", &label_ptr)) {
+                /* Check if we have already encoded this label. If yes,
+                 * fill in the reference and break. */
+                uint16_t *get_offset;
+                get_offset  = shash_find_data(&label_offset_map, label);
+                if (get_offset != NULL) {
+                    ovs_be16 temp = htons(0xc000) | htons(*get_offset);
+                    memcpy(dns_encoded + encode_offset, &temp,
+                        sizeof(temp));
+                    encode_offset += sizeof(temp);
+                    break;
+                } else {
+                    /* The label was not encoded before, encode it now and add
+                     * the offset to the label_offset_map. */
+                    uint16_t *set_offset = xzalloc(sizeof(uint16_t));
+                    memcpy(set_offset, &encode_offset, sizeof(uint16_t));

I think there is no need for memcpy. The below should do

*set_offset = encode_offset

Dhathri: Fixed.

+                    shash_add_once(&label_offset_map, label, set_offset);
+
+                    uint8_t len = strlen(label);
+                    memcpy(dns_encoded + encode_offset, &len, sizeof(uint8_t));
+                    encode_offset += sizeof(uint8_t);
+                    memcpy(dns_encoded + encode_offset, label, len);
+                    encode_offset += len;
+                }
+            }
+            /* Add the end marker (0 byte) to determine the end of the
+             * domain. */
+            if (label == NULL) {
+                uint8_t end = 0;
+                memcpy(dns_encoded + encode_offset, &end, sizeof(uint8_t));
+                encode_offset += sizeof(uint8_t);
+            }
+        }
+        opt_header[1] = encode_offset;
+        ofpbuf_put(ofpacts, dns_encoded, encode_offset);
+
+        out:
+            free(domain_list);
+            free(dns_encoded);
+            struct shash_node *node, *next;
+            SHASH_FOR_EACH_SAFE (node, next, &label_offset_map) {
+                shash_delete(&label_offset_map, node);
+            }
+            shash_destroy(&label_offset_map);
     }
 }

diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index 38555db..f34bc0d 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -34,6 +34,7 @@ struct gen_opts_map {
     size_t code;
 };

+#define DOMAIN_NAME_MAX_LEN 255
 #define DHCP_BROADCAST_FLAG 0x8000

 #define DHCP_OPTION(NAME, CODE, TYPE) \
@@ -81,6 +82,8 @@ 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")
+#define DHCP_OPT_DOMAIN_SEARCH_LIST \
+    DHCP_OPTION("domain_search_list", 119, "domains")

 #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 ef08414..4ec2034 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11336,6 +11336,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_DOMAIN_SEARCH_LIST,
 };

 static struct gen_opts_map supported_dhcpv6_opts[] = {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 54f5301..80e843c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2939,7 +2939,7 @@
         </column>
       </group>

-      <group title="Host_id DHCP Options">
+      <group title="DHCP Options of type host_id">

This change should be ideally part of patch 1. When committing the patch 1 of the
series, I updated it.

Dhathri: Thanks for taking care of this.

Thanks
Numan


         <p>
           These options accept either an IPv4 address or a string value.
         </p>
@@ -2950,6 +2950,19 @@
           </p>
         </column>
       </group>
+
+      <group title=" DHCP Options of type domains">
+        <p>
+          These options accept string value which is a comma separated
+          list of domain names. The domain names are encoded based on RFC 1035.
+        </p>
+
+        <column name="options" key="domain_search_list">
+          <p>
+            The DHCPv4 option code for this option is 119.
+          </p>
+        </column>
+      </group>
     </group>

     <group title="DHCPv6 options">
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 2ec729b..99c5de8 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Southbound",
-    "version": "2.8.1",
-    "cksum": "236203406 21905",
+    "version": "2.8.2",
+    "cksum": "464326363 21916",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -218,7 +218,7 @@
                         "type": "string",
                         "enum": ["set", ["bool", "uint8", "uint16", "uint32",
                                          "ipv4", "static_routes", "str",
-                                         "host_id"]]}}}},
+                                         "host_id", "domains"]]}}}},
             "isRoot": true},
         "DHCPv6_Options": {
             "columns": {
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 208fb93..a6da80b 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -3232,6 +3232,17 @@ tcp.flags = RST;
           </p>
         </dd>

+        <dt><code>value: domains</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is a domain name
+            or a comma separated list of domain names.
+          </p>
+
+          <p>
+            Example. "name=domain_search_list", "code=119", "type=domains".
+          </p>
+        </dd>
       </dl>
     </column>
   </table>
diff --git a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=> [ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=> b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=> [ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
index d3b35ac..341641b 100644
--- a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=> [ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
+++ b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=> [ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=ufd1ADp-zeSzLqB8LOfGIyUDLhyYdjZFznn4LZgkUO4&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=c2WtekklDoN4tWqGNgpxg5c96-Oc8zvaj8WuC6ao_U0&e=>
@@ -1218,6 +1218,9 @@ reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
 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 [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24-2C10.0.0.4-2C40.0.0.0_16-2C10.0.0.6-2C0.0.0.0_0-2C10.0.0.1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=96m5vXho5SJG50a0a1r6IlF-47jvr-F2m3RpQu9swqg&e=> [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24-2C10.0.0.4-2C40.0.0.0_16-2C10.0.0.6-2C0.0.0.0_0-2C10.0.0.1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=wdr-Bfnw1YQsMFk3lK4ISS7qkgVMM2LqtUx_wOslBgM&e=>},ethernet_encap=1,router_discovery=0,tftp_server="tftp_server_test");
     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 [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=OiDe-I1hW7GJhmHM5UowTFA-PsxGKMlYXkLXQTKZHXw&e=> [30.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__30.0.0.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=jPzQEAy7PN42s197eBqdp9wT6EmKoGwvreQoMEwTp1k&e=>, 10.0.0.4, 40.0.0.0/16 [40.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__40.0.0.0_16&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=VbhkCANppqejMxP59B629YqB-Aj6tt3g1L14CKHlZWs&e=> [40.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__40.0.0.0_16&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=SMRXQUYRT5CjcQS_tqr1ZjRXX_PcABh4XZc-hL1CtWI&e=>, 10.0.0.6, 0.0.0.0/0 [0.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__0.0.0.0_0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=kOjuAYotxb4oiaw_G9u8gTT2Se4p1zlEUKooEpO-BC0&e=> [0.0.0.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__0.0.0.0_0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=YIa8Shs2WH_UM_xJexbFp1DuvNVNGCP5w3_E2JSKF-g&e=>, 10.0.0.1}, ethernet_encap = 1, router_discovery = 0, tftp_server = "tftp_server_test");
     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 [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>",wpad="https://example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=Fx11SSyu-c1FGv5EcIFceZTFE-uU5izYatqFg8Mt85I&e=> [example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=izZzxH9QyOY4qT1ffpkDyc4PyQPcgoWz05dfsKVuE3A&e=>]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=>",bootfile_name="https://127.0.0.1/boot.ipxe [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=2crX1h3AeWdd_X4k7_8f6i2nb-21sA1YY0MyfADaHPI&e=> [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=>",path_prefix="/tftpboot",domain_search_list="ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>,abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=5CxCdFet9w3ujZL_BbbvUQoNnxWm3YpjB3lKkFxTp7M&e=> [abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=5CxCdFet9w3ujZL_BbbvUQoNnxWm3YpjB3lKkFxTp7M&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=>");
+    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 [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>", wpad = "https://example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=Fx11SSyu-c1FGv5EcIFceZTFE-uU5izYatqFg8Mt85I&e=> [example.org [example.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=izZzxH9QyOY4qT1ffpkDyc4PyQPcgoWz05dfsKVuE3A&e=>]<https://urldefense.proofpoint.com/v2/url?u=https-3A__example.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=KyEVWVJgjyFlDh-n-OIT4w_csx7KzHD_pTAh1kj2mkE&e=>", bootfile_name = "https://127.0.0.1/boot.ipxe [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=2crX1h3AeWdd_X4k7_8f6i2nb-21sA1YY0MyfADaHPI&e=> [127.0.0.1]<https://urldefense.proofpoint.com/v2/url?u=https-3A__127.0.0.1_boot.ipxe&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Gge0dpzCf-pYXFbN-HA8-8mUKe2KRgbzE_P8bVV9yN0&e=>", path_prefix = "/tftpboot", domain_search_list = "ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=> [ovn.org [ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=upBq528A1jWw23q1mxc-RQz6TXFA2aUr9_sP4IYWa-0&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=nak5ZNmfRpwgCbATULIF8_a8MsC9ww7yrWXow6zWPrA&e=>,abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=5CxCdFet9w3ujZL_BbbvUQoNnxWm3YpjB3lKkFxTp7M&e=> [abc.ovn.org [abc.ovn.org]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=5CxCdFet9w3ujZL_BbbvUQoNnxWm3YpjB3lKkFxTp7M&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__abc.ovn.org&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=NeQ_rpQSLpg_H-Xud8paNbbEkM-LwXhQmMInOaKxOa8&e=>");
+    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)

 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.
@@ -1235,6 +1238,8 @@ reg1[0] = put_dhcp_opts(offerip="xyzzy");
     DHCPv4 option offerip requires numeric value.
 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
     DHCPv4 option domain_name requires string value.
+reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
+    DHCPv4 option domain_search_list requires string value.

 # nd_ns
 nd_ns { nd.target = xxreg0; output; };
@@ -5614,6 +5619,37 @@ AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
 cat 2.expected | cut -c 53- > expout
 AT_CHECK([cat 2.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
+
+# Set domain search list option for ls1
+echo "------ Set domain search list --------"
+ovn-nbctl dhcp-options-set-options $d1 server_id=10.0.0.1 \
+server_mac=ff:10:00:00:00:01 lease_time=3600 router=10.0.0.1 \
+domain_search_list=\"test1.com [test1.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test1.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=8l4tuj9zrNbddA6Xj26dQO8a27EYm8Viu20m3RmrQ-o&e=> [test1.com [test1.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test1.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=8l4tuj9zrNbddA6Xj26dQO8a27EYm8Viu20m3RmrQ-o&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test1.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=krkp1wCWn04vRYNtzZulRgFiSh5iktt19NBTzZIWT2w&e=>,test2.com [test2.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test2.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=gO5co6tk5tHmA44176nyF1_YjSCxdHhido3oewkwwPc&e=> [test2.com [test2.com]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test2.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=gO5co6tk5tHmA44176nyF1_YjSCxdHhido3oewkwwPc&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__test2.com&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=rESEUxbIJ5ifZXQDrtPa6ej3CHZ4-PlOq7iLo8gQVuA&e=>\"
+echo "------------------------------------------"
+
+# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
+# address in the Requested IP Address option.
+offer_ip=`ip_to_hex 10 0 0 6`
+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
+
+# NXT_RESUMEs should be 12.
+OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in [ovs-pcap.in]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovs-2Dpcap.in&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=WkGlIDM4wjYK8f_-DhuqALUyyl3agEZtmtRhW7MOiTQ&e=> [ovs-pcap.in [ovs-pcap.in]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovs-2Dpcap.in&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=9yv1YWK149Il7Yy7MrtCTFcVQ3jGL624ZLwd8aCKVOI&s=WkGlIDM4wjYK8f_-DhuqALUyyl3agEZtmtRhW7MOiTQ&e=>]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovs-2Dpcap.in&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=dftLCwr11LPmmIAnjdakaot5N4f-Q2Qfwcs7XdgQZXE&m=h-etkJUAQ5sCe-M0eGSnFFCA5zXBVet15Ljzxnax3cM&s=Qg06pjiY6Zi3rh0FEjbgKQIX9B77evnYpZpBHaFpIzU&e=>" hv1/vif2-tx.pcap > 2.packets
+cat 2.expected | cut -c -48 > expout
+AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
+# Skipping the IPv4 checksum.
+cat 2.expected | cut -c 53- > expout
+AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
+
 OVN_CLEANUP([hv1])

 AT_CLEANUP
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index 4391694..b43f67f 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, "domain_search_list", 119, "domains");

     /* DHCPv6 options. */
     hmap_init(dhcpv6_opts);
--
1.8.3.1
diff mbox series

Patch

diff --git a/lib/actions.c b/lib/actions.c
index f21be6d..24c9043 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1982,7 +1982,8 @@  parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o,
         return;
     }
 
-    if (!strcmp(o->option->type, "str")) {
+    if (!strcmp(o->option->type, "str") ||
+        !strcmp(o->option->type, "domains")) {
         if (o->value.type != EXPR_C_STRING) {
             lexer_error(ctx->lexer, "%s option %s requires string value.",
                         opts_type, o->option->name);
@@ -2317,6 +2318,89 @@  encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
            opt_header[1] = sizeof(ovs_be32);
            ofpbuf_put(ofpacts, &c->value.ipv4, sizeof(ovs_be32));
         }
+    } else if (!strcmp(o->option->type, "domains")) {
+        /* Please refer to RFC 1035, section 4.1.4 for the format of encoding
+         * domain names. Below is an example for encoding a search list
+         * consisting of the "abc.com" and "xyz.abc.com".
+         *
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         * |119|14 | 3 |'a'|'b'|'c'| 3 |'c'|'o'|'m'| 0 |'x'|'y'|'z'|xC0|x00|
+         * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+         *
+         * The encoding of "abc.com" ends with 0 to mark the end of the
+         * domain name as required by RFC 1035.
+         *
+         * The encoding of "xyz" (for "xyz.abc.com") ends with the two-octet
+         * compression pointer C000 (hex), which points to offset 0 where
+         * another validly encoded domain name can be found to complete
+         * the name ("abc.com").
+         *
+         * Encoding adds 2 bytes (one for length and one for delimiter) for
+         * every domain name that is unique. If all the domain names are unique
+         * (which probably never happens in real world), then encoded string
+         * could be longer than the original string. Just to be on the safer
+         * side, allocate the (approx.) worst case length here.
+         */
+        uint8_t *dns_encoded = xzalloc(2 * strlen(c->string));
+        uint16_t encode_offset = 0;
+        struct shash label_offset_map;
+        shash_init(&label_offset_map);
+        char *domain_list = xstrdup(c->string), *dom_ptr = NULL;
+        for (char *domain = strtok_r(domain_list, ",", &dom_ptr);
+             domain != NULL;
+             domain = strtok_r(NULL, ",", &dom_ptr)) {
+            if (strlen(domain) > DOMAIN_NAME_MAX_LEN) {
+                VLOG_WARN("Domain names longer than 255 characters are not"
+                          "supported");
+                goto out;
+            }
+            char *label_ptr = NULL, *label;
+            for (label = strtok_r(domain, ".", &label_ptr);
+                 label != NULL;
+                 label = strtok_r(NULL, ".", &label_ptr)) {
+                /* Check if we have already encoded this label. If yes,
+                 * fill in the reference and break. */
+                uint16_t *get_offset;
+                get_offset  = shash_find_data(&label_offset_map, label);
+                if (get_offset != NULL) {
+                    ovs_be16 temp = htons(0xc000) | htons(*get_offset);
+                    memcpy(dns_encoded + encode_offset, &temp,
+                        sizeof(temp));
+                    encode_offset += sizeof(temp);
+                    break;
+                } else {
+                    /* The label was not encoded before, encode it now and add
+                     * the offset to the label_offset_map. */
+                    uint16_t *set_offset = xzalloc(sizeof(uint16_t));
+                    memcpy(set_offset, &encode_offset, sizeof(uint16_t));
+                    shash_add_once(&label_offset_map, label, set_offset);
+
+                    uint8_t len = strlen(label);
+                    memcpy(dns_encoded + encode_offset, &len, sizeof(uint8_t));
+                    encode_offset += sizeof(uint8_t);
+                    memcpy(dns_encoded + encode_offset, label, len);
+                    encode_offset += len;
+                }
+            }
+            /* Add the end marker (0 byte) to determine the end of the
+             * domain. */
+            if (label == NULL) {
+                uint8_t end = 0;
+                memcpy(dns_encoded + encode_offset, &end, sizeof(uint8_t));
+                encode_offset += sizeof(uint8_t);
+            }
+        }
+        opt_header[1] = encode_offset;
+        ofpbuf_put(ofpacts, dns_encoded, encode_offset);
+
+        out:
+            free(domain_list);
+            free(dns_encoded);
+            struct shash_node *node, *next;
+            SHASH_FOR_EACH_SAFE (node, next, &label_offset_map) {
+                shash_delete(&label_offset_map, node);
+            }
+            shash_destroy(&label_offset_map);
     }
 }
 
diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
index 38555db..f34bc0d 100644
--- a/lib/ovn-l7.h
+++ b/lib/ovn-l7.h
@@ -34,6 +34,7 @@  struct gen_opts_map {
     size_t code;
 };
 
+#define DOMAIN_NAME_MAX_LEN 255
 #define DHCP_BROADCAST_FLAG 0x8000
 
 #define DHCP_OPTION(NAME, CODE, TYPE) \
@@ -81,6 +82,8 @@  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")
+#define DHCP_OPT_DOMAIN_SEARCH_LIST \
+    DHCP_OPTION("domain_search_list", 119, "domains")
 
 #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 ef08414..4ec2034 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -11336,6 +11336,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_DOMAIN_SEARCH_LIST,
 };
 
 static struct gen_opts_map supported_dhcpv6_opts[] = {
diff --git a/ovn-nb.xml b/ovn-nb.xml
index 54f5301..80e843c 100644
--- a/ovn-nb.xml
+++ b/ovn-nb.xml
@@ -2939,7 +2939,7 @@ 
         </column>
       </group>
 
-      <group title="Host_id DHCP Options">
+      <group title="DHCP Options of type host_id">
         <p>
           These options accept either an IPv4 address or a string value.
         </p>
@@ -2950,6 +2950,19 @@ 
           </p>
         </column>
       </group>
+
+      <group title=" DHCP Options of type domains">
+        <p>
+          These options accept string value which is a comma separated
+          list of domain names. The domain names are encoded based on RFC 1035.
+        </p>
+
+        <column name="options" key="domain_search_list">
+          <p>
+            The DHCPv4 option code for this option is 119.
+          </p>
+        </column>
+      </group>
     </group>
 
     <group title="DHCPv6 options">
diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
index 2ec729b..99c5de8 100644
--- a/ovn-sb.ovsschema
+++ b/ovn-sb.ovsschema
@@ -1,7 +1,7 @@ 
 {
     "name": "OVN_Southbound",
-    "version": "2.8.1",
-    "cksum": "236203406 21905",
+    "version": "2.8.2",
+    "cksum": "464326363 21916",
     "tables": {
         "SB_Global": {
             "columns": {
@@ -218,7 +218,7 @@ 
                         "type": "string",
                         "enum": ["set", ["bool", "uint8", "uint16", "uint32",
                                          "ipv4", "static_routes", "str",
-                                         "host_id"]]}}}},
+                                         "host_id", "domains"]]}}}},
             "isRoot": true},
         "DHCPv6_Options": {
             "columns": {
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 208fb93..a6da80b 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -3232,6 +3232,17 @@  tcp.flags = RST;
           </p>
         </dd>
 
+        <dt><code>value: domains</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is a domain name
+            or a comma separated list of domain names.
+          </p>
+
+          <p>
+            Example. "name=domain_search_list", "code=119", "type=domains".
+          </p>
+        </dd>
       </dl>
     </column>
   </table>
diff --git a/tests/ovn.at b/tests/ovn.at
index d3b35ac..341641b 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1218,6 +1218,9 @@  reg0[15] = put_dhcp_opts(offerip=10.0.0.4,router=10.0.0.1,netmask=255.255.255.0,
 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="tftp_server_test");
     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 = "tftp_server_test");
     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)
 
 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.
@@ -1235,6 +1238,8 @@  reg1[0] = put_dhcp_opts(offerip="xyzzy");
     DHCPv4 option offerip requires numeric value.
 reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_name=1.2.3.4);
     DHCPv4 option domain_name requires string value.
+reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain_search_list=1.2.3.4);
+    DHCPv4 option domain_search_list requires string value.
 
 # nd_ns
 nd_ns { nd.target = xxreg0; output; };
@@ -5614,6 +5619,37 @@  AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
 cat 2.expected | cut -c 53- > expout
 AT_CHECK([cat 2.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
+
+# Set domain search list option for ls1
+echo "------ Set domain search list --------"
+ovn-nbctl dhcp-options-set-options $d1 server_id=10.0.0.1 \
+server_mac=ff:10:00:00:00:01 lease_time=3600 router=10.0.0.1 \
+domain_search_list=\"test1.com,test2.com\"
+echo "------------------------------------------"
+
+# Send DHCPREQUEST in the SELECTING/INIT-REBOOT state with the offered IP
+# address in the Requested IP Address option.
+offer_ip=`ip_to_hex 10 0 0 6`
+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
+
+# NXT_RESUMEs should be 12.
+OVS_WAIT_UNTIL([test 12 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
+cat 2.expected | cut -c -48 > expout
+AT_CHECK([cat 2.packets | cut -c -48], [0], [expout])
+# Skipping the IPv4 checksum.
+cat 2.expected | cut -c 53- > expout
+AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout])
+
 OVN_CLEANUP([hv1])
 
 AT_CLEANUP
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
index 4391694..b43f67f 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, "domain_search_list", 119, "domains");
 
     /* DHCPv6 options. */
     hmap_init(dhcpv6_opts);