From patchwork Mon Apr 16 15:22:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ahern X-Patchwork-Id: 898722 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=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="IXqDNkAr"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40Pscn6kdNz9s3G for ; Tue, 17 Apr 2018 01:24:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752840AbeDPPYk (ORCPT ); Mon, 16 Apr 2018 11:24:40 -0400 Received: from mail-pl0-f66.google.com ([209.85.160.66]:38365 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752497AbeDPPXb (ORCPT ); Mon, 16 Apr 2018 11:23:31 -0400 Received: by mail-pl0-f66.google.com with SMTP id c7-v6so10220142plr.5 for ; Mon, 16 Apr 2018 08:23:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hgNEaINEJZJLGqGYy+FYu0uV6CsDLmzkbmkQiNrXvno=; b=IXqDNkArwRXm+KrBmwXVkckOJfix8GCYd8HqU17AeHq8DgjYwyC4pfpbetLtGo4ak8 behet0aKNGuqbhY7qUwiGxObOhy9vfikDfTmMtiiDmbmBnl3zDXpTbXVF0KZ5305FuWj rPQZYjK/UGolfLVllL+eTh8L5EO+GZmBru4YoBOTuMycH8enDGmEJ8tDPp8iaZjiNMbL cMyeYm9oxBmp7rAV91tC+hRs0U/lMX6aVoNi25BdT65j1EEpWUaqM7YYcPsA/8Pg1Jmn fTb+3cfRWnjNczdxKH/9ZTvLclluEG74+WUYDu20aSY4b334pdcNwF7hvjz+LaM2i9vO crzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=hgNEaINEJZJLGqGYy+FYu0uV6CsDLmzkbmkQiNrXvno=; b=q104KpW+apHdXWhJkBiUI7aKrnrPKehU2GkrQ8OhRSz027PQzcSkjfjBtQeFsEDd5F 4EmKh9XjSxYdwaae5HAiyMgy+Nbdab+CI80RgROTMl1cgmDD2NL9fTw0vYQhYlPXpmKX ioi7t/ld2heR7UWNMrZ/7xrjjLwMQw9gzL88Dky7QPe5XC2eoRQOkGvKgQGhQpEebih6 /1AKRWh70JGMqdGSyeD5AwM8D5d8kpRZwrfae9JofZrXzpXX+Gn08C/yjC6ZK9YjqFMf ipouGacibz/q3OslybwH4cjeDqxoWX68SfOEHASohCOouEqZ5Zsl098xDhyhvaTurMdX AdPQ== X-Gm-Message-State: ALQs6tBeXUbeStirAhkuxT3zPsSVFQ52q3a4NdX8ldVBcpJzUDYgsKW4 Xks61KQU8UJRukZ/sgeq9q+xmQ== X-Google-Smtp-Source: AIpwx49U2dtYn405a+eV3sfmcU6LYNkNovVuhTZnq/6T3Xg+6gtz7vtHZo6fUqp5hqBtD1Mp59xpwQ== X-Received: by 2002:a17:902:481:: with SMTP id e1-v6mr15974848ple.377.1523892210888; Mon, 16 Apr 2018 08:23:30 -0700 (PDT) Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com. [216.129.126.126]) by smtp.googlemail.com with ESMTPSA id r82sm4919437pfk.187.2018.04.16.08.23.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Apr 2018 08:23:30 -0700 (PDT) From: David Ahern To: netdev@vger.kernel.org Cc: davem@davemloft.net, idosch@idosch.org, roopa@cumulusnetworks.com, eric.dumazet@gmail.com, weiwan@google.com, kafai@fb.com, yoshfuji@linux-ipv6.org, David Ahern Subject: [PATCH net-next 09/21] net/ipv6: Defer initialization of dst to data path Date: Mon, 16 Apr 2018 08:22:43 -0700 Message-Id: <20180416152255.2256-10-dsahern@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180416152255.2256-1-dsahern@gmail.com> References: <20180416152255.2256-1-dsahern@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Defer setting dst input, output and error until fib entry is copied. The reject path from ip6_route_info_create is moved to a new function ip6_rt_init_dst_reject with a helper doing the conversion from fib6_type to dst error. The remainder of the new ip6_rt_init_dst is an amalgamtion of dst code from addrconf_dst_alloc and the non-reject path of ip6_route_info_create. The dst output function is always ip6_output and the input function is either ip6_input (local routes), ip6_mc_input (multicast routes) or ip6_forward (anything else). A couple of places using dst.error are updated to look at rt6i_flags. Signed-off-by: David Ahern --- net/ipv6/route.c | 115 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7af47bb319da..1d216c59cf10 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -920,6 +920,75 @@ static struct net_device *ip6_rt_get_dev_rcu(struct rt6_info *rt) return dev; } +static const int fib6_prop[RTN_MAX + 1] = { + [RTN_UNSPEC] = 0, + [RTN_UNICAST] = 0, + [RTN_LOCAL] = 0, + [RTN_BROADCAST] = 0, + [RTN_ANYCAST] = 0, + [RTN_MULTICAST] = 0, + [RTN_BLACKHOLE] = -EINVAL, + [RTN_UNREACHABLE] = -EHOSTUNREACH, + [RTN_PROHIBIT] = -EACCES, + [RTN_THROW] = -EAGAIN, + [RTN_NAT] = -EINVAL, + [RTN_XRESOLVE] = -EINVAL, +}; + +static int ip6_rt_type_to_error(u8 fib6_type) +{ + return fib6_prop[fib6_type]; +} + +static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct rt6_info *ort) +{ + rt->dst.error = ip6_rt_type_to_error(ort->fib6_type); + + switch (ort->fib6_type) { + case RTN_BLACKHOLE: + rt->dst.output = dst_discard_out; + rt->dst.input = dst_discard; + break; + case RTN_PROHIBIT: + rt->dst.output = ip6_pkt_prohibit_out; + rt->dst.input = ip6_pkt_prohibit; + break; + case RTN_THROW: + case RTN_UNREACHABLE: + default: + rt->dst.output = ip6_pkt_discard_out; + rt->dst.input = ip6_pkt_discard; + break; + } +} + +static void ip6_rt_init_dst(struct rt6_info *rt, struct rt6_info *ort) +{ + if (ort->rt6i_flags & RTF_REJECT) { + ip6_rt_init_dst_reject(rt, ort); + return; + } + + rt->dst.error = 0; + rt->dst.output = ip6_output; + + if (ort->fib6_type == RTN_LOCAL) { + rt->dst.flags |= DST_HOST; + rt->dst.input = ip6_input; + } else if (ipv6_addr_type(&ort->rt6i_dst.addr) & IPV6_ADDR_MULTICAST) { + rt->dst.input = ip6_mc_input; + } else { + rt->dst.input = ip6_forward; + } + + if (ort->fib6_nh.nh_lwtstate) { + rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.nh_lwtstate); + lwtunnel_set_redirect(&rt->dst); + } + + rt->dst.lastuse = jiffies; +} + static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) { BUG_ON(from->from); @@ -932,14 +1001,12 @@ static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort) { - rt->dst.input = ort->dst.input; - rt->dst.output = ort->dst.output; + ip6_rt_init_dst(rt, ort); + rt->rt6i_dst = ort->rt6i_dst; - rt->dst.error = ort->dst.error; rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); - rt->dst.lastuse = jiffies; rt->rt6i_gateway = ort->fib6_nh.nh_gw; rt->rt6i_flags = ort->rt6i_flags; rt6_set_from(rt, ort); @@ -2329,7 +2396,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, continue; if (rt6_check_expired(rt)) continue; - if (rt->dst.error) + if (rt->rt6i_flags & RTF_REJECT) break; if (!(rt->rt6i_flags & RTF_GATEWAY)) continue; @@ -2357,7 +2424,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net, if (!rt) rt = net->ipv6.ip6_null_entry; - else if (rt->dst.error) { + else if (rt->rt6i_flags & RTF_REJECT) { rt = net->ipv6.ip6_null_entry; goto out; } @@ -2900,15 +2967,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, addr_type = ipv6_addr_type(&cfg->fc_dst); - if (addr_type & IPV6_ADDR_MULTICAST) - rt->dst.input = ip6_mc_input; - else if (cfg->fc_flags & RTF_LOCAL) - rt->dst.input = ip6_input; - else - rt->dst.input = ip6_forward; - - rt->dst.output = ip6_output; - if (cfg->fc_encap) { struct lwtunnel_state *lwtstate; @@ -2918,7 +2976,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, if (err) goto out; rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate); - lwtunnel_set_redirect(&rt->dst); } ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); @@ -2958,27 +3015,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, } } rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; - switch (cfg->fc_type) { - case RTN_BLACKHOLE: - rt->dst.error = -EINVAL; - rt->dst.output = dst_discard_out; - rt->dst.input = dst_discard; - break; - case RTN_PROHIBIT: - rt->dst.error = -EACCES; - rt->dst.output = ip6_pkt_prohibit_out; - rt->dst.input = ip6_pkt_prohibit; - break; - case RTN_THROW: - case RTN_UNREACHABLE: - default: - rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN - : (cfg->fc_type == RTN_UNREACHABLE) - ? -EHOSTUNREACH : -ENETUNREACH; - rt->dst.output = ip6_pkt_discard_out; - rt->dst.input = ip6_pkt_discard; - break; - } goto install_route; } @@ -3622,12 +3658,9 @@ struct rt6_info *addrconf_dst_alloc(struct net *net, return ERR_PTR(-ENOMEM); in6_dev_hold(idev); - - rt->dst.flags |= DST_HOST; - rt->dst.input = ip6_input; - rt->dst.output = ip6_output; rt->rt6i_idev = idev; + rt->dst.flags |= DST_HOST; rt->rt6i_protocol = RTPROT_KERNEL; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; if (anycast) {