[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20180901004954.7145-16-dsahern@kernel.org>
Date: Fri, 31 Aug 2018 17:49:50 -0700
From: dsahern@...nel.org
To: netdev@...r.kernel.org
Cc: roopa@...ulusnetworks.com, sharpd@...ulusnetworks.com,
idosch@...lanox.com, davem@...emloft.net,
David Ahern <dsahern@...il.com>
Subject: [PATCH RFC net-next 15/18] net/ipv6: Use helpers to access fib6_nh data
From: David Ahern <dsahern@...il.com>
Similar to ipv4, add helpers for accessing fib6_nh data and convert
existing users.
Signed-off-by: David Ahern <dsahern@...il.com>
---
include/net/ip6_fib.h | 11 ----------
include/net/ip6_route.h | 2 ++
include/net/nexthop.h | 40 +++++++++++++++++++++++++++++++++++
include/trace/events/fib6.h | 2 +-
net/core/filter.c | 11 +++++++---
net/ipv6/route.c | 51 ++++++++++++++++++++++++++-------------------
6 files changed, 81 insertions(+), 36 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 9526eef711d5..1f04a26e4c65 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -424,17 +424,6 @@ static inline void fib6_nh_release(struct fib6_nh *fib6_nh)
lwtstate_put(fib6_nh->nh_lwtstate);
}
-static inline struct net_device *fib6_info_nh_dev(const struct fib6_info *f6i)
-{
- return f6i->fib6_nh->nh_dev;
-}
-
-static inline
-struct lwtunnel_state *fib6_info_nh_lwt(const struct fib6_info *f6i)
-{
- return f6i->fib6_nh->nh_lwtstate;
-}
-
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
unsigned int flags);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index b1ca637acb2a..0cdfe176c530 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -2,6 +2,8 @@
#ifndef _NET_IP6_ROUTE_H
#define _NET_IP6_ROUTE_H
+#include <net/nexthop.h>
+
struct route_info {
__u8 type;
__u8 length;
diff --git a/include/net/nexthop.h b/include/net/nexthop.h
index c149fe8394ab..dae1518af3f3 100644
--- a/include/net/nexthop.h
+++ b/include/net/nexthop.h
@@ -160,6 +160,46 @@ static inline __be32 fib_info_nh_gw(struct fib_info *fi)
return fib_nh ? fib_nh->nh_gw : 0;
}
+/* IPv6 variants
+ */
+static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh)
+{
+ struct nh_info *nhi;
+
+ nhi = rcu_dereference(nh->nh_info);
+ if (nhi->family == AF_INET6)
+ return &nhi->fib6_nh;
+
+ return NULL;
+}
+
+static inline struct fib6_nh *fib6_info_nh(struct fib6_info *f6i)
+{
+ return f6i->fib6_nh;
+}
+
+static inline struct net_device *fib6_info_nh_dev(struct fib6_info *f6i)
+{
+ struct fib6_nh *fib6_nh = fib6_info_nh(f6i);
+
+ return fib6_nh ? fib6_nh->nh_dev : NULL;
+}
+
+static inline struct in6_addr *fib6_info_nh_gw(struct fib6_info *f6i)
+{
+ struct fib6_nh *fib6_nh = fib6_info_nh(f6i);
+
+ return fib6_nh ? &fib6_nh->nh_gw : NULL;
+}
+
+static inline
+struct lwtunnel_state *fib6_info_nh_lwt(struct fib6_info *f6i)
+{
+ struct fib6_nh *fib6_nh = fib6_info_nh(f6i);
+
+ return fib6_nh ? fib6_nh->nh_lwtstate : NULL;
+}
+
int fib_check_nexthop(struct fib_info *fi, struct fib_config *cfg,
struct netlink_ext_ack *extack);
diff --git a/include/trace/events/fib6.h b/include/trace/events/fib6.h
index 037df3d2be0b..4e5e36cc35b9 100644
--- a/include/trace/events/fib6.h
+++ b/include/trace/events/fib6.h
@@ -36,7 +36,7 @@ TRACE_EVENT(fib6_table_lookup,
),
TP_fast_assign(
- struct fib6_nh *fib6_nh = f6i->fib6_nh;
+ struct fib6_nh *fib6_nh = fib6_info_nh(f6i);
struct in6_addr *in6;
__entry->tb_id = table->tb6_id;
diff --git a/net/core/filter.c b/net/core/filter.c
index bc979edf06ca..4d227fae69c8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4340,6 +4340,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
{
struct in6_addr *src = (struct in6_addr *) params->ipv6_src;
struct in6_addr *dst = (struct in6_addr *) params->ipv6_dst;
+ struct fib6_nh *fib6_nh;
struct neighbour *neigh;
struct net_device *dev;
struct inet6_dev *idev;
@@ -4428,13 +4429,17 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
return BPF_FIB_LKUP_RET_FRAG_NEEDED;
}
- if (f6i->fib6_nh->nh_lwtstate)
+ fib6_nh = fib6_info_nh(f6i);
+ if (!fib6_nh)
+ return BPF_FIB_LKUP_RET_NOT_FWDED;
+
+ if (fib6_nh->nh_lwtstate)
return BPF_FIB_LKUP_RET_UNSUPP_LWT;
if (f6i->fib6_flags & RTF_GATEWAY)
- *dst = f6i->fib6_nh->nh_gw;
+ *dst = fib6_nh->nh_gw;
- dev = f6i->fib6_nh->nh_dev;
+ dev = fib6_nh->nh_dev;
params->rt_metric = f6i->fib6_metric;
/* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 5792f57fdb91..2c140ce95eb4 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -533,8 +533,8 @@ static void rt6_probe(struct fib6_info *rt)
if (!rt || !(rt->fib6_flags & RTF_GATEWAY))
return;
- nh_gw = &rt->fib6_nh->nh_gw;
- dev = rt->fib6_nh->nh_dev;
+ nh_gw = fib6_info_nh_gw(rt);
+ dev = fib6_info_nh_dev(rt);
rcu_read_lock_bh();
neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
if (neigh) {
@@ -580,9 +580,9 @@ static inline void rt6_probe(struct fib6_info *rt)
*/
static inline int rt6_check_dev(struct fib6_info *rt, int oif)
{
- const struct net_device *dev = rt->fib6_nh->nh_dev;
+ const struct net_device *dev = fib6_info_nh_dev(rt);
- if (!oif || dev->ifindex == oif)
+ if (!oif || (dev && dev->ifindex == oif))
return 2;
return 0;
}
@@ -590,6 +590,8 @@ static inline int rt6_check_dev(struct fib6_info *rt, int oif)
static inline enum rt6_nud_state rt6_check_neigh(struct fib6_info *rt)
{
enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
+ const struct in6_addr *nh_gw = fib6_info_nh_gw(rt);
+ struct net_device *dev = fib6_info_nh_dev(rt);
struct neighbour *neigh;
if (rt->fib6_flags & RTF_NONEXTHOP ||
@@ -597,8 +599,7 @@ static inline enum rt6_nud_state rt6_check_neigh(struct fib6_info *rt)
return RT6_NUD_SUCCEED;
rcu_read_lock_bh();
- neigh = __ipv6_neigh_lookup_noref(rt->fib6_nh->nh_dev,
- &rt->fib6_nh->nh_gw);
+ neigh = __ipv6_neigh_lookup_noref(dev, nh_gw);
if (neigh) {
read_lock(&neigh->lock);
if (neigh->nud_state & NUD_VALID)
@@ -638,12 +639,12 @@ static int rt6_score_route(struct fib6_info *rt, int oif, int strict)
}
/* called with rc_read_lock held */
-// TO-DO: if (!f6i->nh)
static inline bool fib6_ignore_linkdown(const struct fib6_info *f6i)
{
- const struct net_device *dev = fib6_info_nh_dev(f6i);
+ const struct net_device *dev;
bool rc = false;
+ dev = f6i->fib6_nh->nh_dev;
if (dev) {
const struct inet6_dev *idev = __in6_dev_get(dev);
@@ -869,7 +870,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
/* called with rcu_lock held */
static struct net_device *ip6_rt_get_dev_rcu(struct fib6_info *rt)
{
- struct net_device *dev = rt->fib6_nh->nh_dev;
+ struct net_device *dev = fib6_info_nh_dev(rt);
if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) {
/* for copies of local routes, dst->dev needs to be the
@@ -947,6 +948,8 @@ static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct fib6_info *ort)
static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
{
+ struct lwtunnel_state *lws;
+
rt->dst.flags |= fib6_info_dst_flags(ort);
if (ort->fib6_flags & RTF_REJECT) {
@@ -965,8 +968,9 @@ static void ip6_rt_init_dst(struct rt6_info *rt, struct fib6_info *ort)
rt->dst.input = ip6_forward;
}
- if (ort->fib6_nh->nh_lwtstate) {
- rt->dst.lwtstate = lwtstate_get(ort->fib6_nh->nh_lwtstate);
+ lws = fib6_info_nh_lwt(ort);
+ if (lws) {
+ rt->dst.lwtstate = lwtstate_get(lws);
lwtunnel_set_redirect(&rt->dst);
}
@@ -985,19 +989,20 @@ static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort)
{
struct net_device *dev = fib6_info_nh_dev(ort);
+ struct fib6_nh *fib6_nh = fib6_info_nh(ort);
ip6_rt_init_dst(rt, ort);
rt->rt6i_dst = ort->fib6_dst;
rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL;
- rt->rt6i_gateway = ort->fib6_nh->nh_gw;
+ rt->rt6i_gateway = fib6_nh->nh_gw;
rt->rt6i_flags = ort->fib6_flags;
rt6_set_from(rt, ort);
#ifdef CONFIG_IPV6_SUBTREES
rt->rt6i_src = ort->fib6_src;
#endif
rt->rt6i_prefsrc = ort->fib6_prefsrc;
- rt->dst.lwtstate = lwtstate_get(ort->fib6_nh->nh_lwtstate);
+ rt->dst.lwtstate = lwtstate_get(fib6_nh->nh_lwtstate);
}
static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
@@ -1039,7 +1044,7 @@ static bool ip6_hold_safe(struct net *net, struct rt6_info **prt,
static struct rt6_info *ip6_create_rt_rcu(struct fib6_info *rt)
{
unsigned short flags = fib6_info_dst_flags(rt);
- struct net_device *dev = rt->fib6_nh->nh_dev;
+ struct net_device *dev = fib6_info_nh_dev(rt);
struct rt6_info *nrt;
if (!fib6_info_hold_safe(rt))
@@ -1392,8 +1397,9 @@ __rt6_find_exception_rcu(struct rt6_exception_bucket **bucket,
return NULL;
}
-static unsigned int fib6_mtu(const struct fib6_info *rt)
+static unsigned int fib6_mtu(struct fib6_info *rt)
{
+ struct lwtunnel_state *lws = fib6_info_nh_lwt(rt);
unsigned int mtu;
if (rt->fib6_pmtu) {
@@ -1410,7 +1416,7 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
mtu = min_t(unsigned int, mtu, IP6_MAX_MTU);
- return mtu - lwtunnel_headroom(rt->fib6_nh->nh_lwtstate, mtu);
+ return mtu - lwtunnel_headroom(lws, mtu);
}
static int rt6_insert_exception(struct rt6_info *nrt,
@@ -2454,7 +2460,9 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
for_each_fib6_node_rt_rcu(fn) {
- if (rt->fib6_nh->nh_flags & RTNH_F_DEAD)
+ struct fib6_nh *fib6_nh = fib6_info_nh(rt);
+
+ if (fib6_nh->nh_flags & RTNH_F_DEAD)
continue;
if (fib6_check_expired(rt))
continue;
@@ -2462,14 +2470,14 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
break;
if (!(rt->fib6_flags & RTF_GATEWAY))
continue;
- if (fl6->flowi6_oif != rt->fib6_nh->nh_dev->ifindex)
+ if (fl6->flowi6_oif != fib6_nh->nh_dev->ifindex)
continue;
/* rt_cache's gateway might be different from its 'parent'
* in the case of an ip redirect.
* So we keep searching in the exception table if the gateway
* is different.
*/
- if (!ipv6_addr_equal(&rdfl->gateway, &rt->fib6_nh->nh_gw)) {
+ if (!ipv6_addr_equal(&rdfl->gateway, &fib6_nh->nh_gw)) {
rt_cache = rt6_find_cached_rt(rt,
&fl6->daddr,
&fl6->saddr);
@@ -3804,8 +3812,9 @@ static int fib6_remove_prefsrc(struct fib6_info *rt, void *arg)
struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
struct net *net = ((struct arg_dev_net_ip *)arg)->net;
struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
+ struct net_device *nh_dev = fib6_info_nh_dev(rt);
- if (((void *)rt->fib6_nh->nh_dev == dev || !dev) &&
+ if ((nh_dev == dev || !dev) &&
rt != net->ipv6.fib6_null_entry &&
ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) {
spin_lock_bh(&rt6_exception_lock);
@@ -4127,7 +4136,7 @@ static int rt6_mtu_change_route(struct fib6_info *rt, void *p_arg)
Since RFC 1981 doesn't include administrative MTU increase
update PMTU increase is a MUST. (i.e. jumbo frame)
*/
- if (rt->fib6_nh->nh_dev == arg->dev &&
+ if (fib6_info_nh_dev(rt) == arg->dev &&
!fib6_metric_locked(rt, RTAX_MTU)) {
u32 mtu = rt->fib6_pmtu;
--
2.11.0
Powered by blists - more mailing lists