> Add an "ia_pd" DHCPv6 option that lets the CMS supply a delegated prefix in a
> logical port's DHCP_Options for OVN's native DHCPv6 server to hand out, with
> no
> pool or lease state kept in the dataplane. This lets OVN delegate a prefix
> (for example to a VM that in turn sub-delegates to its own workloads) while
> remaining the stateless responder it already is for IA_NA.
>
> The server is request-aware per RFC 8415: it parses the client's IA_PD,
> captures its IAID, and emits an IA_PD -> IA_PREFIX carrying the configured
> prefix only when the client actually solicited one, echoing the client's IAID.
> Prefixes are advertised with infinite lifetimes, matching the existing IA_NA
> emit. Only Solicit and Request elicit a delegated prefix; an IA_PD in
> Confirm,
> Decline or Information-request is ignored, and only the first IA_PD from a
> client is honored (a single prefix is delegated).
>
> A port must also receive a managed IPv6 address (ia_addr), which is what makes
> northd intercept its DHCPv6 traffic; PD-only ports are not yet supported.
>
> - lib/ovn-l7.h, northd/ovn-northd.c: register DHCPV6_OPT_IA_PD_PREFIX
> ("ia_pd", code 25, type "ia_pd") and add it to supported_dhcpv6_opts[].
> - lib/actions.c: encode the "ia_pd" type into the action buffer as
> [plen][prefix], deriving plen from the value's mask. parse_gen_opt
> rejects a value that is not a single masked IPv6 prefix, since the mask
> supplies the on-wire prefix length (a bare address would silently encode
> a /0, and a set would drop all but the first).
> - controller/pinctrl.c: parse the client IA_PD and emit the delegated
> prefix, copying it with memcpy to avoid an unaligned struct in6_addr
> access on strict-alignment architectures.
> - ovn-sb.ovsschema: allow "ia_pd" in the DHCPv6_Options "type" column enum
> and bump the schema version. northd writes the supported option into the
> Southbound DHCPv6_Options table, so without this every northd SB commit
> failed with a constraint violation.
> - ovn-nb.xml, ovn-sb.xml: document the new option and the SB type.
> - tests: register ia_pd in the test harness, add put_dhcpv6_opts parse and
> encode cases, and extend the dhcpv6 system test to exercise the
> request-aware path (a sibling IA_NA-only port must not receive an IA_PD).
>
> Signed-off-by: Dax Kelson <[email protected]>
Hi Dax,
just a nit inline.
Regards,
Lorenzo
> ---
> controller/pinctrl.c | 84 +++++++++++++++++++++++++++++++++++++++++---
> lib/actions.c | 20 +++++++++++
> lib/ovn-l7.h | 3 ++
> northd/ovn-northd.c | 1 +
> ovn-nb.xml | 33 +++++++++++++++++
> ovn-sb.ovsschema | 7 ++--
> ovn-sb.xml | 18 ++++++++++
> tests/ovn.at | 68 ++++++++++++++++++++++++++++++++++-
> tests/test-ovn.c | 1 +
> 9 files changed, 227 insertions(+), 8 deletions(-)
>
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index fce1c4be0..ff5004746 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -2962,7 +2962,8 @@ encode_dhcpv6_server_id_opt(struct ofpbuf *opts, void
> *user_data)
> static bool
> compose_out_dhcpv6_opts(struct ofpbuf *userdata,
> struct ofpbuf *out_dhcpv6_opts,
> - ovs_be32 iaid, bool ipxe_req, uint8_t fqdn_flags)
> + ovs_be32 iaid, bool ipxe_req, uint8_t fqdn_flags,
> + ovs_be32 pd_iaid, bool pd_requested)
> {
> while (userdata->size) {
> struct dhcpv6_opt_header *userdata_opt = ofpbuf_try_pull(
> @@ -3025,6 +3026,54 @@ compose_out_dhcpv6_opts(struct ofpbuf *userdata,
> break;
> }
>
> + case DHCPV6_OPT_IA_PD:
> + {
> + if (size != sizeof(uint8_t) + sizeof(struct in6_addr)) {
> + return false;
> + }
> +
> + if (!pd_requested) {
> + /* The client did not ask for a delegated prefix, so don't
> + * put an IA_PD option in the response. */
> + break;
> + }
> +
> + /* The IA Prefix option carries a delegated prefix and must be
> + * encapsulated in the Options field of an IA_PD option. Please
> + * see RFC 8415 sections 21.21 and 21.22. */
> + uint8_t plen = *(uint8_t *) userdata_opt_data;
> +
> + struct dhcpv6_opt_ia_na *opt_ia_pd = ofpbuf_put_zeros(
> + out_dhcpv6_opts, sizeof *opt_ia_pd);
> + opt_ia_pd->opt.code = htons(DHCPV6_OPT_IA_PD);
> + /* IA_PD length (in bytes)-
> + * IAID - 4
> + * T1 - 4
> + * T2 - 4
> + * IA Prefix - sizeof(struct dhcpv6_opt_ia_prefix)
> + */
> + opt_ia_pd->opt.len =
> + htons(12 + sizeof(struct dhcpv6_opt_ia_prefix));
> + opt_ia_pd->iaid = pd_iaid;
> + /* Set the lifetime of the prefix to infinity. */
> + opt_ia_pd->t1 = OVS_BE32_MAX;
> + opt_ia_pd->t2 = OVS_BE32_MAX;
> +
> + struct dhcpv6_opt_ia_prefix *opt_ia_prefix = ofpbuf_put_zeros(
> + out_dhcpv6_opts, sizeof *opt_ia_prefix);
> + opt_ia_prefix->opt.code = htons(DHCPV6_OPT_IA_PREFIX);
> + opt_ia_prefix->opt.len =
> + htons(sizeof(struct dhcpv6_opt_ia_prefix) -
> + DHCP6_OPT_HEADER_LEN);
> + opt_ia_prefix->plife_time = OVS_BE32_MAX;
> + opt_ia_prefix->vlife_time = OVS_BE32_MAX;
> + opt_ia_prefix->plen = plen;
> + memcpy(&opt_ia_prefix->ipv6,
> + (uint8_t *) userdata_opt_data + sizeof plen,
> + sizeof opt_ia_prefix->ipv6);
> + break;
> + }
> +
> case DHCPV6_OPT_DNS_SERVER_CODE:
> {
> struct dhcpv6_opt_header *opt_dns = ofpbuf_put_zeros(
> @@ -3209,6 +3258,8 @@ pinctrl_handle_put_dhcpv6_opts(
> * option. So we don't need to copy that in the Server's response.
> * */
> ovs_be32 iaid = 0;
> + ovs_be32 pd_iaid = 0;
> + bool pd_requested = false;
> struct dhcpv6_opt_header const *in_opt_client_id = NULL;
> bool ipxe_req = false;
> uint8_t fqdn_flags = DHCPV6_FQDN_FLAGS_UNDEFINED;
> @@ -3234,6 +3285,23 @@ pinctrl_handle_put_dhcpv6_opts(
> break;
> }
>
> + case DHCPV6_OPT_IA_PD:
> + {
> + if (opt_len < sizeof(struct dhcpv6_opt_ia_na)) {
> + break;
> + }
> +
> + /* IA_PD shares the IAID/T1/T2 header layout with IA_NA. OVN
> + * delegates a single prefix, so honor only the first IA_PD. */
> + if (!pd_requested) {
> + struct dhcpv6_opt_ia_na *opt_ia_pd =
> + (struct dhcpv6_opt_ia_na *) in_opt;
> + pd_iaid = opt_ia_pd->iaid;
> + pd_requested = true;
> + }
> + break;
> + }
> +
> case DHCPV6_OPT_CLIENT_ID_CODE:
> in_opt_client_id = in_opt;
> break;
> @@ -3271,8 +3339,15 @@ pinctrl_handle_put_dhcpv6_opts(
> goto exit;
> }
>
> - if (!iaid && hdr->msg_type != DHCPV6_MSG_TYPE_INFO_REQ) {
> - VLOG_WARN_RL(&rl, "DHCPv6 option - IA NA not present in the "
> + /* A delegated prefix is only offered in reply to a Solicit or Request.
> */
> + if (hdr->msg_type != DHCPV6_MSG_TYPE_SOLICIT &&
> + hdr->msg_type != DHCPV6_MSG_TYPE_REQUEST) {
> + pd_requested = false;
> + }
> +
> + if (!iaid && !pd_requested &&
> + hdr->msg_type != DHCPV6_MSG_TYPE_INFO_REQ) {
> + VLOG_WARN_RL(&rl, "DHCPv6 option - no IA_NA or IA_PD present in the "
> "DHCPv6 packet");
> goto exit;
> }
> @@ -3286,7 +3361,8 @@ pinctrl_handle_put_dhcpv6_opts(
> compose = compose_dhcpv6_status(userdata, &out_dhcpv6_opts);
> } else {
> compose = compose_out_dhcpv6_opts(userdata, &out_dhcpv6_opts, iaid,
> - ipxe_req, fqdn_flags);
> + ipxe_req, fqdn_flags, pd_iaid,
> + pd_requested);
> }
>
> if (!compose) {
> diff --git a/lib/actions.c b/lib/actions.c
> index 0367b330c..725674b0c 100644
> --- a/lib/actions.c
> +++ b/lib/actions.c
> @@ -2694,6 +2694,20 @@ parse_gen_opt(struct action_context *ctx, struct
> ovnact_gen_option *o,
> return;
> }
> }
> +
> + /* The ia_pd value is a single IPv6 prefix: its mask supplies the
> + * delegated prefix length on the wire, so reject a bare address (which
> + * would encode a meaningless /0) or a set of addresses. */
> + if (!strcmp(o->option->type, "ia_pd")) {
> + const struct expr_constant *c = vector_get_ptr(&o->value.values, 0);
> + if (vector_len(&o->value.values) != 1 ||
> + c->format != LEX_F_IPV6 || !c->masked) {
> + lexer_error(ctx->lexer, "%s option %s requires a single IPv6 "
> + "prefix value, e.g. aef0:1::/64.",
> + opts_type, o->option->name);
> + return;
> + }
> + }
> }
>
> static const struct ovnact_gen_option *
> @@ -3221,6 +3235,12 @@ encode_put_dhcpv6_option(const struct
> ovnact_gen_option *o,
> ofpbuf_put(ofpacts, encoded, size);
>
> free(encoded);
> + } else if (!strcmp(o->option->type, "ia_pd")) {
> + uint8_t plen = ipv6_count_cidr_bits(&c->mask.ipv6);
> + size = sizeof plen + sizeof c->value.ipv6;
> + opt->len = htons(size);
> + ofpbuf_put(ofpacts, &plen, sizeof plen);
> + ofpbuf_put(ofpacts, &c->value.ipv6, sizeof c->value.ipv6);
should we use a proper mask here? something like:
struct in6_addr masked;
ipv6_addr_bitand(&c->value.ipv6, &c->mask.ipv6, &masked);
ofpbuf_put(ofpacts, &masked, sizeof masked);
> }
> }
>
> diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h
> index 5f52e1791..b23e3ca29 100644
> --- a/lib/ovn-l7.h
> +++ b/lib/ovn-l7.h
> @@ -286,6 +286,9 @@ BUILD_ASSERT_DECL(DHCP_OPT_HEADER_LEN == sizeof(struct
> dhcp_opt_header));
> #define DHCPV6_OPT_IA_ADDR \
> DHCP_OPTION("ia_addr", DHCPV6_OPT_IA_ADDR_CODE, "ipv6")
>
> +#define DHCPV6_OPT_IA_PD_PREFIX \
> + DHCP_OPTION("ia_pd", DHCPV6_OPT_IA_PD, "ia_pd")
> +
> #define DHCPV6_OPT_DNS_SERVER \
> DHCP_OPTION("dns_server", DHCPV6_OPT_DNS_SERVER_CODE, "ipv6")
>
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index c4c71ca81..e5ea2fdf7 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -284,6 +284,7 @@ static struct gen_opts_map supported_dhcp_opts[] = {
>
> static struct gen_opts_map supported_dhcpv6_opts[] = {
> DHCPV6_OPT_IA_ADDR,
> + DHCPV6_OPT_IA_PD_PREFIX,
> DHCPV6_OPT_SERVER_ID,
> DHCPV6_OPT_DOMAIN_SEARCH,
> DHCPV6_OPT_DNS_SERVER,
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 15fb1d7e8..8622267e1 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -5918,6 +5918,39 @@ or
> </p>
> </column>
> </group>
> +
> + <group title="Prefix Delegation DHCPv6 options">
> + <p>
> + The option below makes OVN delegate an IPv6 prefix to a client that
> + requests one. OVN does not manage a prefix pool or any lease
> state;
> + the CMS supplies the prefix to delegate, and OVN emits it only when
> + the client solicits a prefix.
> + </p>
> +
> + <column name="options" key="ia_pd">
> + <p>
> + The DHCPv6 option code for this option is 25, ``Identity
> + Association for Prefix Delegation'' (IA_PD), which carries an IA
> + Prefix (option 26). The value is the delegated prefix in CIDR
> + notation, e.g. <code>aef0:1::/64</code>. When the client
> requests
> + an IA_PD, OVN replies with this prefix and echoes the client's
> + IA_PD IAID. Please refer to RFC 8415 for more details.
> + </p>
> +
> + <p>
> + A single prefix is delegated: only the first IA_PD a client
> + requests is answered. If this option is not set, no IA_PD is
> + returned even when the client requests one, the same way a
> missing
> + <code>ia_addr</code> is handled.
> + </p>
> +
> + <p>
> + The logical port must also receive a DHCPv6-managed IPv6 address
> + (see <code>ia_addr</code>), which is what makes OVN intercept the
> + port's DHCPv6 traffic.
> + </p>
> + </column>
> + </group>
> </group>
>
> <group title="Common Columns">
> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
> index 3d79a64b4..40bdf9b32 100644
> --- a/ovn-sb.ovsschema
> +++ b/ovn-sb.ovsschema
> @@ -1,7 +1,7 @@
> {
> "name": "OVN_Southbound",
> - "version": "21.10.0",
> - "cksum": "2298996353 36780",
> + "version": "21.11.0",
> + "cksum": "2650041963 36830",
> "tables": {
> "SB_Global": {
> "columns": {
> @@ -324,7 +324,8 @@
> "type": {
> "type": {"key": {
> "type": "string",
> - "enum": ["set", ["ipv6", "str", "mac",
> "domain"]]}}}},
> + "enum": ["set", ["ipv6", "str", "mac", "domain",
> + "ia_pd"]]}}}},
> "isRoot": true},
> "Connection": {
> "columns": {
> diff --git a/ovn-sb.xml b/ovn-sb.xml
> index 0d3ec6c2c..4069acfc0 100644
> --- a/ovn-sb.xml
> +++ b/ovn-sb.xml
> @@ -4440,6 +4440,24 @@ tcp.flags = RST;
> put_dhcpv6_opts(..., server_id = 01:02:03:04L05:06,...)
> </p>
> </dd>
> +
> + <dt><code>value: ia_pd</code></dt>
> + <dd>
> + <p>
> + This indicates that the value of the DHCPv6 option is a single
> IPv6
> + prefix to be delegated to the client via Prefix Delegation
> + (IA_PD/IA_PREFIX). The value must be a masked IPv6 address; the
> + mask supplies the delegated prefix length.
> + </p>
> +
> + <p>
> + Example. "name=ia_pd", "code=25", "type=ia_pd".
> + </p>
> +
> + <p>
> + put_dhcpv6_opts(..., ia_pd = aef0:1::/64,...)
> + </p>
> + </dd>
> </dl>
> </column>
> </table>
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 5dda50044..9ae023577 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -1625,6 +1625,10 @@ put_nd(inport, nd.target, nd.sll);
> # put_dhcpv6_opts
> reg1[[0]] = put_dhcpv6_opts(ia_addr = ae70::4, server_id =
> 00:00:00:00:10:02);
> encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.02.00.06.00.00.00.00.10.02,pause)
> +reg1[[0]] = put_dhcpv6_opts(ia_pd = aef0:1::/64);
> + encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.19.00.11.40.ae.f0.00.01.00.00.00.00.00.00.00.00.00.00.00.00,pause)
> +reg1[[0]] = put_dhcpv6_opts(ia_addr = ae70::4, ia_pd = aef0:1::/64,
> server_id = 00:00:00:00:10:02);
> + encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.05.00.10.ae.70.00.00.00.00.00.00.00.00.00.00.00.00.00.04.00.19.00.11.40.ae.f0.00.01.00.00.00.00.00.00.00.00.00.00.00.00.00.02.00.06.00.00.00.00.10.02,pause)
> reg1[[0]] = put_dhcpv6_opts();
> encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40,pause)
> reg1[[0]] = put_dhcpv6_opts(dns_server={ae70::1,ae70::2});
> @@ -1645,6 +1649,14 @@ reg1[[0]] = put_dhcpv6_opts(ia_addr="ae70::4");
> DHCPv6 option ia_addr requires numeric value.
> reg1[[0]] = put_dhcpv6_opts(ia_addr=ae70::4, domain_search=ae70::1);
> DHCPv6 option domain_search requires string value.
> +reg1[[0]] = put_dhcpv6_opts(ia_pd = "aef0:1::/64");
> + DHCPv6 option ia_pd requires numeric value.
> +reg1[[0]] = put_dhcpv6_opts(ia_pd = aef0:1::);
> + DHCPv6 option ia_pd requires a single IPv6 prefix value, e.g.
> aef0:1::/64.
> +reg1[[0]] = put_dhcpv6_opts(ia_pd = {aef0:1::/64, aef0:2::/64});
> + DHCPv6 option ia_pd requires a single IPv6 prefix value, e.g.
> aef0:1::/64.
> +reg1[[0]] = put_dhcpv6_opts(ia_pd = 1.2.3.4/24);
> + DHCPv6 option ia_pd requires a single IPv6 prefix value, e.g.
> aef0:1::/64.
> reg1[[0]] = put_dhcpv6_opts(bootfile_name="https://127.0.0.1/boot.ipxe");
> formats as reg1[[0]] = put_dhcpv6_opts(bootfile_name =
> "https://127.0.0.1/boot.ipxe");
> encodes as
> controller(userdata=00.00.00.05.00.00.00.00.00.01.de.10.00.00.00.40.00.3b.00.1b.68.74.74.70.73.3a.2f.2f.31.32.37.2e.30.2e.30.2e.31.2f.62.6f.6f.74.2e.69.70.78.65,pause)
> @@ -7623,7 +7635,7 @@ check ovn-nbctl lsp-add ls1 ls1-lp3 \
> check ovn-nbctl lsp-set-port-security ls1-lp3 "f0:00:00:00:00:22 ae70::22"
>
> d1="$(ovn-nbctl create DHCP_Options cidr="ae70\:\:/64" \
> -options="\"server_id\"=\"00:00:00:10:00:01\"")"
> +options="\"server_id\"=\"00:00:00:10:00:01\" \"ia_pd\"=\"aef0:1::/64\"")"
>
> check ovn-nbctl lsp-set-dhcpv6-options ls1-lp1 ${d1}
> check ovn-nbctl lsp-set-dhcpv6-options ls1-lp2 ${d1}
> @@ -7783,6 +7795,51 @@ test_dhcpv6_release() {
> n_resume=$((n_resume + 1))
> }
>
> +# This shell function sends a DHCPv6 request that carries an IA_PD option and
> +# checks that the reply delegates a prefix in an IA_PD -> IA_PREFIX. The
> +# request's IA_PD uses a distinct IAID so the reply must echo the IA_PD IAID,
> +# not the IA_NA one.
> +# test_dhcpv6_pd INPORT SRC_MAC SRC_LLA DHCPv6_MSG_TYPE OFFER_IP PD_PREFIX
> PD_PLEN
> +test_dhcpv6_pd() {
> + local inport=$1 src_mac=$2 src_lla=$3 msg_code=$4 offer_ip=$5
> + local pd_prefix=$6 pd_plen=$7
> +
> + local req_scapy="Ether(dst='33:33:00:01:00:02', src='${src_mac}')/ \
> + IPv6(dst='ff02::1:2', src='${src_lla}')/ \
> + UDP(sport=546, dport=547)/ \
> + DHCP6(msgtype=${msg_code}, trid=0x010203)/ \
> + DHCP6OptClientId(duid=DUID_LL(lladdr='${src_mac}'))/ \
> + DHCP6OptIA_NA(iaid=0x01020304, T1=3600, T2=5400)/ \
> + DHCP6OptIA_PD(iaid=0x0a0b0c0d, T1=3600, T2=5400)"
> + request=$(fmt_pkt "${req_scapy}")
> +
> + local reply_code=7
> + if test $msg_code = 1; then
> + reply_code=2
> + fi
> +
> + local ip_scapy="DHCP6OptIAAddress(addr='${offer_ip}', \
> + preflft=0xffffffff, validlft=0xffffffff)"
> + local pd_scapy="DHCP6OptIAPrefix(prefix='${pd_prefix}', plen=${pd_plen},
> \
> + preflft=0xffffffff, validlft=0xffffffff)"
> + local rep_scapy="Ether(dst='${src_mac}', src='00:00:00:10:00:01')/ \
> + IPv6(dst='${src_lla}',
> src='fe80::0200:00ff:fe10:0001')/ \
> + UDP(sport=547, dport=546)/ \
> + DHCP6(msgtype=${reply_code}, trid=0x010203)/ \
> + DHCP6OptClientId(duid=DUID_LL(lladdr='${src_mac}'))/ \
> + DHCP6OptIA_NA(iaid=0x01020304, T1=0xffffffff, \
> + T2=0xffffffff, ianaopts=[[${ip_scapy}]])/ \
> + DHCP6OptIA_PD(iaid=0x0a0b0c0d, T1=0xffffffff, \
> + T2=0xffffffff, iapdopt=[[${pd_scapy}]])/ \
> +
> DHCP6OptServerId(duid=DUID_LL(lladdr='00:00:00:10:00:01'))"
> + reply=$(fmt_pkt "${rep_scapy}")
> + echo $reply | trim_zeros >> $inport.expected
> +
> + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
> + OVS_WAIT_UNTIL([test $n_resume = `cat ofctl_monitor*.log | grep -c
> NXT_RESUME`])
> + n_resume=$((n_resume + 1))
> +}
> +
> check_packets() {
> local port=$1
>
> @@ -7845,6 +7902,15 @@ reset_pcap_file hv1-vif1 hv1/vif1
> test_dhcpv6_release 1 $src_mac $src_lla $offer_ip
> check_packets 1
>
> +# Request a delegated prefix on ls1-lp2. d1 carries an ia_pd option, so the
> +# reply must include an IA_PD -> IA_PREFIX with the delegated prefix and the
> +# client's IA_PD IAID. The IA_NA-only request on ls1-lp1 above must NOT get
> an
> +# IA_PD, which exercises the request-aware path.
> +reset_pcap_file hv1-vif2 hv1/vif2
> +test_dhcpv6_pd 2 f0:00:00:00:00:02 fe80::f200:00ff:fe00:0002 1 ae70::5
> aef0:1:: 64
> +check_packets 2
> +reset_pcap_file hv1-vif2 hv1/vif2
> +
> # Send invalid packet on ls1-lp2. ovn-controller should resume the packet
> # without any modifications and the packet should be received by ls1-lp1.
> # ls1-lp1 will receive the packet twice, one from the ovn-controller after
> the
> diff --git a/tests/test-ovn.c b/tests/test-ovn.c
> index 51471750b..460035b7f 100644
> --- a/tests/test-ovn.c
> +++ b/tests/test-ovn.c
> @@ -203,6 +203,7 @@ create_gen_opts(struct hmap *dhcp_opts, struct hmap
> *dhcpv6_opts,
> hmap_init(dhcpv6_opts);
> dhcp_opt_add(dhcpv6_opts, "server_id", 2, "mac");
> dhcp_opt_add(dhcpv6_opts, "ia_addr", 5, "ipv6");
> + dhcp_opt_add(dhcpv6_opts, "ia_pd", 25, "ia_pd");
> dhcp_opt_add(dhcpv6_opts, "dns_server", 23, "ipv6");
> dhcp_opt_add(dhcpv6_opts, "domain_search", 24, "str");
> dhcp_opt_add(dhcpv6_opts, "bootfile_name", 59, "str");
> --
> 2.50.1 (Apple Git-155)
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev