summaryrefslogtreecommitdiff
path: root/drivers/net/wireguard/netlink.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-05-19 13:45:49 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2021-05-19 18:37:54 +0200
commitab7e4abe1cd867362dc403a04a32028e8d62e1e9 (patch)
tree3a5a1f80013831f33b06a962aa2100bc3de86c2a /drivers/net/wireguard/netlink.c
parentba1d3e59fcdadf0c72fb44f5385ef6e0af849351 (diff)
downloadwireguard-linux-trimmed-ab7e4abe1cd867362dc403a04a32028e8d62e1e9.tar.gz
wireguard-linux-trimmed-ab7e4abe1cd867362dc403a04a32028e8d62e1e9.zip
wireguard: allowedips: batch process peer removalsjd/deferred-aip-removal
Deleting peers requires traversing the entire trie in order to rebalance nodes and safely free them so that we can use RCU in the critical path and never block. But for a structure filled with half million nodes, removing a few thousand of them can take an extremely long time, during which we're holding the rtnl lock. Large-scale users were reporting 200ms latencies added to the networking stack as a whole every time their userspace software would queue up significant removals. This commit works around the problem by marking nodes as dead, and then scheduling a deferred cleanup routine a second later to do one sweep of the entire structure, in order to amortize removals to just a single traversal. Not only should this remove the added latencies to the stack, but it should also make update operations that include peer removal or allowedips changes much faster. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'drivers/net/wireguard/netlink.c')
-rw-r--r--drivers/net/wireguard/netlink.c15
1 files changed, 5 insertions, 10 deletions
diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c
index d0f3b6d..9dcbc57 100644
--- a/drivers/net/wireguard/netlink.c
+++ b/drivers/net/wireguard/netlink.c
@@ -340,16 +340,12 @@ static int set_allowedip(struct wg_peer *peer, struct nlattr **attrs)
if (family == AF_INET && cidr <= 32 &&
nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in_addr))
- ret = wg_allowedips_insert_v4(
- &peer->device->peer_allowedips,
- nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer,
- &peer->device->device_update_lock);
+ ret = wg_allowedips_insert_v4(&peer->device->peer_allowedips,
+ nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer);
else if (family == AF_INET6 && cidr <= 128 &&
nla_len(attrs[WGALLOWEDIP_A_IPADDR]) == sizeof(struct in6_addr))
- ret = wg_allowedips_insert_v6(
- &peer->device->peer_allowedips,
- nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer,
- &peer->device->device_update_lock);
+ ret = wg_allowedips_insert_v6(&peer->device->peer_allowedips,
+ nla_data(attrs[WGALLOWEDIP_A_IPADDR]), cidr, peer);
return ret;
}
@@ -449,8 +445,7 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs)
}
if (flags & WGPEER_F_REPLACE_ALLOWEDIPS)
- wg_allowedips_remove_by_peer(&wg->peer_allowedips, peer,
- &wg->device_update_lock);
+ wg_allowedips_remove_by_peer(&wg->peer_allowedips, peer);
if (attrs[WGPEER_A_ALLOWEDIPS]) {
struct nlattr *attr, *allowedip[WGALLOWEDIP_A_MAX + 1];