From patchwork Thu Jun 7 10:13:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Sitnicki X-Patchwork-Id: 926256 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 411hFK3LVwz9s01 for ; Thu, 7 Jun 2018 20:13:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932562AbeFGKNH (ORCPT ); Thu, 7 Jun 2018 06:13:07 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:42906 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932183AbeFGKNE (ORCPT ); Thu, 7 Jun 2018 06:13:04 -0400 Received: by mail-wr0-f195.google.com with SMTP id w10-v6so9439737wrk.9 for ; Thu, 07 Jun 2018 03:13:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=P1LwEME+LT529y1tzOYv/6rjNn3L3T4FOawk7xrBX5Q=; b=kJjn3Z2u/Fy6sL0wMKbgf7ZH3+IPVSjMcZcWslTxSP8um6OD959DZ4WFRts3gO6x86 Z9dkbmN6d5G0+MFktE2rknKjGFGhoXmKd9+JWCx+6II/5okWLMD9lQlgWb/RfRsNv6G1 9H9EPVlUxcwnElrFRE8HfQqIukOD5uFxT61/MIgIU4WGFdGjkh2cMtqq9NROOzA9npRA b9meIJ+A+YTdkU3MoAWbJwVnKAdKtrHmffPwknmnJFVMlmSUrhaVYqFHxHtVQbYUkbHY Fg/gy2rBuFmxhf8JIDPgDQffDGmo6MZfGvb4rfDTSH3ooFEK+h8waNut1n1d3Dc07wuc cJBA== X-Gm-Message-State: APt69E0i96A2sR8X8nw4ce29euyNaMKY8VtDQEEUuUflKTOtPtoAm8tl oW9j6IkkoYdL4do3fSzhwhIn9l0M8+Q= X-Google-Smtp-Source: ADUXVKKT4HyRogA6xaXL9//hAD47AZLtBRQu1E7L5C/uk13CR/Qy0xBsB3BiPHDK4L1lt5y4P8uWuw== X-Received: by 2002:adf:be81:: with SMTP id i1-v6mr1154188wrh.86.1528366383071; Thu, 07 Jun 2018 03:13:03 -0700 (PDT) Received: from redhat.com (red-hat-inc.vlan404.asr1.mad1.gblx.net. [64.215.113.190]) by smtp.gmail.com with ESMTPSA id 203-v6sm1833057wmp.23.2018.06.07.03.13.01 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 07 Jun 2018 03:13:02 -0700 (PDT) From: Jakub Sitnicki To: netdev@vger.kernel.org Subject: [RFC net-next] ipv4: Don't promote secondaries when flushing addresses Date: Thu, 7 Jun 2018 12:13:01 +0200 Message-Id: <20180607101301.30439-1-jkbs@redhat.com> X-Mailer: git-send-email 2.14.4 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Promoting secondary addresses on address removal makes flushing all addresses from a device with 1000's of them slow. This is because we cannot take down the secondary addresses when we are removing the primary one, which would make it faster. However, the userspace, when performing a flush, will in the end remove all the addresses regardless of secondary address promotion taking place. Unfortunately the kernel currently cannot distinguish between a single address removal and a flush of all addresses. To help with this case introduce a IFA_F_FLUSH flag that can be used by userspace to signal that a removal operation is being done because of a flush. When the flag is set, don't bother with secondary address promotion as we expect that secondary addresses will be removed soon as well. Signed-off-by: Jakub Sitnicki --- A benchmark involving a flush of 40,000 addresses from a dummy device shows a x4 speed-up of the 'flush' operation. 'ip' had to be modified to set the IFA_F_FLUSH flag for RTM_DELADDR requests issued for the 'flush': # time $IP -stats addr flush dev dum0 Before: real 0m30.596s user 0m0.000s sys 0m30.567s After: real 0m7.601s user 0m0.000s sys 0m7.569s It's also worth noting that promote_secondaries sysctl param is enabled by default since systemd 216 thus making it the new "normal" on some distros. include/uapi/linux/if_addr.h | 1 + net/ipv4/devinet.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) -- 2.14.4 diff --git a/include/uapi/linux/if_addr.h b/include/uapi/linux/if_addr.h index ebaf5701c9db..19aab9a9cec5 100644 --- a/include/uapi/linux/if_addr.h +++ b/include/uapi/linux/if_addr.h @@ -54,6 +54,7 @@ enum { #define IFA_F_NOPREFIXROUTE 0x200 #define IFA_F_MCAUTOJOIN 0x400 #define IFA_F_STABLE_PRIVACY 0x800 +#define IFA_F_FLUSH 0x1000 struct ifa_cacheinfo { __u32 ifa_prefered; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index d7585ab1a77a..1f436e1e5222 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -331,13 +331,14 @@ int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b) } static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, - int destroy, struct nlmsghdr *nlh, u32 portid) + int destroy, struct nlmsghdr *nlh, u32 portid, + bool flush) { struct in_ifaddr *promote = NULL; struct in_ifaddr *ifa, *ifa1 = *ifap; struct in_ifaddr *last_prim = in_dev->ifa_list; struct in_ifaddr *prev_prom = NULL; - int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); + int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev) && !flush; ASSERT_RTNL(); @@ -437,7 +438,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy) { - __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); + __inet_del_ifa(in_dev, ifap, destroy, NULL, 0, false); } static void check_lifetime(struct work_struct *work); @@ -607,6 +608,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, struct in_device *in_dev; struct ifaddrmsg *ifm; struct in_ifaddr *ifa, **ifap; + bool flush = false; int err = -EINVAL; ASSERT_RTNL(); @@ -623,6 +625,9 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout; } + if (tb[IFA_FLAGS]) + flush = !!(nla_get_u32(tb[IFA_FLAGS]) & IFA_F_FLUSH); + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (tb[IFA_LOCAL] && @@ -639,7 +644,8 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, if (ipv4_is_multicast(ifa->ifa_address)) ip_mc_config(net->ipv4.mc_autojoin_sk, false, ifa); - __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid); + __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid, + flush); return 0; }