From: Andrew Zaborowski <andrew.zaborowski@intel.com>
To: ell@lists.linux.dev
Subject: [PATCH 5/7] netconfig: Decouple icmp6 start from dhcp6 start
Date: Mon, 19 Sep 2022 15:31:03 +0200 [thread overview]
Message-ID: <20220919133105.3129080-5-andrew.zaborowski@intel.com> (raw)
In-Reply-To: <20220919133105.3129080-1-andrew.zaborowski@intel.com>
In preparation for supporting generating SLAAC addresses, start the
l_icmp6_client directly from the netconfig state machine.
l_dhcp6_client still takes care of creating and destroying
l_icmp6_client because it needs it for its own public API, but netconfig
starts/stops/handles events locally. This also allows a slight
optimization described in RFC4862 where if we're lucky, we will
send the Router Solicitation simultaneously with the Neighbor
Solicitation for the link-local addresses so as to avoid waiting the sum
of the RA response time + DAD timeout and instead wait the longer of the
two periods.
---
ell/dhcp6.c | 3 ++
ell/netconfig.c | 102 ++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 93 insertions(+), 12 deletions(-)
diff --git a/ell/dhcp6.c b/ell/dhcp6.c
index 15b451d..e234eb0 100644
--- a/ell/dhcp6.c
+++ b/ell/dhcp6.c
@@ -1473,6 +1473,9 @@ static void dhcp6_client_icmp6_event(struct l_icmp6_client *icmp6,
{
struct l_dhcp6_client *client = user_data;
+ if (client->nora)
+ return;
+
switch (event) {
case L_ICMP6_CLIENT_EVENT_ROUTER_FOUND:
{
diff --git a/ell/netconfig.c b/ell/netconfig.c
index 72c67a9..3ac0319 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -24,12 +24,13 @@
#include <config.h>
#endif
+#include <net/if.h>
#include <linux/types.h>
#include <linux/if_ether.h>
+#include <linux/if_arp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netinet/icmp6.h>
-#include <net/if.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -56,6 +57,7 @@
#include "net.h"
#include "net-private.h"
#include "acd.h"
+#include "timeout.h"
#include "netconfig.h"
struct l_netconfig {
@@ -87,6 +89,8 @@ struct l_netconfig {
struct l_queue *icmp_route_data;
struct l_acd *acd;
unsigned int orig_disable_ipv6;
+ uint8_t mac[ETH_ALEN];
+ struct l_timeout *ra_timeout;
/* These objects, if not NULL, are owned by @addresses and @routes */
struct l_rtnl_address *v4_address;
@@ -665,6 +669,35 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
}
}
+static bool netconfig_match(const void *a, const void *b)
+{
+ return a == b;
+}
+
+static bool netconfig_check_start_dhcp6(struct l_netconfig *nc)
+{
+ /* Don't start DHCPv6 until we get an RA with the managed bit set */
+ if (nc->ra_timeout)
+ return true;
+
+ /* Don't start DHCPv6 while waiting for the link-local address */
+ if (l_queue_find(addr_wait_list, netconfig_match, nc))
+ return true;
+
+ return l_dhcp6_client_start(nc->dhcp6_client);
+}
+
+static void netconfig_ra_timeout_cb(struct l_timeout *timeout, void *user_data)
+{
+ struct l_netconfig *nc = user_data;
+
+ l_timeout_remove(l_steal_ptr(nc->ra_timeout));
+
+ /* No Router Advertisements received, assume no DHCPv6 or SLAAC */
+ l_icmp6_client_stop(nc->icmp6_client);
+ netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_FAILED);
+}
+
static uint64_t now;
static bool netconfig_check_route_expired(void *data, void *user_data)
@@ -883,23 +916,23 @@ static void netconfig_icmp6_event_handler(struct l_icmp6_client *client,
const struct l_icmp6_router *r;
struct netconfig_route_data *default_rd;
unsigned int i;
+ bool first_ra = false;
if (event != L_ICMP6_CLIENT_EVENT_ROUTER_FOUND)
return;
r = event_data;
- /*
- * Note: If this is the first RA received, the l_dhcp6_client
- * will have received the event before us and will be acting
- * on it by now.
- */
-
- if (nc->v6_gateway_override)
- return;
+ if (nc->ra_timeout) {
+ first_ra = true;
+ l_timeout_remove(l_steal_ptr(nc->ra_timeout));
+ }
netconfig_expire_routes(nc);
+ if (nc->v6_gateway_override)
+ goto process_nondefault_routes;
+
/* Process the default gateway information */
default_rd = netconfig_find_icmp6_route(nc, r->address, NULL);
@@ -922,6 +955,7 @@ static void netconfig_icmp6_event_handler(struct l_icmp6_client *client,
else if (default_rd && !r->lifetime)
netconfig_remove_icmp6_route(nc, default_rd);
+process_nondefault_routes:
/*
* Process the onlink and offlink routes, from the Router
* Advertisement's Prefix Information options and Route
@@ -950,6 +984,16 @@ static void netconfig_icmp6_event_handler(struct l_icmp6_client *client,
netconfig_remove_icmp6_route(nc, rd);
}
+ /* See if we should start DHCPv6 now */
+ if (first_ra) {
+ if (!l_icmp6_router_get_managed(r) ||
+ !netconfig_check_start_dhcp6(nc)) {
+ netconfig_emit_event(nc, AF_INET6,
+ L_NETCONFIG_EVENT_FAILED);
+ return;
+ }
+ }
+
/*
* Note: we may be emitting this before L_NETCONFIG_EVENT_CONFIGURE.
* We should probably instead save the affected routes in separate
@@ -1046,6 +1090,7 @@ LIB_EXPORT struct l_netconfig *l_netconfig_new(uint32_t ifindex)
nc, NULL);
nc->dhcp6_client = l_dhcp6_client_new(ifindex);
+ l_dhcp6_client_set_nora(nc->dhcp6_client, true);
l_dhcp6_client_set_event_handler(nc->dhcp6_client,
netconfig_dhcp6_event_handler,
nc, NULL);
@@ -1535,10 +1580,10 @@ static void netconfig_ifaddr_ipv6_added(struct l_netconfig *nc,
l_icmp6_client_set_link_local_address(nc->icmp6_client, ip);
/*
- * Only now that we have a link-local address start actual DHCPv6
- * setup.
+ * Only now that we have a link-local address see if we can start
+ * actual DHCPv6 setup.
*/
- if (l_dhcp6_client_start(nc->dhcp6_client))
+ if (netconfig_check_start_dhcp6(nc))
return;
netconfig_emit_event(nc, AF_INET6, L_NETCONFIG_EVENT_FAILED);
@@ -1687,6 +1732,35 @@ configure_ipv6:
l_queue_push_tail(addr_wait_list, netconfig);
+ if (!l_net_get_mac_address(netconfig->ifindex, netconfig->mac))
+ goto unregister;
+
+ l_dhcp6_client_set_address(netconfig->dhcp6_client, ARPHRD_ETHER,
+ netconfig->mac, ETH_ALEN);
+ l_icmp6_client_set_address(netconfig->icmp6_client, netconfig->mac);
+
+ /*
+ * RFC4862 Section 4: "To speed the autoconfiguration process, a host
+ * may generate its link-local address (and verify its uniqueness) in
+ * parallel with waiting for a Router Advertisement. Because a router
+ * may delay responding to a Router Solicitation for a few seconds,
+ * the total time needed to complete autoconfiguration can be
+ * significantly longer if the two steps are done serially."
+ *
+ * We don't know whether we have the LL address yet. The interface
+ * may have been just brought up and DAD may still running or the LL
+ * address may have been deleted and won't be added until
+ * netconfig_ifaddr_ipv6_dump_done_cb() writes the /proc settings.
+ * In any case the Router Solicitation doesn't depend on having the
+ * LL address so send it now. We won't start DHCPv6 however until we
+ * have both the LL address and the Router Advertisement.
+ */
+ if (!l_icmp6_client_start(netconfig->icmp6_client))
+ goto unregister;
+
+ netconfig->ra_timeout = l_timeout_create(10, netconfig_ra_timeout_cb,
+ netconfig, NULL);
+
done:
netconfig->started = true;
return true;
@@ -1717,6 +1791,9 @@ LIB_EXPORT void l_netconfig_stop(struct l_netconfig *netconfig)
if (netconfig->signal_expired_work)
l_idle_remove(l_steal_ptr(netconfig->signal_expired_work));
+ if (netconfig->ra_timeout)
+ l_timeout_remove(l_steal_ptr(netconfig->ra_timeout));
+
netconfig_addr_wait_unregister(netconfig, false);
netconfig_update_cleanup(netconfig);
@@ -1734,6 +1811,7 @@ LIB_EXPORT void l_netconfig_stop(struct l_netconfig *netconfig)
l_dhcp_client_stop(netconfig->dhcp_client);
l_dhcp6_client_stop(netconfig->dhcp6_client);
+ l_icmp6_client_stop(netconfig->icmp6_client);
l_acd_destroy(l_steal_ptr(netconfig->acd));
--
2.34.1
next prev parent reply other threads:[~2022-09-19 13:31 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-19 13:30 [PATCH 1/7] icmp6: Save SLAAC prefixes from RAs Andrew Zaborowski
2022-09-19 13:31 ` [PATCH 2/7] icmp6: Parse RDNSS and DNSSL options Andrew Zaborowski
2022-09-19 13:31 ` [PATCH 3/7] icmp6: Switch socket from AF_INET6 to AF_PACKET Andrew Zaborowski
2022-09-19 13:31 ` [PATCH 4/7] rtnl: Add l_rtnl_address_get_in_addr Andrew Zaborowski
2022-09-19 13:31 ` Andrew Zaborowski [this message]
2022-09-19 13:31 ` [PATCH 6/7] netconfig: Create SLAAC address Andrew Zaborowski
2022-09-19 13:31 ` [PATCH 7/7] netconfig: Control optimistic DAD Andrew Zaborowski
2022-09-19 18:43 ` Denis Kenzior
2022-09-19 23:56 ` Andrew Zaborowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220919133105.3129080-5-andrew.zaborowski@intel.com \
--to=andrew.zaborowski@intel.com \
--cc=ell@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).