From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mike Manning Subject: [PATCH net-next 5/5] ipv6: add vrf table handling code for ipv6 mcast Date: Thu, 20 Sep 2018 09:58:48 +0100 Message-ID: <20180920085848.17721-6-mmanning@vyatta.att-mail.com> References: <20180920085848.17721-1-mmanning@vyatta.att-mail.com> Cc: Patrick Ruddy To: netdev@vger.kernel.org Return-path: Received: from mx0a-00191d01.pphosted.com ([67.231.149.140]:43120 "EHLO mx0a-00191d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731457AbeITOlh (ORCPT ); Thu, 20 Sep 2018 10:41:37 -0400 Received: from pps.filterd (m0049287.ppops.net [127.0.0.1]) by m0049287.ppops.net-00191d01. (8.16.0.22/8.16.0.22) with SMTP id w8K8svLZ036995 for ; Thu, 20 Sep 2018 04:59:11 -0400 Received: from tlpd255.enaf.dadc.sbc.com (sbcsmtp3.sbc.com [144.160.112.28]) by m0049287.ppops.net-00191d01. with ESMTP id 2mm2ap7uds-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 20 Sep 2018 04:59:10 -0400 Received: from enaf.dadc.sbc.com (localhost [127.0.0.1]) by tlpd255.enaf.dadc.sbc.com (8.14.5/8.14.5) with ESMTP id w8K8x9Eq007045 for ; Thu, 20 Sep 2018 03:59:10 -0500 Received: from zlp30494.vci.att.com (zlp30494.vci.att.com [135.46.181.159]) by tlpd255.enaf.dadc.sbc.com (8.14.5/8.14.5) with ESMTP id w8K8x69h006877 for ; Thu, 20 Sep 2018 03:59:06 -0500 Received: from zlp30494.vci.att.com (zlp30494.vci.att.com [127.0.0.1]) by zlp30494.vci.att.com (Service) with ESMTP id 68528400048D for ; Thu, 20 Sep 2018 08:59:06 +0000 (GMT) Received: from tlpd252.dadc.sbc.com (unknown [135.31.184.157]) by zlp30494.vci.att.com (Service) with ESMTP id 4FF21400069B for ; Thu, 20 Sep 2018 08:59:06 +0000 (GMT) Received: from dadc.sbc.com (localhost [127.0.0.1]) by tlpd252.dadc.sbc.com (8.14.5/8.14.5) with ESMTP id w8K8x6k4106463 for ; Thu, 20 Sep 2018 03:59:06 -0500 Received: from mail.eng.vyatta.net (mail.eng.vyatta.net [10.156.50.82]) by tlpd252.dadc.sbc.com (8.14.5/8.14.5) with ESMTP id w8K8x1Rs106141 for ; Thu, 20 Sep 2018 03:59:01 -0500 In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com> Sender: netdev-owner@vger.kernel.org List-ID: From: Patrick Ruddy The code to obtain the correct table for the incoming interface was missing for IPv6. This has been added along with the table creation notification to fib rules for the RTNL_FAMILY_IP6MR address family. Signed-off-by: Patrick Ruddy Signed-off-by: Mike Manning --- drivers/net/vrf.c | 11 +++++++++++ net/ipv6/ip6mr.c | 49 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 9d817c19f3b4..21ad4b1d7f03 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1214,8 +1214,19 @@ static int vrf_add_fib_rules(const struct net_device *dev) goto ipmr_err; #endif +#if IS_ENABLED(CONFIG_IPV6_MROUTE_MULTIPLE_TABLES) + err = vrf_fib_rule(dev, RTNL_FAMILY_IP6MR, true); + if (err < 0) + goto ip6mr_err; +#endif + return 0; +#if IS_ENABLED(CONFIG_IPV6_MROUTE_MULTIPLE_TABLES) +ip6mr_err: + vrf_fib_rule(dev, RTNL_FAMILY_IPMR, false); +#endif + #if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES) ipmr_err: vrf_fib_rule(dev, AF_INET6, false); diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index d0b7e0249c13..1ecc88456dc5 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -85,7 +85,8 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id); static void ip6mr_free_table(struct mr_table *mrt); static void ip6_mr_forward(struct net *net, struct mr_table *mrt, - struct sk_buff *skb, struct mfc6_cache *cache); + struct net_device *dev, struct sk_buff *skb, + struct mfc6_cache *cache); static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, mifi_t mifi, int assert); static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc, @@ -138,6 +139,9 @@ static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6, .flags = FIB_LOOKUP_NOREF, }; + /* update flow if oif or iif point to device enslaved to l3mdev */ + l3mdev_update_flow(net, flowi6_to_flowi(flp6)); + err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flowi6_to_flowi(flp6), 0, &arg); if (err < 0) @@ -164,7 +168,9 @@ static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp, return -EINVAL; } - mrt = ip6mr_get_table(rule->fr_net, rule->table); + arg->table = fib_rule_get_table(rule, arg); + + mrt = ip6mr_get_table(rule->fr_net, arg->table); if (!mrt) return -EAGAIN; res->mrt = mrt; @@ -1014,7 +1020,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt, } rtnl_unicast(skb, net, NETLINK_CB(skb).portid); } else - ip6_mr_forward(net, mrt, skb, c); + ip6_mr_forward(net, mrt, skb->dev, skb, c); } } @@ -1120,7 +1126,7 @@ static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, /* Queue a packet for resolution. It gets locked cache entry! */ static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, - struct sk_buff *skb) + struct sk_buff *skb, struct net_device *dev) { struct mfc6_cache *c; bool found = false; @@ -1180,6 +1186,10 @@ static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi, kfree_skb(skb); err = -ENOBUFS; } else { + if (dev) { + skb->dev = dev; + skb->skb_iif = dev->ifindex; + } skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb); err = 0; } @@ -2043,11 +2053,12 @@ static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev) } static void ip6_mr_forward(struct net *net, struct mr_table *mrt, - struct sk_buff *skb, struct mfc6_cache *c) + struct net_device *dev, struct sk_buff *skb, + struct mfc6_cache *c) { int psend = -1; int vif, ct; - int true_vifi = ip6mr_find_vif(mrt, skb->dev); + int true_vifi = ip6mr_find_vif(mrt, dev); vif = c->_c.mfc_parent; c->_c.mfc_un.res.pkt++; @@ -2073,7 +2084,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, /* * Wrong interface: drop packet and (maybe) send PIM assert. */ - if (mrt->vif_table[vif].dev != skb->dev) { + if (mrt->vif_table[vif].dev != dev) { c->_c.mfc_un.res.wrong_if++; if (true_vifi >= 0 && mrt->mroute_do_assert && @@ -2146,6 +2157,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, int ip6_mr_input(struct sk_buff *skb) { + struct rtable *rt = skb_rtable(skb); struct mfc6_cache *cache; struct net *net = dev_net(skb->dev); struct mr_table *mrt; @@ -2154,6 +2166,19 @@ int ip6_mr_input(struct sk_buff *skb) .flowi6_mark = skb->mark, }; int err; + struct net_device *dev; + + /* skb->dev passed in is the master dev for vrfs. + * Get the proper interface that does have a vif associated with it. + */ + dev = skb->dev; + if (netif_is_l3_master(skb->dev)) { + dev = dev_get_by_index_rcu(net, IPCB(skb)->iif); + if (!dev) { + kfree_skb(skb); + return -ENODEV; + } + } err = ip6mr_fib_lookup(net, &fl6, &mrt); if (err < 0) { @@ -2165,7 +2190,7 @@ int ip6_mr_input(struct sk_buff *skb) cache = ip6mr_cache_find(mrt, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); if (!cache) { - int vif = ip6mr_find_vif(mrt, skb->dev); + int vif = ip6mr_find_vif(mrt, dev); if (vif >= 0) cache = ip6mr_cache_find_any(mrt, @@ -2179,9 +2204,9 @@ int ip6_mr_input(struct sk_buff *skb) if (!cache) { int vif; - vif = ip6mr_find_vif(mrt, skb->dev); + vif = ip6mr_find_vif(mrt, dev); if (vif >= 0) { - int err = ip6mr_cache_unresolved(mrt, vif, skb); + int err = ip6mr_cache_unresolved(mrt, vif, skb, dev); read_unlock(&mrt_lock); return err; @@ -2191,7 +2216,7 @@ int ip6_mr_input(struct sk_buff *skb) return -ENODEV; } - ip6_mr_forward(net, mrt, skb, cache); + ip6_mr_forward(net, mrt, dev, skb, cache); read_unlock(&mrt_lock); @@ -2257,7 +2282,7 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, iph->saddr = rt->rt6i_src.addr; iph->daddr = rt->rt6i_dst.addr; - err = ip6mr_cache_unresolved(mrt, vif, skb2); + err = ip6mr_cache_unresolved(mrt, vif, skb2, dev); read_unlock(&mrt_lock); return err; -- 2.11.0