From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE, SPF_PASS,T_DKIMWL_WL_HIGH,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DDC96C28CC6 for ; Wed, 5 Jun 2019 23:15:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B5E192075B for ; Wed, 5 Jun 2019 23:15:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559776536; bh=gH5lSvZ4ldWrE6w9Z7E3kiQl6Q59FDAbIdrVu6DL7GU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=qn0ltZ7iKwgEWm5WiDTuYhWg+IBE8gzuIQXlgNq8Eto3zS0ddzwPmu+oqbcJ60RBR 3KeIDELmoJBxszpQXfjlVRnvG2+YBax4T+okvIVcMQWSZsQHYs9lu2j9VHjf377NJG KvlahCg8bYJ8fHqBjfOzjzYT1zEXpAUeMA672gns= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726785AbfFEXPc (ORCPT ); Wed, 5 Jun 2019 19:15:32 -0400 Received: from mail.kernel.org ([198.145.29.99]:59382 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726708AbfFEXP3 (ORCPT ); Wed, 5 Jun 2019 19:15:29 -0400 Received: from kenny.it.cumulusnetworks.com. (fw.cumulusnetworks.com [216.129.126.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 8488B20B7C; Wed, 5 Jun 2019 23:15:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1559776528; bh=gH5lSvZ4ldWrE6w9Z7E3kiQl6Q59FDAbIdrVu6DL7GU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YnCaNPffUttBd/lAUhCFm8ohr0FpCchQbsIHaWhT2xOR3eV02utt7SjiiNg63xsJ5 /q2rI67cF6jt8GNsM8UQ7XmE633h2LVuUfTicmkvsk7gcF5d0eI60jH8z+OkyTDnlO M/KoBijC+OZ81PKDsgedTbGW70d3/xuGI8sl07rk= From: David Ahern To: davem@davemloft.net, netdev@vger.kernel.org Cc: idosch@mellanox.com, kafai@fb.com, weiwan@google.com, sbrivio@redhat.com, David Ahern Subject: [PATCH net-next 13/19] ipv6: Allow routes to use nexthop objects Date: Wed, 5 Jun 2019 16:15:17 -0700 Message-Id: <20190605231523.18424-14-dsahern@kernel.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190605231523.18424-1-dsahern@kernel.org> References: <20190605231523.18424-1-dsahern@kernel.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Ahern Add support for RTA_NH_ID attribute to allow a user to specify a nexthop id to use with a route. fc_nh_id is added to fib6_config to hold the value passed in the RTA_NH_ID attribute. If a nexthop id is given, the gateway, device, encap and multipath attributes can not be set. Update ip6_route_del to check metric and protocol before nexthop specs. If fc_nh_id is set, then it must match the id in the route entry. Since IPv6 allows delete of a cached entry (an exception), add ip6_del_cached_rt_nh to cycle through all of the fib6_nh in a fib entry if it is using a nexthop. Signed-off-by: David Ahern --- include/net/ip6_fib.h | 1 + net/ipv6/route.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 1a8acd51b277..ef946578341f 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -53,6 +53,7 @@ struct fib6_config { u16 fc_delete_all_nh : 1, fc_ignore_dev_down:1, __unused : 14; + u32 fc_nh_id; struct in6_addr fc_dst; struct in6_addr fc_src; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6f4b5fa6159b..d0441cefbc74 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3533,6 +3533,16 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, goto out; } #endif + if (cfg->fc_nh_id) { + nh = nexthop_find_by_id(net, cfg->fc_nh_id); + if (!nh) { + NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); + goto out; + } + err = fib6_check_nexthop(nh, cfg, extack); + if (err) + goto out; + } err = -ENOBUFS; if (cfg->fc_nlinfo.nlh && @@ -3764,6 +3774,30 @@ static int ip6_del_cached_rt(struct fib6_config *cfg, struct fib6_info *rt, return 0; } +struct fib6_nh_del_cached_rt_arg { + struct fib6_config *cfg; + struct fib6_info *f6i; +}; + +static int fib6_nh_del_cached_rt(struct fib6_nh *nh, void *_arg) +{ + struct fib6_nh_del_cached_rt_arg *arg = _arg; + int rc; + + rc = ip6_del_cached_rt(arg->cfg, arg->f6i, nh); + return rc != -ESRCH ? rc : 0; +} + +static int ip6_del_cached_rt_nh(struct fib6_config *cfg, struct fib6_info *f6i) +{ + struct fib6_nh_del_cached_rt_arg arg = { + .cfg = cfg, + .f6i = f6i + }; + + return nexthop_for_each_fib6_nh(f6i->nh, fib6_nh_del_cached_rt, &arg); +} + static int ip6_route_del(struct fib6_config *cfg, struct netlink_ext_ack *extack) { @@ -3789,11 +3823,20 @@ static int ip6_route_del(struct fib6_config *cfg, for_each_fib6_node_rt_rcu(fn) { struct fib6_nh *nh; - nh = rt->fib6_nh; - if (cfg->fc_flags & RTF_CACHE) { - int rc; + if (rt->nh && rt->nh->id != cfg->fc_nh_id) + continue; - rc = ip6_del_cached_rt(cfg, rt, nh); + if (cfg->fc_flags & RTF_CACHE) { + int rc = 0; + + if (rt->nh) { + rc = ip6_del_cached_rt_nh(cfg, rt); + } else if (cfg->fc_nh_id) { + continue; + } else { + nh = rt->fib6_nh; + rc = ip6_del_cached_rt(cfg, rt, nh); + } if (rc != -ESRCH) { rcu_read_unlock(); return rc; @@ -3801,6 +3844,23 @@ static int ip6_route_del(struct fib6_config *cfg, continue; } + if (cfg->fc_metric && cfg->fc_metric != rt->fib6_metric) + continue; + if (cfg->fc_protocol && + cfg->fc_protocol != rt->fib6_protocol) + continue; + + if (rt->nh) { + if (!fib6_info_hold_safe(rt)) + continue; + rcu_read_unlock(); + + return __ip6_del_rt(rt, &cfg->fc_nlinfo); + } + if (cfg->fc_nh_id) + continue; + + nh = rt->fib6_nh; if (cfg->fc_ifindex && (!nh->fib_nh_dev || nh->fib_nh_dev->ifindex != cfg->fc_ifindex)) @@ -3808,10 +3868,6 @@ static int ip6_route_del(struct fib6_config *cfg, if (cfg->fc_flags & RTF_GATEWAY && !ipv6_addr_equal(&cfg->fc_gateway, &nh->fib_nh_gw6)) continue; - if (cfg->fc_metric && cfg->fc_metric != rt->fib6_metric) - continue; - if (cfg->fc_protocol && cfg->fc_protocol != rt->fib6_protocol) - continue; if (!fib6_info_hold_safe(rt)) continue; rcu_read_unlock(); @@ -4711,6 +4767,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { [RTA_IP_PROTO] = { .type = NLA_U8 }, [RTA_SPORT] = { .type = NLA_U16 }, [RTA_DPORT] = { .type = NLA_U16 }, + [RTA_NH_ID] = { .type = NLA_U32 }, }; static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -4757,6 +4814,16 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK); + if (tb[RTA_NH_ID]) { + if (tb[RTA_GATEWAY] || tb[RTA_OIF] || + tb[RTA_MULTIPATH] || tb[RTA_ENCAP]) { + NL_SET_ERR_MSG(extack, + "Nexthop specification and nexthop id are mutually exclusive"); + goto errout; + } + cfg->fc_nh_id = nla_get_u32(tb[RTA_NH_ID]); + } + if (tb[RTA_GATEWAY]) { cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]); cfg->fc_flags |= RTF_GATEWAY; @@ -5091,6 +5158,12 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, if (err < 0) return err; + if (cfg.fc_nh_id && + !nexthop_find_by_id(sock_net(skb->sk), cfg.fc_nh_id)) { + NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); + return -EINVAL; + } + if (cfg.fc_mp) return ip6_route_multipath_del(&cfg, extack); else { -- 2.11.0