On Mon, Mar 18, 2024 at 10:12 PM Frode Nordahl <fnord...@ubuntu.com> wrote:
>
> The prefix we obtain is used to fill the ``ipv6_ra_prefixes``
> option for configuration of instances through SLAAC.
>
> As discussed in RFC 7421 the interface identifier is 64 bits long,
> and client implementations refrain from performing SLAAC with any
> other prefix length.
>
> TODO: I'm pretty sure the origin of this behavior is tied to an
>       older RFC, attempt to track it down.
>
> The DHCPv6 server is at liberty to offer whichever prefix length it
> wants, so make sure new requests are for a prefix length of 64 so
> that it is suitable.
>
> TODO: We may need to make the default prefix-length to request
>       configurable?  Setting this to 64 fixes an issue I see in my
>       network where the server will delegate a /62 by default,
>       which does not work well for SLAAC.
>
> A future improvement might be to adjust the requested prefix length
> to the number of downstream LRPs we have and then allocate to the
> downstream LRPs from that larger delegated prefix.
>
> TODO: We are free to request whatever prefix-length we want, and
>       the server is equally free to ignore our request and give us
>       something else.  So we need some generic handling of
>       allocations where prefix-length < 64.  Perhaps just split
>       the prefix up in /64 chunks and add them all to
>       ``ipv6_ra_prefixes`` ?
>
> TODO: tests
>
> QUESTION: From cursory view there appears to be an issue with
>           routing inside OVN after successful IPv6 Prefix
>           Delegation, it may be an issue with my setup, but
>           thought I might as well ask.  Is the prefix delegation
>           code supposed to automatically handle internal routing?

I apparently can't quite let go of this itch :)

Responding to my own question, there does appear to be missing
functionality in a few more areas to make IPv6 Prefix Delegation
support complete:
1) We need to include the learned ipv6_prefix when building
lr_in_ip_routing logical flows, something like this does it:

diff --git a/lib/ovn-util.c b/lib/ovn-util.c
index ee5cbcdc3..94ebf6488 100644
--- a/lib/ovn-util.c
+++ b/lib/ovn-util.c
@@ -344,6 +344,22 @@ extract_lrp_networks(const struct
nbrec_logical_router_port *lrp,
         }
     }

+    for (int i = 0; i < lrp->n_ipv6_prefix; i++) {
+        struct in6_addr ip6;
+        unsigned int plen;
+        char *error;
+
+        error = ipv6_parse_cidr(lrp->ipv6_prefix[i], &ip6, &plen);
+        if (!error) {
+            add_ipv6_netaddr(laddrs, ip6, plen);
+        } else {
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+            VLOG_INFO_RL(&rl, "invalid syntax '%s' in ipv6_prefix",
+                         lrp->networks[i]);
+            free(error);
+        }
+    }
+

---

I just piggy backed on extract_lrp_networks() here, but it might
deserve its own extract_lrp_delegated_ipv6_prefix() or something like
that for clarity?

2) Traffic is currently allowed to pass through port security,
presumably due to ND/MAC learning, but we should probably let IPAM
know about the learned prefixes so that dynamic addresses can be
properly populated?

3) I need to manually add an external v6 default route, but as a user
I would expect this to be learned through RA when IPv6 Prefix
Delegation is enabled. Maybe we should make this automatic?

> Signed-off-by: Frode Nordahl <fnord...@ubuntu.com>
> ---
>  controller/pinctrl.c | 35 ++++++++++++++++++++++++-----------
>  1 file changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 721a737de..8c4425a2e 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -1120,9 +1120,7 @@ compose_prefixd_packet(struct dp_packet *b, struct 
> ipv6_prefixd_state *pfd)
>      if (pfd->uuid.len) {
>          payload += pfd->uuid.len + sizeof(struct dhcpv6_opt_header);
>      }
> -    if (ipv6_addr_is_set(&pfd->prefix)) {
> -        payload += sizeof(struct dhcpv6_opt_ia_prefix);
> -    }
> +    payload += sizeof(struct dhcpv6_opt_ia_prefix);
>
>      eth_compose(b, (struct eth_addr) ETH_ADDR_C(33,33,00,01,00,02), pfd->ea,
>                  ETH_TYPE_IPV6, IPV6_HEADER_LEN);
> @@ -1174,23 +1172,38 @@ compose_prefixd_packet(struct dp_packet *b, struct 
> ipv6_prefixd_state *pfd)
>      ia_pd->opt.code = htons(DHCPV6_OPT_IA_PD);
>      int opt_len = sizeof(struct dhcpv6_opt_ia_na) -
>                    sizeof(struct dhcpv6_opt_header);
> -    if (ipv6_addr_is_set(&pfd->prefix)) {
> -        opt_len += sizeof(struct dhcpv6_opt_ia_prefix);
> -    }
> +    opt_len += sizeof(struct dhcpv6_opt_ia_prefix);
>      ia_pd->opt.len = htons(opt_len);
>      ia_pd->iaid = htonl(pfd->aid);
>      ia_pd->t1 = OVS_BE32_MAX;
>      ia_pd->t2 = OVS_BE32_MAX;
> +    struct dhcpv6_opt_ia_prefix *ia_prefix =
> +        (struct dhcpv6_opt_ia_prefix *)(ia_pd + 1);
> +    ia_prefix->opt.code = htons(DHCPV6_OPT_IA_PREFIX);
> +    ia_prefix->opt.len = htons(sizeof(struct dhcpv6_opt_ia_prefix) -
> +                               sizeof(struct dhcpv6_opt_header));
>      if (ipv6_addr_is_set(&pfd->prefix)) {
> -        struct dhcpv6_opt_ia_prefix *ia_prefix =
> -            (struct dhcpv6_opt_ia_prefix *)(ia_pd + 1);
> -        ia_prefix->opt.code = htons(DHCPV6_OPT_IA_PREFIX);
> -        ia_prefix->opt.len = htons(sizeof(struct dhcpv6_opt_ia_prefix) -
> -                                   sizeof(struct dhcpv6_opt_header));
>          ia_prefix->plife_time = OVS_BE32_MAX;
>          ia_prefix->vlife_time = OVS_BE32_MAX;
>          ia_prefix->plen = pfd->plen;
>          ia_prefix->ipv6 = pfd->prefix;
> +    } else {
> +        /* The prefix we obtain is used to fill the ``ipv6_ra_prefixes``
> +         * option for configuration of instances through SLAAC.
> +         *
> +         * As discussed in RFC 7421 the interface identifier is 64 bits long,
> +         * and client implementations refrain from performing SLAAC with any
> +         * other prefix length.
> +         *
> +         * The DHCPv6 server is at liberty to offer whichever prefix length 
> it
> +         * wants, so make sure new requests are for a prefix length of 64 so
> +         * that it is suitable.
> +         *
> +         * A future improvement might be to adjust the requested prefix 
> length
> +         * to the number of downstream LRPs we have and then allocate to the
> +         * downstream LRPs from that larger delegated prefix. */
> +        ia_prefix->ipv6 = in6addr_any;
> +        ia_prefix->plen = 64;
>      }
>
>      uint32_t csum = packet_csum_pseudoheader6(dp_packet_l3(b));
> --
> 2.43.0
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to