On Fri, Aug 16, 2024 at 09:39:15AM +0200, Stefano Brivio wrote: > It makes no sense for a container or a guest to try and perform > duplicate address detection for their link-local address, as we'll > anyway not relay neighbour solicitations with an unspecified source > address. > > While they perform duplicate address detection, the link-local address > is not usable, which prevents us from bringing up especially > containers and communicate with them right away via IPv6. > > This is not enough to prevent DAD and reach the container right away: > we'll need a couple more patches. > > As we send NLM_F_REPLACE requests right away, while we still have to > read out other addresses on the same socket, we can't use nl_do(): > keep track of the last sequence we sent (last address we changed), and > deal with the answers to those NLM_F_REPLACE requests in a separate > loop, later. > > Link: https://github.com/containers/podman/pull/23561#discussion_r1711639663 > Signed-off-by: Stefano Brivio > --- > netlink.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > netlink.h | 1 + > pasta.c | 6 ++++++ > 3 files changed, 62 insertions(+) > > diff --git a/netlink.c b/netlink.c > index 873e6c7..59f2fd9 100644 > --- a/netlink.c > +++ b/netlink.c > @@ -673,6 +673,61 @@ int nl_route_dup(int s_src, unsigned int ifi_src, > return 0; > } > > +/** > + * nl_addr_set_ll_nodad() - Set IFA_F_NODAD on IPv6 link-local addresses > + * @s: Netlink socket > + * @ifi: Interface index in target namespace > + * > + * Return: 0 on success, negative error code on failure > + */ > +int nl_addr_set_ll_nodad(int s, unsigned int ifi) > +{ > + struct req_t { > + struct nlmsghdr nlh; > + struct ifaddrmsg ifa; > + } req = { > + .ifa.ifa_family = AF_INET6, > + .ifa.ifa_index = ifi, > + }; > + unsigned ll_addrs = 0; > + struct nlmsghdr *nh; > + char buf[NLBUFSIZ]; > + ssize_t status; > + uint32_t seq; > + > + seq = nl_send(s, &req, RTM_GETADDR, NLM_F_DUMP, sizeof(req)); > + nl_foreach_oftype(nh, status, s, buf, seq, RTM_NEWADDR) { > + struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nh); > + struct rtattr *rta; > + size_t na; > + > + if (ifa->ifa_index != ifi || ifa->ifa_scope != RT_SCOPE_LINK) > + continue; > + > + ifa->ifa_flags |= IFA_F_NODAD; > + > + for (rta = IFA_RTA(ifa), na = IFA_PAYLOAD(nh); RTA_OK(rta, na); > + rta = RTA_NEXT(rta, na)) { > + /* If 32-bit flags are used, add IFA_F_NODAD there */ > + if (rta->rta_type == IFA_FLAGS) > + *(uint32_t *)RTA_DATA(rta) |= IFA_F_NODAD; > + } > + > + nl_send(s, nh, RTM_NEWADDR, NLM_F_REPLACE, nh->nlmsg_len); > + ll_addrs++; > + } Uh.. did you forget to push an update. This looks like the last version. > + if (status < 0) > + return status; You still have this early return. > + > + seq += ll_addrs; > + > + nl_foreach(nh, status, s, buf, seq) > + warn("netlink: Unexpected response message"); And you need an outer loop over this nl_foreach() for each value of seq from the one from the RTM_GETADDR to the last one from NLM_F_REPLACE. > + > + return status; > +} > + > /** > * nl_addr_get() - Get most specific global address, given interface and family > * @s: Netlink socket > diff --git a/netlink.h b/netlink.h > index 178f8ae..66a44ad 100644 > --- a/netlink.h > +++ b/netlink.h > @@ -19,6 +19,7 @@ int nl_addr_get(int s, unsigned int ifi, sa_family_t af, > void *addr, int *prefix_len, void *addr_l); > int nl_addr_set(int s, unsigned int ifi, sa_family_t af, > const void *addr, int prefix_len); > +int nl_addr_set_ll_nodad(int s, unsigned int ifi); > int nl_addr_dup(int s_src, unsigned int ifi_src, > int s_dst, unsigned int ifi_dst, sa_family_t af); > int nl_link_get_mac(int s, unsigned int ifi, void *mac); > diff --git a/pasta.c b/pasta.c > index 96545b1..17eed15 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -340,6 +340,12 @@ void pasta_ns_conf(struct ctx *c) > } > > if (c->ifi6) { > + rc = nl_addr_set_ll_nodad(nl_sock_ns, c->pasta_ifi); > + if (rc < 0) { > + warn("Can't set nodad for LL in namespace: %s", > + strerror(-rc)); > + } > + > if (c->ip6.no_copy_addrs) { > rc = nl_addr_set(nl_sock_ns, c->pasta_ifi, > AF_INET6, &c->ip6.addr, 64); -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson