* [PATCH net-next 1/8] ipv4: Update fib_table_lookup tracepoint to take common nexthop
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 2/8] ipv4: Add fib_nh_common to fib_result David Ahern
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Update fib_table_lookup tracepoint to take a fib_nh_common struct and
dump the v6 gateway address if the nexthop uses it.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/trace/events/fib.h | 45 ++++++++++++++++++++++++++-------------------
net/ipv4/fib_trie.c | 2 +-
2 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/include/trace/events/fib.h b/include/trace/events/fib.h
index 61ea7a24c8e5..7f83b6eafc5c 100644
--- a/include/trace/events/fib.h
+++ b/include/trace/events/fib.h
@@ -13,9 +13,9 @@
TRACE_EVENT(fib_table_lookup,
TP_PROTO(u32 tb_id, const struct flowi4 *flp,
- const struct fib_nh *nh, int err),
+ const struct fib_nh_common *nhc, int err),
- TP_ARGS(tb_id, flp, nh, err),
+ TP_ARGS(tb_id, flp, nhc, err),
TP_STRUCT__entry(
__field( u32, tb_id )
@@ -28,14 +28,17 @@ TRACE_EVENT(fib_table_lookup,
__field( __u8, flags )
__array( __u8, src, 4 )
__array( __u8, dst, 4 )
- __array( __u8, gw, 4 )
- __array( __u8, saddr, 4 )
+ __array( __u8, gw4, 4 )
+ __array( __u8, gw6, 16 )
__field( u16, sport )
__field( u16, dport )
__dynamic_array(char, name, IFNAMSIZ )
),
TP_fast_assign(
+ struct in6_addr in6_zero = {};
+ struct net_device *dev;
+ struct in6_addr *in6;
__be32 *p32;
__entry->tb_id = tb_id;
@@ -62,33 +65,37 @@ TRACE_EVENT(fib_table_lookup,
__entry->dport = 0;
}
- if (nh) {
- struct net_device *dev;
+ dev = nhc ? nhc->nhc_dev : NULL;
+ __assign_str(name, dev ? dev->name : "-");
- p32 = (__be32 *) __entry->saddr;
- *p32 = nh->nh_saddr;
+ if (nhc) {
+ if (nhc->nhc_family == AF_INET) {
+ p32 = (__be32 *) __entry->gw4;
+ *p32 = nhc->nhc_gw.ipv4;
- p32 = (__be32 *) __entry->gw;
- *p32 = nh->fib_nh_gw4;
+ in6 = (struct in6_addr *)__entry->gw6;
+ *in6 = in6_zero;
+ } else if (nhc->nhc_family == AF_INET6) {
+ p32 = (__be32 *) __entry->gw4;
+ *p32 = 0;
- dev = nh->fib_nh_dev;
- __assign_str(name, dev ? dev->name : "-");
+ in6 = (struct in6_addr *)__entry->gw6;
+ *in6 = nhc->nhc_gw.ipv6;
+ }
} else {
- p32 = (__be32 *) __entry->saddr;
+ p32 = (__be32 *) __entry->gw4;
*p32 = 0;
- p32 = (__be32 *) __entry->gw;
- *p32 = 0;
-
- __assign_str(name, "-");
+ in6 = (struct in6_addr *)__entry->gw6;
+ *in6 = in6_zero;
}
),
- TP_printk("table %u oif %d iif %d proto %u %pI4/%u -> %pI4/%u tos %d scope %d flags %x ==> dev %s gw %pI4 src %pI4 err %d",
+ TP_printk("table %u oif %d iif %d proto %u %pI4/%u -> %pI4/%u tos %d scope %d flags %x ==> dev %s gw %pI4/%pI6c err %d",
__entry->tb_id, __entry->oif, __entry->iif, __entry->proto,
__entry->src, __entry->sport, __entry->dst, __entry->dport,
__entry->tos, __entry->scope, __entry->flags,
- __get_str(name), __entry->gw, __entry->saddr, __entry->err)
+ __get_str(name), __entry->gw4, __entry->gw6, __entry->err)
);
#endif /* _TRACE_FIB_H */
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1e3b492690f9..13b3327206f9 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1498,7 +1498,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
#ifdef CONFIG_IP_FIB_TRIE_STATS
this_cpu_inc(stats->semantic_match_passed);
#endif
- trace_fib_table_lookup(tb->tb_id, flp, nh, err);
+ trace_fib_table_lookup(tb->tb_id, flp, &nh->nh_common, err);
return err;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 2/8] ipv4: Add fib_nh_common to fib_result
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
2019-03-30 0:47 ` [PATCH net-next 1/8] ipv4: Update fib_table_lookup tracepoint to take common nexthop David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 3/8] ipv4: Move cached routes to fib_nh_common David Ahern
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Most of the ipv4 code only needs data from fib_nh_common. Add
fib_nh_common selection to fib_result and update users to use it.
Right now, fib_nh_common in fib_result will point to a nexthop within
a fib_info. Later, it can point to data within a nexthop struct.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip_fib.h | 47 +++++++++++++++++--------------------
net/core/filter.c | 12 +++++-----
net/ipv4/fib_frontend.c | 6 ++---
net/ipv4/fib_lookup.h | 1 +
net/ipv4/fib_semantics.c | 28 ++++++++++++++++++----
net/ipv4/fib_trie.c | 13 ++++++-----
net/ipv4/route.c | 60 ++++++++++++++++++++++++++++++++----------------
7 files changed, 102 insertions(+), 65 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 12a6d759cf57..5070bc531ca4 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -156,15 +156,16 @@ struct fib_rule;
struct fib_table;
struct fib_result {
- __be32 prefix;
- unsigned char prefixlen;
- unsigned char nh_sel;
- unsigned char type;
- unsigned char scope;
- u32 tclassid;
- struct fib_info *fi;
- struct fib_table *table;
- struct hlist_head *fa_head;
+ __be32 prefix;
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+ u32 tclassid;
+ struct fib_nh_common *nhc;
+ struct fib_info *fi;
+ struct fib_table *table;
+ struct hlist_head *fa_head;
};
struct fib_result_nl {
@@ -182,11 +183,10 @@ struct fib_result_nl {
int err;
};
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
-#else /* CONFIG_IP_ROUTE_MULTIPATH */
-#define FIB_RES_NH(res) ((res).fi->fib_nh[0])
-#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+static inline struct fib_nh_common *fib_info_nhc(struct fib_info *fi, int nhsel)
+{
+ return &fi->fib_nh[nhsel].nh_common;
+}
#ifdef CONFIG_IP_MULTIPLE_TABLES
#define FIB_TABLE_HASHSZ 256
@@ -195,18 +195,11 @@ struct fib_result_nl {
#endif
__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
+__be32 fib_result_prefsrc(struct net *net, struct fib_result *res);
-#define FIB_RES_SADDR(net, res) \
- ((FIB_RES_NH(res).nh_saddr_genid == \
- atomic_read(&(net)->ipv4.dev_addr_genid)) ? \
- FIB_RES_NH(res).nh_saddr : \
- fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
-#define FIB_RES_GW(res) (FIB_RES_NH(res).fib_nh_gw4)
-#define FIB_RES_DEV(res) (FIB_RES_NH(res).fib_nh_dev)
-#define FIB_RES_OIF(res) (FIB_RES_NH(res).fib_nh_oif)
-
-#define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
- FIB_RES_SADDR(net, res))
+#define FIB_RES_NH(res) ((res).nhc)
+#define FIB_RES_DEV(res) (FIB_RES_NH(res)->nhc_dev)
+#define FIB_RES_OIF(res) (FIB_RES_NH(res)->nhc_oif)
struct fib_entry_notifier_info {
struct fib_notifier_info info; /* must be first */
@@ -453,10 +446,12 @@ struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
#ifdef CONFIG_IP_ROUTE_CLASSID
+ struct fib_nh_common *nhc = res->nhc;
+ struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
#ifdef CONFIG_IP_MULTIPLE_TABLES
u32 rtag;
#endif
- *itag = FIB_RES_NH(*res).nh_tclassid<<16;
+ *itag = nh->nh_tclassid << 16;
#ifdef CONFIG_IP_MULTIPLE_TABLES
rtag = res->tclassid;
if (*itag == 0)
diff --git a/net/core/filter.c b/net/core/filter.c
index 4a8455757507..199e7d289a7d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4555,11 +4555,11 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params,
static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
u32 flags, bool check_mtu)
{
+ struct fib_nh_common *nhc;
struct in_device *in_dev;
struct neighbour *neigh;
struct net_device *dev;
struct fib_result res;
- struct fib_nh *nh;
struct flowi4 fl4;
int err;
u32 mtu;
@@ -4632,15 +4632,15 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
return BPF_FIB_LKUP_RET_FRAG_NEEDED;
}
- nh = &res.fi->fib_nh[res.nh_sel];
+ nhc = res.nhc;
/* do not handle lwt encaps right now */
- if (nh->fib_nh_lws)
+ if (nhc->nhc_lwtstate)
return BPF_FIB_LKUP_RET_UNSUPP_LWT;
- dev = nh->fib_nh_dev;
- if (nh->fib_nh_gw4)
- params->ipv4_dst = nh->fib_nh_gw4;
+ dev = nhc->nhc_dev;
+ if (nhc->nhc_has_gw)
+ params->ipv4_dst = nhc->nhc_gw.ipv4;
params->rt_metric = res.fi->fib_priority;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index ffbe24397dbe..00edebab2ca0 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -307,7 +307,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
.flowi4_mark = vmark ? skb->mark : 0,
};
if (!fib_lookup(net, &fl4, &res, 0))
- return FIB_RES_PREFSRC(net, res);
+ return fib_result_prefsrc(net, &res);
} else {
scope = RT_SCOPE_LINK;
}
@@ -390,7 +390,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
dev_match = fib_info_nh_uses_dev(res.fi, dev);
if (dev_match) {
- ret = FIB_RES_NH(res).fib_nh_scope >= RT_SCOPE_HOST;
+ ret = FIB_RES_NH(res)->nhc_scope >= RT_SCOPE_HOST;
return ret;
}
if (no_addr)
@@ -402,7 +402,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
ret = 0;
if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
if (res.type == RTN_UNICAST)
- ret = FIB_RES_NH(res).fib_nh_scope >= RT_SCOPE_HOST;
+ ret = FIB_RES_NH(res)->nhc_scope >= RT_SCOPE_HOST;
}
return ret;
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index e6ff282bb7f4..7945f0534db7 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -45,6 +45,7 @@ static inline void fib_result_assign(struct fib_result *res,
{
/* we used to play games with refcounts, but we now use RCU */
res->fi = fi;
+ res->nhc = fib_info_nhc(fi, 0);
}
struct fib_prop {
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index df777af7e278..f81c7dc7ff59 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1075,6 +1075,24 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh)
return nh->nh_saddr;
}
+__be32 fib_result_prefsrc(struct net *net, struct fib_result *res)
+{
+ struct fib_nh_common *nhc = res->nhc;
+ struct fib_nh *nh;
+
+ if (res->fi->fib_prefsrc)
+ return res->fi->fib_prefsrc;
+
+ if (unlikely(nhc->nhc_family != AF_INET))
+ return inet_select_addr(nhc->nhc_dev, 0, res->fi->fib_scope);
+
+ nh = container_of(nhc, struct fib_nh, nh_common);
+ if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid))
+ return nh->nh_saddr;
+
+ return fib_info_update_nh_saddr(net, nh);
+}
+
static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
{
if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
@@ -1762,20 +1780,22 @@ void fib_select_multipath(struct fib_result *res, int hash)
struct net *net = fi->fib_net;
bool first = false;
- for_nexthops(fi) {
+ change_nexthops(fi) {
if (net->ipv4.sysctl_fib_multipath_use_neigh) {
- if (!fib_good_nh(nh))
+ if (!fib_good_nh(nexthop_nh))
continue;
if (!first) {
res->nh_sel = nhsel;
+ res->nhc = &nexthop_nh->nh_common;
first = true;
}
}
- if (hash > atomic_read(&nh->fib_nh_upper_bound))
+ if (hash > atomic_read(&nexthop_nh->fib_nh_upper_bound))
continue;
res->nh_sel = nhsel;
+ res->nhc = &nexthop_nh->nh_common;
return;
} endfor_nexthops(fi);
}
@@ -1802,5 +1822,5 @@ void fib_select_path(struct net *net, struct fib_result *res,
check_saddr:
if (!fl4->saddr)
- fl4->saddr = FIB_RES_PREFSRC(net, *res);
+ fl4->saddr = fib_result_prefsrc(net, res);
}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 13b3327206f9..334f723bdf80 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1470,17 +1470,17 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
if (fi->fib_flags & RTNH_F_DEAD)
continue;
for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
- const struct fib_nh *nh = &fi->fib_nh[nhsel];
+ struct fib_nh_common *nhc = fib_info_nhc(fi, nhsel);
- if (nh->fib_nh_flags & RTNH_F_DEAD)
+ if (nhc->nhc_flags & RTNH_F_DEAD)
continue;
- if (ip_ignore_linkdown(nh->fib_nh_dev) &&
- nh->fib_nh_flags & RTNH_F_LINKDOWN &&
+ if (ip_ignore_linkdown(nhc->nhc_dev) &&
+ nhc->nhc_flags & RTNH_F_LINKDOWN &&
!(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
continue;
if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
if (flp->flowi4_oif &&
- flp->flowi4_oif != nh->fib_nh_oif)
+ flp->flowi4_oif != nhc->nhc_oif)
continue;
}
@@ -1490,6 +1490,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
res->prefix = htonl(n->key);
res->prefixlen = KEYLENGTH - fa->fa_slen;
res->nh_sel = nhsel;
+ res->nhc = nhc;
res->type = fa->fa_type;
res->scope = fi->fib_scope;
res->fi = fi;
@@ -1498,7 +1499,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
#ifdef CONFIG_IP_FIB_TRIE_STATS
this_cpu_inc(stats->semantic_match_passed);
#endif
- trace_fib_table_lookup(tb->tb_id, flp, &nh->nh_common, err);
+ trace_fib_table_lookup(tb->tb_id, flp, nhc, err);
return err;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 7977514d90f5..3556d87558e6 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -778,8 +778,10 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
neigh_event_send(n, NULL);
} else {
if (fib_lookup(net, fl4, &res, 0) == 0) {
- struct fib_nh *nh = &FIB_RES_NH(res);
+ struct fib_nh_common *nhc = FIB_RES_NH(res);
+ struct fib_nh *nh;
+ nh = container_of(nhc, struct fib_nh, nh_common);
update_or_create_fnhe(nh, fl4->daddr, new_gw,
0, false,
jiffies + ip_rt_gc_timeout);
@@ -1027,8 +1029,10 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
rcu_read_lock();
if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
- struct fib_nh *nh = &FIB_RES_NH(res);
+ struct fib_nh_common *nhc = FIB_RES_NH(res);
+ struct fib_nh *nh;
+ nh = container_of(nhc, struct fib_nh, nh_common);
update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock,
jiffies + ip_rt_mtu_expires);
}
@@ -1235,7 +1239,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
rcu_read_lock();
if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res, 0) == 0)
- src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res);
+ src = fib_result_prefsrc(dev_net(rt->dst.dev), &res);
else
src = inet_select_addr(rt->dst.dev,
rt_nexthop(rt, iph->daddr),
@@ -1354,9 +1358,9 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
{
+ struct fib_nh_common *nhc = res->nhc;
+ struct net_device *dev = nhc->nhc_dev;
struct fib_info *fi = res->fi;
- struct fib_nh *nh = &fi->fib_nh[res->nh_sel];
- struct net_device *dev = nh->fib_nh_dev;
u32 mtu = 0;
if (dev_net(dev)->ipv4.sysctl_ip_fwd_use_pmtu ||
@@ -1364,6 +1368,7 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
mtu = fi->fib_mtu;
if (likely(!mtu)) {
+ struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
struct fib_nh_exception *fnhe;
fnhe = find_exception(nh, daddr);
@@ -1374,7 +1379,7 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
if (likely(!mtu))
mtu = min(READ_ONCE(dev->mtu), IP_MAX_MTU);
- return mtu - lwtunnel_headroom(nh->fib_nh_lws, mtu);
+ return mtu - lwtunnel_headroom(nhc->nhc_lwtstate, mtu);
}
static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
@@ -1529,7 +1534,8 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
bool cached = false;
if (fi) {
- struct fib_nh *nh = &FIB_RES_NH(*res);
+ struct fib_nh_common *nhc = FIB_RES_NH(*res);
+ struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
if (nh->fib_nh_gw4 && nh->fib_nh_scope == RT_SCOPE_LINK) {
rt->rt_gateway = nh->fib_nh_gw4;
@@ -1699,15 +1705,18 @@ static int __mkroute_input(struct sk_buff *skb,
struct in_device *in_dev,
__be32 daddr, __be32 saddr, u32 tos)
{
+ struct fib_nh_common *nhc = FIB_RES_NH(*res);
+ struct net_device *dev = nhc->nhc_dev;
struct fib_nh_exception *fnhe;
struct rtable *rth;
+ struct fib_nh *nh;
int err;
struct in_device *out_dev;
bool do_cache;
u32 itag = 0;
/* get a working reference to the output device */
- out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res));
+ out_dev = __in_dev_get_rcu(dev);
if (!out_dev) {
net_crit_ratelimited("Bug in ip_route_input_slow(). Please report.\n");
return -EINVAL;
@@ -1724,10 +1733,13 @@ static int __mkroute_input(struct sk_buff *skb,
do_cache = res->fi && !itag;
if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) &&
- skb->protocol == htons(ETH_P_IP) &&
- (IN_DEV_SHARED_MEDIA(out_dev) ||
- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
- IPCB(skb)->flags |= IPSKB_DOREDIRECT;
+ skb->protocol == htons(ETH_P_IP)) {
+ __be32 gw = nhc->nhc_family == AF_INET ? nhc->nhc_gw.ipv4 : 0;
+
+ if (IN_DEV_SHARED_MEDIA(out_dev) ||
+ inet_addr_onlink(out_dev, saddr, gw))
+ IPCB(skb)->flags |= IPSKB_DOREDIRECT;
+ }
if (skb->protocol != htons(ETH_P_IP)) {
/* Not IP (i.e. ARP). Do not create route, if it is
@@ -1744,12 +1756,13 @@ static int __mkroute_input(struct sk_buff *skb,
}
}
- fnhe = find_exception(&FIB_RES_NH(*res), daddr);
+ nh = container_of(nhc, struct fib_nh, nh_common);
+ fnhe = find_exception(nh, daddr);
if (do_cache) {
if (fnhe)
rth = rcu_dereference(fnhe->fnhe_rth_input);
else
- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+ rth = rcu_dereference(nh->nh_rth_input);
if (rt_cache_valid(rth)) {
skb_dst_set_noref(skb, &rth->dst);
goto out;
@@ -2043,7 +2056,11 @@ out: return err;
do_cache = false;
if (res->fi) {
if (!itag) {
- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
+ struct fib_nh_common *nhc = FIB_RES_NH(*res);
+ struct fib_nh *nh;
+
+ nh = container_of(nhc, struct fib_nh, nh_common);
+ rth = rcu_dereference(nh->nh_rth_input);
if (rt_cache_valid(rth)) {
skb_dst_set_noref(skb, &rth->dst);
err = 0;
@@ -2073,15 +2090,17 @@ out: return err;
}
if (do_cache) {
- struct fib_nh *nh = &FIB_RES_NH(*res);
+ struct fib_nh_common *nhc = FIB_RES_NH(*res);
+ struct fib_nh *nh;
- rth->dst.lwtstate = lwtstate_get(nh->fib_nh_lws);
+ rth->dst.lwtstate = lwtstate_get(nhc->nhc_lwtstate);
if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
WARN_ON(rth->dst.input == lwtunnel_input);
rth->dst.lwtstate->orig_input = rth->dst.input;
rth->dst.input = lwtunnel_input;
}
+ nh = container_of(nhc, struct fib_nh, nh_common);
if (unlikely(!rt_cache_route(nh, rth)))
rt_add_uncached_list(rth);
}
@@ -2253,8 +2272,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
fnhe = NULL;
do_cache &= fi != NULL;
if (fi) {
+ struct fib_nh_common *nhc = FIB_RES_NH(*res);
+ struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
struct rtable __rcu **prth;
- struct fib_nh *nh = &FIB_RES_NH(*res);
fnhe = find_exception(nh, fl4->daddr);
if (!do_cache)
@@ -2264,8 +2284,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
} else {
if (unlikely(fl4->flowi4_flags &
FLOWI_FLAG_KNOWN_NH &&
- !(nh->fib_nh_gw4 &&
- nh->fib_nh_scope == RT_SCOPE_LINK))) {
+ !(nhc->nhc_has_gw &&
+ nhc->nhc_scope == RT_SCOPE_LINK))) {
do_cache = false;
goto add;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 3/8] ipv4: Move cached routes to fib_nh_common
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
2019-03-30 0:47 ` [PATCH net-next 1/8] ipv4: Update fib_table_lookup tracepoint to take common nexthop David Ahern
2019-03-30 0:47 ` [PATCH net-next 2/8] ipv4: Add fib_nh_common to fib_result David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-31 0:11 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 4/8] ipv6: Move exceptions " David Ahern
` (4 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
While the cached routes, nh_pcpu_rth_output and nh_rth_input, are IPv4
specific, a later patch wants to make them accessible for IPv6
gateways with IPv4 routes but also allow IPv6 routes to have their own
cached entries. Move the IPv4 cached routes from fib_nh to fib_nh_common
and update references.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip_fib.h | 6 ++++--
net/ipv4/fib_semantics.c | 33 +++++++++++++++++----------------
net/ipv4/route.c | 18 +++++++++---------
3 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 5070bc531ca4..cce437a1b2ff 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -92,6 +92,10 @@ struct fib_nh_common {
int nhc_weight;
atomic_t nhc_upper_bound;
+
+ /* v4 specific, but allows v6 gw with v4 routes */
+ struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
+ struct rtable __rcu *nhc_rth_input;
};
struct fib_nh {
@@ -103,8 +107,6 @@ struct fib_nh {
#endif
__be32 nh_saddr;
int nh_saddr_genid;
- struct rtable __rcu * __percpu *nh_pcpu_rth_output;
- struct rtable __rcu *nh_rth_input;
struct fnhe_hash_bucket __rcu *nh_exceptions;
#define fib_nh_family nh_common.nhc_family
#define fib_nh_dev nh_common.nhc_dev
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f81c7dc7ff59..e8c9208d35d2 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -210,6 +210,8 @@ void fib_nh_common_release(struct fib_nh_common *nhc)
dev_put(nhc->nhc_dev);
lwtstate_put(nhc->nhc_lwtstate);
+ rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
+ rt_fibinfo_free(&nhc->nhc_rth_input);
}
EXPORT_SYMBOL_GPL(fib_nh_common_release);
@@ -221,8 +223,6 @@ void fib_nh_release(struct net *net, struct fib_nh *fib_nh)
#endif
fib_nh_common_release(&fib_nh->nh_common);
free_nh_exceptions(fib_nh);
- rt_fibinfo_free_cpus(fib_nh->nh_pcpu_rth_output);
- rt_fibinfo_free(&fib_nh->nh_rth_input);
}
/* Release a nexthop info record */
@@ -472,9 +472,15 @@ int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *encap,
u16 encap_type, void *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{
+ int err;
+
+ nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *,
+ gfp_flags);
+ if (!nhc->nhc_pcpu_rth_output)
+ return -ENOMEM;
+
if (encap) {
struct lwtunnel_state *lwtstate;
- int err;
if (encap_type == LWTUNNEL_ENCAP_NONE) {
NL_SET_ERR_MSG(extack, "LWT encap type not specified");
@@ -483,12 +489,17 @@ int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *encap,
err = lwtunnel_build_state(encap_type, encap, nhc->nhc_family,
cfg, &lwtstate, extack);
if (err)
- return err;
+ goto lwt_failure;
nhc->nhc_lwtstate = lwtstate_get(lwtstate);
}
return 0;
+
+lwt_failure:
+ rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
+ nhc->nhc_pcpu_rth_output = NULL;
+ return err;
}
EXPORT_SYMBOL_GPL(fib_nh_common_init);
@@ -496,18 +507,14 @@ int fib_nh_init(struct net *net, struct fib_nh *nh,
struct fib_config *cfg, int nh_weight,
struct netlink_ext_ack *extack)
{
- int err = -ENOMEM;
+ int err;
nh->fib_nh_family = AF_INET;
- nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *);
- if (!nh->nh_pcpu_rth_output)
- goto err_out;
-
err = fib_nh_common_init(&nh->nh_common, cfg->fc_encap,
cfg->fc_encap_type, cfg, GFP_KERNEL, extack);
if (err)
- goto init_failure;
+ return err;
nh->fib_nh_oif = cfg->fc_oif;
if (cfg->fc_gw) {
@@ -525,12 +532,6 @@ int fib_nh_init(struct net *net, struct fib_nh *nh,
nh->fib_nh_weight = nh_weight;
#endif
return 0;
-
-init_failure:
- rt_fibinfo_free_cpus(nh->nh_pcpu_rth_output);
- nh->nh_pcpu_rth_output = NULL;
-err_out:
- return err;
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3556d87558e6..60d525391908 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -637,6 +637,7 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh
static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
u32 pmtu, bool lock, unsigned long expires)
{
+ struct fib_nh_common *nhc = &nh->nh_common;
struct fnhe_hash_bucket *hash;
struct fib_nh_exception *fnhe;
struct rtable *rt;
@@ -706,13 +707,13 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
* stale, so anyone caching it rechecks if this exception
* applies to them.
*/
- rt = rcu_dereference(nh->nh_rth_input);
+ rt = rcu_dereference(nhc->nhc_rth_input);
if (rt)
rt->dst.obsolete = DST_OBSOLETE_KILL;
for_each_possible_cpu(i) {
struct rtable __rcu **prt;
- prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i);
+ prt = per_cpu_ptr(nhc->nhc_pcpu_rth_output, i);
rt = rcu_dereference(*prt);
if (rt)
rt->dst.obsolete = DST_OBSOLETE_KILL;
@@ -1432,13 +1433,14 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
{
+ struct fib_nh_common *nhc = &nh->nh_common;
struct rtable *orig, *prev, **p;
bool ret = true;
if (rt_is_input_route(rt)) {
- p = (struct rtable **)&nh->nh_rth_input;
+ p = (struct rtable **)&nhc->nhc_rth_input;
} else {
- p = (struct rtable **)raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ p = (struct rtable **)raw_cpu_ptr(nhc->nhc_pcpu_rth_output);
}
orig = *p;
@@ -1762,7 +1764,7 @@ static int __mkroute_input(struct sk_buff *skb,
if (fnhe)
rth = rcu_dereference(fnhe->fnhe_rth_input);
else
- rth = rcu_dereference(nh->nh_rth_input);
+ rth = rcu_dereference(nhc->nhc_rth_input);
if (rt_cache_valid(rth)) {
skb_dst_set_noref(skb, &rth->dst);
goto out;
@@ -2057,10 +2059,8 @@ out: return err;
if (res->fi) {
if (!itag) {
struct fib_nh_common *nhc = FIB_RES_NH(*res);
- struct fib_nh *nh;
- nh = container_of(nhc, struct fib_nh, nh_common);
- rth = rcu_dereference(nh->nh_rth_input);
+ rth = rcu_dereference(nhc->nhc_rth_input);
if (rt_cache_valid(rth)) {
skb_dst_set_noref(skb, &rth->dst);
err = 0;
@@ -2289,7 +2289,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
do_cache = false;
goto add;
}
- prth = raw_cpu_ptr(nh->nh_pcpu_rth_output);
+ prth = raw_cpu_ptr(nhc->nhc_pcpu_rth_output);
}
rth = rcu_dereference(*prth);
if (rt_cache_valid(rth) && dst_hold_safe(&rth->dst))
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net-next 3/8] ipv4: Move cached routes to fib_nh_common
2019-03-30 0:47 ` [PATCH net-next 3/8] ipv4: Move cached routes to fib_nh_common David Ahern
@ 2019-03-31 0:11 ` David Ahern
2019-03-31 1:41 ` David Miller
0 siblings, 1 reply; 11+ messages in thread
From: David Ahern @ 2019-03-31 0:11 UTC (permalink / raw)
To: David Ahern, davem, netdev; +Cc: idosch
On 3/29/19 6:47 PM, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> While the cached routes, nh_pcpu_rth_output and nh_rth_input, are IPv4
> specific, a later patch wants to make them accessible for IPv6
> gateways with IPv4 routes but also allow IPv6 routes to have their own
> cached entries. Move the IPv4 cached routes from fib_nh to fib_nh_common
> and update references.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
> include/net/ip_fib.h | 6 ++++--
> net/ipv4/fib_semantics.c | 33 +++++++++++++++++----------------
> net/ipv4/route.c | 18 +++++++++---------
> 3 files changed, 30 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
> index 5070bc531ca4..cce437a1b2ff 100644
> --- a/include/net/ip_fib.h
> +++ b/include/net/ip_fib.h
> @@ -92,6 +92,10 @@ struct fib_nh_common {
>
> int nhc_weight;
> atomic_t nhc_upper_bound;
> +
> + /* v4 specific, but allows v6 gw with v4 routes */
> + struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
> + struct rtable __rcu *nhc_rth_input;
> };
>
Dave: please drop this set. I need to take another look at the
combinations and make sure I did not miss something.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net-next 4/8] ipv6: Move exceptions to fib_nh_common
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
` (2 preceding siblings ...)
2019-03-30 0:47 ` [PATCH net-next 3/8] ipv4: Move cached routes to fib_nh_common David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 5/8] ipv4: Switch to nhc_exceptions for exception bucket David Ahern
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Exceptions are really per device, so move rt6i_exception_bucket to
fib_nh_common as a generic nhc_exception_bucket. Move the flushed
flag to common as well. fib_nh_common for both is a strategic choice
to reduce memory consumption. Moving to fib6_nh pushes the struct over
256 which increases the actual allocation of a fib entry to 512.
Exception flushing when a fib entry is deleted is limited to the exceptions
per nexthop that reference the to-be-deleted fib entry (ie., 'from' points
to it). When a fib6_nh is released, all exceptions are flushed.
Move the core logic of rt6_flush_exceptions, rt6_remove_exception_rt and
rt6_update_exception_stamp_rt to helpers that can be invoked per fib6_nh.
For fib6_nh_flush_exceptions, only remove the exception if from is NULL
(ie., flushing all exceptions) or the rt6_info->from matches (fib delete).
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip6_fib.h | 6 +--
include/net/ip_fib.h | 4 +-
net/ipv6/ip6_fib.c | 7 ---
net/ipv6/route.c | 140 ++++++++++++++++++++++++++++++++------------------
4 files changed, 96 insertions(+), 61 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 58dbb4e82908..c1d1e32e1a19 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -153,7 +153,6 @@ struct fib6_info {
struct rt6key fib6_prefsrc;
struct rt6_info * __percpu *rt6i_pcpu;
- struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
#ifdef CONFIG_IPV6_ROUTER_PREF
unsigned long last_probe;
@@ -162,12 +161,11 @@ struct fib6_info {
u32 fib6_metric;
u8 fib6_protocol;
u8 fib6_type;
- u8 exception_bucket_flushed:1,
- should_flush:1,
+ u8 should_flush:1,
dst_nocount:1,
dst_nopolicy:1,
dst_host:1,
- unused:3;
+ unused:4;
struct fib6_nh fib6_nh;
struct rcu_head rcu;
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index cce437a1b2ff..063430ca0c6e 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -84,7 +84,8 @@ struct fib_nh_common {
unsigned char nhc_scope;
u8 nhc_family;
u8 nhc_has_gw:1,
- unused:7;
+ nhc_exceptions_flushed:1,
+ unused:6;
union {
__be32 ipv4;
struct in6_addr ipv6;
@@ -96,6 +97,7 @@ struct fib_nh_common {
/* v4 specific, but allows v6 gw with v4 routes */
struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
struct rtable __rcu *nhc_rth_input;
+ void __rcu *nhc_exceptions;
};
struct fib_nh {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8c00609a1513..cce976a59a8c 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -170,16 +170,9 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
void fib6_info_destroy_rcu(struct rcu_head *head)
{
struct fib6_info *f6i = container_of(head, struct fib6_info, rcu);
- struct rt6_exception_bucket *bucket;
WARN_ON(f6i->fib6_node);
- bucket = rcu_dereference_protected(f6i->rt6i_exception_bucket, 1);
- if (bucket) {
- f6i->rt6i_exception_bucket = NULL;
- kfree(bucket);
- }
-
if (f6i->rt6i_pcpu) {
int cpu;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e0ee30cbd079..c66b9ac37036 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1413,6 +1413,7 @@ static unsigned int fib6_mtu(const struct fib6_info *rt)
static int rt6_insert_exception(struct rt6_info *nrt,
struct fib6_info *ort)
{
+ struct fib_nh_common *nhc = &ort->fib6_nh.nh_common;
struct net *net = dev_net(nrt->dst.dev);
struct rt6_exception_bucket *bucket;
struct in6_addr *src_key = NULL;
@@ -1421,12 +1422,12 @@ static int rt6_insert_exception(struct rt6_info *nrt,
spin_lock_bh(&rt6_exception_lock);
- if (ort->exception_bucket_flushed) {
+ if (nhc->nhc_exceptions_flushed) {
err = -EINVAL;
goto out;
}
- bucket = rcu_dereference_protected(ort->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
if (!bucket) {
bucket = kcalloc(FIB6_EXCEPTION_BUCKET_SIZE, sizeof(*bucket),
@@ -1435,7 +1436,7 @@ static int rt6_insert_exception(struct rt6_info *nrt,
err = -ENOMEM;
goto out;
}
- rcu_assign_pointer(ort->rt6i_exception_bucket, bucket);
+ rcu_assign_pointer(nhc->nhc_exceptions, bucket);
}
#ifdef CONFIG_IPV6_SUBTREES
@@ -1490,8 +1491,9 @@ static int rt6_insert_exception(struct rt6_info *nrt,
return err;
}
-void rt6_flush_exceptions(struct fib6_info *rt)
+static void fib6_nh_flush_exceptions(struct fib6_nh *nh, struct fib6_info *from)
{
+ struct fib_nh_common *nhc = &nh->nh_common;
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
struct hlist_node *tmp;
@@ -1499,17 +1501,21 @@ void rt6_flush_exceptions(struct fib6_info *rt)
spin_lock_bh(&rt6_exception_lock);
/* Prevent rt6_insert_exception() to recreate the bucket list */
- rt->exception_bucket_flushed = 1;
+ if (!from)
+ nhc->nhc_exceptions_flushed = 1;
- bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
if (!bucket)
goto out;
for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) {
- hlist_for_each_entry_safe(rt6_ex, tmp, &bucket->chain, hlist)
- rt6_remove_exception(bucket, rt6_ex);
- WARN_ON_ONCE(bucket->depth);
+ hlist_for_each_entry_safe(rt6_ex, tmp, &bucket->chain, hlist) {
+ if (!from ||
+ rcu_access_pointer(rt6_ex->rt6i->from) == from)
+ rt6_remove_exception(bucket, rt6_ex);
+ }
+ WARN_ON_ONCE(!from && bucket->depth);
bucket++;
}
@@ -1517,6 +1523,11 @@ void rt6_flush_exceptions(struct fib6_info *rt)
spin_unlock_bh(&rt6_exception_lock);
}
+void rt6_flush_exceptions(struct fib6_info *f6i)
+{
+ fib6_nh_flush_exceptions(&f6i->fib6_nh, f6i);
+}
+
/* Find cached rt in the hash table inside passed in rt
* Caller has to hold rcu_read_lock()
*/
@@ -1524,12 +1535,13 @@ static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt,
struct in6_addr *daddr,
struct in6_addr *saddr)
{
+ struct fib_nh_common *nhc = &rt->fib6_nh.nh_common;
struct rt6_exception_bucket *bucket;
struct in6_addr *src_key = NULL;
struct rt6_exception *rt6_ex;
struct rt6_info *res = NULL;
- bucket = rcu_dereference(rt->rt6i_exception_bucket);
+ bucket = rcu_dereference(nhc->nhc_exceptions);
#ifdef CONFIG_IPV6_SUBTREES
/* rt6i_src.plen != 0 indicates rt is in subtree
@@ -1549,25 +1561,20 @@ static struct rt6_info *rt6_find_cached_rt(struct fib6_info *rt,
return res;
}
-/* Remove the passed in cached rt from the hash table that contains it */
-static int rt6_remove_exception_rt(struct rt6_info *rt)
+static int fib6_nh_remove_exception(struct fib6_nh *nh, int plen,
+ const struct rt6_info *rt)
{
+ struct fib_nh_common *nhc = &nh->nh_common;
+ const struct in6_addr *src_key = NULL;
struct rt6_exception_bucket *bucket;
- struct in6_addr *src_key = NULL;
struct rt6_exception *rt6_ex;
- struct fib6_info *from;
- int err;
-
- from = rcu_dereference(rt->from);
- if (!from ||
- !(rt->rt6i_flags & RTF_CACHE))
- return -EINVAL;
+ int err = 0;
- if (!rcu_access_pointer(from->rt6i_exception_bucket))
+ if (!rcu_access_pointer(nhc->nhc_exceptions))
return -ENOENT;
spin_lock_bh(&rt6_exception_lock);
- bucket = rcu_dereference_protected(from->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
#ifdef CONFIG_IPV6_SUBTREES
/* rt6i_src.plen != 0 indicates 'from' is in subtree
@@ -1576,39 +1583,43 @@ static int rt6_remove_exception_rt(struct rt6_info *rt)
* Otherwise, the exception table is indexed by
* a hash of only rt6i_dst.
*/
- if (from->fib6_src.plen)
+ if (plen)
src_key = &rt->rt6i_src.addr;
#endif
rt6_ex = __rt6_find_exception_spinlock(&bucket,
&rt->rt6i_dst.addr,
src_key);
- if (rt6_ex) {
+ if (rt6_ex)
rt6_remove_exception(bucket, rt6_ex);
- err = 0;
- } else {
+ else
err = -ENOENT;
- }
spin_unlock_bh(&rt6_exception_lock);
return err;
}
-/* Find rt6_ex which contains the passed in rt cache and
- * refresh its stamp
- */
-static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
+/* Remove the passed in cached rt from the hash table that contains it */
+static int rt6_remove_exception_rt(struct rt6_info *rt)
{
- struct rt6_exception_bucket *bucket;
- struct in6_addr *src_key = NULL;
- struct rt6_exception *rt6_ex;
struct fib6_info *from;
- rcu_read_lock();
from = rcu_dereference(rt->from);
if (!from || !(rt->rt6i_flags & RTF_CACHE))
- goto unlock;
+ return -EINVAL;
- bucket = rcu_dereference(from->rt6i_exception_bucket);
+ return fib6_nh_remove_exception(&from->fib6_nh,
+ from->fib6_src.plen, rt);
+}
+
+static void fib6_nh_update_exception(struct fib6_nh *nh, int plen,
+ const struct rt6_info *rt)
+{
+ struct fib_nh_common *nhc = &nh->nh_common;
+ const struct in6_addr *src_key = NULL;
+ struct rt6_exception_bucket *bucket;
+ struct rt6_exception *rt6_ex;
+
+ bucket = rcu_dereference(nhc->nhc_exceptions);
#ifdef CONFIG_IPV6_SUBTREES
/* rt6i_src.plen != 0 indicates 'from' is in subtree
@@ -1617,15 +1628,28 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
* Otherwise, the exception table is indexed by
* a hash of only rt6i_dst.
*/
- if (from->fib6_src.plen)
+ if (plen)
src_key = &rt->rt6i_src.addr;
#endif
- rt6_ex = __rt6_find_exception_rcu(&bucket,
- &rt->rt6i_dst.addr,
- src_key);
+ rt6_ex = __rt6_find_exception_rcu(&bucket, &rt->rt6i_dst.addr, src_key);
if (rt6_ex)
rt6_ex->stamp = jiffies;
+}
+
+/* Find rt6_ex which contains the passed in rt cache and
+ * refresh its stamp
+ */
+static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
+{
+ struct fib6_info *from;
+
+ rcu_read_lock();
+ from = rcu_dereference(rt->from);
+ if (!from || !(rt->rt6i_flags & RTF_CACHE))
+ goto unlock;
+
+ fib6_nh_update_exception(&from->fib6_nh, from->fib6_src.plen, rt);
unlock:
rcu_read_unlock();
}
@@ -1655,11 +1679,12 @@ static bool rt6_mtu_change_route_allowed(struct inet6_dev *idev,
static void rt6_exceptions_update_pmtu(struct inet6_dev *idev,
struct fib6_info *rt, int mtu)
{
+ struct fib_nh_common *nhc = &rt->fib6_nh.nh_common;
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
int i;
- bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
if (!bucket)
@@ -1686,16 +1711,17 @@ static void rt6_exceptions_update_pmtu(struct inet6_dev *idev,
static void rt6_exceptions_clean_tohost(struct fib6_info *rt,
struct in6_addr *gateway)
{
+ struct fib_nh_common *nhc = &rt->fib6_nh.nh_common;
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
struct hlist_node *tmp;
int i;
- if (!rcu_access_pointer(rt->rt6i_exception_bucket))
+ if (!rcu_access_pointer(nhc->nhc_exceptions))
return;
spin_lock_bh(&rt6_exception_lock);
- bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
if (bucket) {
@@ -1768,15 +1794,18 @@ void rt6_age_exceptions(struct fib6_info *rt,
{
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
+ struct fib_nh_common *nhc;
struct hlist_node *tmp;
int i;
- if (!rcu_access_pointer(rt->rt6i_exception_bucket))
- return;
-
rcu_read_lock_bh();
+
+ nhc = &rt->fib6_nh.nh_common;
+ if (!rcu_access_pointer(nhc->nhc_exceptions))
+ goto out;
+
spin_lock(&rt6_exception_lock);
- bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&rt6_exception_lock));
if (bucket) {
@@ -1790,6 +1819,7 @@ void rt6_age_exceptions(struct fib6_info *rt,
}
}
spin_unlock(&rt6_exception_lock);
+out:
rcu_read_unlock_bh();
}
@@ -2596,6 +2626,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst)
u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
struct in6_addr *saddr)
{
+ struct fib_nh_common *nhc = &f6i->fib6_nh.nh_common;
struct rt6_exception_bucket *bucket;
struct rt6_exception *rt6_ex;
struct in6_addr *src_key;
@@ -2614,7 +2645,7 @@ u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
src_key = saddr;
#endif
- bucket = rcu_dereference(f6i->rt6i_exception_bucket);
+ bucket = rcu_dereference(nhc->nhc_exceptions);
rt6_ex = __rt6_find_exception_rcu(&bucket, daddr, src_key);
if (rt6_ex && !rt6_check_expired(rt6_ex->rt6i))
mtu = dst_metric_raw(&rt6_ex->rt6i->dst, RTAX_MTU);
@@ -3011,6 +3042,17 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
void fib6_nh_release(struct fib6_nh *fib6_nh)
{
+ struct fib_nh_common *nhc = &fib6_nh->nh_common;
+ struct rt6_exception_bucket *bucket;
+
+ fib6_nh_flush_exceptions(fib6_nh, NULL);
+
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions, 1);
+ if (bucket) {
+ rcu_assign_pointer(nhc->nhc_exceptions, NULL);
+ kfree(bucket);
+ }
+
fib_nh_common_release(&fib6_nh->nh_common);
}
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 5/8] ipv4: Switch to nhc_exceptions for exception bucket
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
` (3 preceding siblings ...)
2019-03-30 0:47 ` [PATCH net-next 4/8] ipv6: Move exceptions " David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 6/8] ipv4: Refactor nexthop attributes in fib_dump_info David Ahern
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Flip IPv4 to use nhc_exceptions for fnhe_hash_bucket and drop
nh_exceptions from fib_nh.
Simplify the code a bit by converting update_or_create_fnhe,
find_exception and rt_cache_route to take fib_nh_common as the input
over fib_nh.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip_fib.h | 1 -
net/ipv4/fib_semantics.c | 13 +++++---
net/ipv4/route.c | 87 +++++++++++++++++++++++-------------------------
3 files changed, 50 insertions(+), 51 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 063430ca0c6e..9849c8901033 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -109,7 +109,6 @@ struct fib_nh {
#endif
__be32 nh_saddr;
int nh_saddr_genid;
- struct fnhe_hash_bucket __rcu *nh_exceptions;
#define fib_nh_family nh_common.nhc_family
#define fib_nh_dev nh_common.nhc_dev
#define fib_nh_oif nh_common.nhc_oif
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e8c9208d35d2..9db4c61ebe1c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -157,12 +157,12 @@ static void rt_fibinfo_free(struct rtable __rcu **rtp)
dst_release_immediate(&rt->dst);
}
-static void free_nh_exceptions(struct fib_nh *nh)
+static void free_nh_exceptions(struct fib_nh_common *nhc)
{
struct fnhe_hash_bucket *hash;
int i;
- hash = rcu_dereference_protected(nh->nh_exceptions, 1);
+ hash = rcu_dereference_protected(nhc->nhc_exceptions, 1);
if (!hash)
return;
for (i = 0; i < FNHE_HASH_SIZE; i++) {
@@ -217,12 +217,14 @@ EXPORT_SYMBOL_GPL(fib_nh_common_release);
void fib_nh_release(struct net *net, struct fib_nh *fib_nh)
{
+ struct fib_nh_common *nhc = &fib_nh->nh_common;
+
#ifdef CONFIG_IP_ROUTE_CLASSID
if (fib_nh->nh_tclassid)
net->ipv4.fib_num_tclassid_users--;
#endif
- fib_nh_common_release(&fib_nh->nh_common);
- free_nh_exceptions(fib_nh);
+ fib_nh_common_release(nhc);
+ free_nh_exceptions(nhc);
}
/* Release a nexthop info record */
@@ -1505,10 +1507,11 @@ static int call_fib_nh_notifiers(struct fib_nh *nh,
*/
static void nh_update_mtu(struct fib_nh *nh, u32 new, u32 orig)
{
+ struct fib_nh_common *nhc = &nh->nh_common;
struct fnhe_hash_bucket *bucket;
int i;
- bucket = rcu_dereference_protected(nh->nh_exceptions, 1);
+ bucket = rcu_dereference_protected(nhc->nhc_exceptions, 1);
if (!bucket)
return;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 60d525391908..75e2952c2964 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -634,10 +634,10 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh
}
}
-static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
- u32 pmtu, bool lock, unsigned long expires)
+static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
+ __be32 gw, u32 pmtu, bool lock,
+ unsigned long expires)
{
- struct fib_nh_common *nhc = &nh->nh_common;
struct fnhe_hash_bucket *hash;
struct fib_nh_exception *fnhe;
struct rtable *rt;
@@ -645,17 +645,20 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
unsigned int i;
int depth;
- genid = fnhe_genid(dev_net(nh->fib_nh_dev));
+ if (nhc->nhc_family != AF_INET)
+ return;
+
+ genid = fnhe_genid(dev_net(nhc->nhc_dev));
hval = fnhe_hashfun(daddr);
spin_lock_bh(&fnhe_lock);
- hash = rcu_dereference(nh->nh_exceptions);
+ hash = rcu_dereference(nhc->nhc_exceptions);
if (!hash) {
hash = kcalloc(FNHE_HASH_SIZE, sizeof(*hash), GFP_ATOMIC);
if (!hash)
goto out_unlock;
- rcu_assign_pointer(nh->nh_exceptions, hash);
+ rcu_assign_pointer(nhc->nhc_exceptions, hash);
}
hash += hval;
@@ -778,15 +781,10 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
if (!(n->nud_state & NUD_VALID)) {
neigh_event_send(n, NULL);
} else {
- if (fib_lookup(net, fl4, &res, 0) == 0) {
- struct fib_nh_common *nhc = FIB_RES_NH(res);
- struct fib_nh *nh;
-
- nh = container_of(nhc, struct fib_nh, nh_common);
- update_or_create_fnhe(nh, fl4->daddr, new_gw,
- 0, false,
+ if (fib_lookup(net, fl4, &res, 0) == 0)
+ update_or_create_fnhe(FIB_RES_NH(res),
+ fl4->daddr, new_gw, 0, false,
jiffies + ip_rt_gc_timeout);
- }
if (kill_route)
rt->dst.obsolete = DST_OBSOLETE_KILL;
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
@@ -1029,14 +1027,9 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
return;
rcu_read_lock();
- if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
- struct fib_nh_common *nhc = FIB_RES_NH(res);
- struct fib_nh *nh;
-
- nh = container_of(nhc, struct fib_nh, nh_common);
- update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock,
+ if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0)
+ update_or_create_fnhe(FIB_RES_NH(res), fl4->daddr, 0, mtu, lock,
jiffies + ip_rt_mtu_expires);
- }
rcu_read_unlock();
}
@@ -1292,7 +1285,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
}
-static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
+static void ip_del_fnhe(struct fib_nh_common *nhc, __be32 daddr)
{
struct fnhe_hash_bucket *hash;
struct fib_nh_exception *fnhe, __rcu **fnhe_p;
@@ -1300,7 +1293,7 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
spin_lock_bh(&fnhe_lock);
- hash = rcu_dereference_protected(nh->nh_exceptions,
+ hash = rcu_dereference_protected(nhc->nhc_exceptions,
lockdep_is_held(&fnhe_lock));
hash += hval;
@@ -1326,12 +1319,17 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
spin_unlock_bh(&fnhe_lock);
}
-static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
+static struct fib_nh_exception *find_exception(struct fib_nh_common *nhc,
+ __be32 daddr)
{
- struct fnhe_hash_bucket *hash = rcu_dereference(nh->nh_exceptions);
+ struct fnhe_hash_bucket *hash;
struct fib_nh_exception *fnhe;
u32 hval;
+ if (nhc->nhc_family != AF_INET)
+ return NULL;
+
+ hash = rcu_dereference(nhc->nhc_exceptions);
if (!hash)
return NULL;
@@ -1342,7 +1340,7 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
if (fnhe->fnhe_daddr == daddr) {
if (fnhe->fnhe_expires &&
time_after(jiffies, fnhe->fnhe_expires)) {
- ip_del_fnhe(nh, daddr);
+ ip_del_fnhe(nhc, daddr);
break;
}
return fnhe;
@@ -1369,10 +1367,9 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
mtu = fi->fib_mtu;
if (likely(!mtu)) {
- struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
struct fib_nh_exception *fnhe;
- fnhe = find_exception(nh, daddr);
+ fnhe = find_exception(nhc, daddr);
if (fnhe && !time_after_eq(jiffies, fnhe->fnhe_expires))
mtu = fnhe->fnhe_pmtu;
}
@@ -1431,9 +1428,8 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
return ret;
}
-static bool rt_cache_route(struct fib_nh *nh, struct rtable *rt)
+static bool rt_cache_route(struct fib_nh_common *nhc, struct rtable *rt)
{
- struct fib_nh_common *nhc = &nh->nh_common;
struct rtable *orig, *prev, **p;
bool ret = true;
@@ -1537,22 +1533,28 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
if (fi) {
struct fib_nh_common *nhc = FIB_RES_NH(*res);
- struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
- if (nh->fib_nh_gw4 && nh->fib_nh_scope == RT_SCOPE_LINK) {
- rt->rt_gateway = nh->fib_nh_gw4;
+ if (nhc->nhc_gw.ipv4 && nhc->nhc_scope == RT_SCOPE_LINK) {
+ rt->rt_gateway = nhc->nhc_gw.ipv4;
rt->rt_uses_gateway = 1;
}
ip_dst_init_metrics(&rt->dst, fi->fib_metrics);
#ifdef CONFIG_IP_ROUTE_CLASSID
- rt->dst.tclassid = nh->nh_tclassid;
+ if (nhc->nhc_family == AF_INET) {
+ struct fib_nh *nh;
+
+ nh = container_of(nhc, struct fib_nh, nh_common);
+ rt->dst.tclassid = nh->nh_tclassid;
+ }
#endif
- rt->dst.lwtstate = lwtstate_get(nh->fib_nh_lws);
+
+ rt->dst.lwtstate = lwtstate_get(nhc->nhc_lwtstate);
if (unlikely(fnhe))
cached = rt_bind_exception(rt, fnhe, daddr, do_cache);
else if (do_cache)
- cached = rt_cache_route(nh, rt);
+ cached = rt_cache_route(nhc, rt);
+
if (unlikely(!cached)) {
/* Routes we intend to cache in nexthop exception or
* FIB nexthop have the DST_NOCACHE bit clear.
@@ -1709,9 +1711,8 @@ static int __mkroute_input(struct sk_buff *skb,
{
struct fib_nh_common *nhc = FIB_RES_NH(*res);
struct net_device *dev = nhc->nhc_dev;
- struct fib_nh_exception *fnhe;
+ struct fib_nh_exception *fnhe = NULL;
struct rtable *rth;
- struct fib_nh *nh;
int err;
struct in_device *out_dev;
bool do_cache;
@@ -1758,8 +1759,7 @@ static int __mkroute_input(struct sk_buff *skb,
}
}
- nh = container_of(nhc, struct fib_nh, nh_common);
- fnhe = find_exception(nh, daddr);
+ fnhe = find_exception(nhc, daddr);
if (do_cache) {
if (fnhe)
rth = rcu_dereference(fnhe->fnhe_rth_input);
@@ -2091,7 +2091,6 @@ out: return err;
if (do_cache) {
struct fib_nh_common *nhc = FIB_RES_NH(*res);
- struct fib_nh *nh;
rth->dst.lwtstate = lwtstate_get(nhc->nhc_lwtstate);
if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
@@ -2100,8 +2099,7 @@ out: return err;
rth->dst.input = lwtunnel_input;
}
- nh = container_of(nhc, struct fib_nh, nh_common);
- if (unlikely(!rt_cache_route(nh, rth)))
+ if (unlikely(!rt_cache_route(nhc, rth)))
rt_add_uncached_list(rth);
}
skb_dst_set(skb, &rth->dst);
@@ -2273,10 +2271,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
do_cache &= fi != NULL;
if (fi) {
struct fib_nh_common *nhc = FIB_RES_NH(*res);
- struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
struct rtable __rcu **prth;
- fnhe = find_exception(nh, fl4->daddr);
+ fnhe = find_exception(nhc, fl4->daddr);
if (!do_cache)
goto add;
if (fnhe) {
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 6/8] ipv4: Refactor nexthop attributes in fib_dump_info
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
` (4 preceding siblings ...)
2019-03-30 0:47 ` [PATCH net-next 5/8] ipv4: Switch to nhc_exceptions for exception bucket David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 7/8] ipv4: Change fib_nexthop_info and fib_add_nexthop to take fib_nh_common David Ahern
2019-03-30 0:47 ` [PATCH net-next 8/8] ipv6: Flip to fib_nexthop_info David Ahern
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Similar to ipv6, move addition of nexthop attributes to dump
message into helpers that are called for both single path and
multipath routes. Align the new helpers to the IPv6 variant
which most notably means computing the flags argument based on
settings in nh_flags.
The RTA_FLOW argument is unique to IPv4, so it is appended after
the new fib_nexthop_info helper. The intent of a later patch is to
make both fib_nexthop_info and fib_add_nexthop usable for both IPv4
and IPv6. This patch is stepping stone in that direction.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv4/fib_semantics.c | 166 ++++++++++++++++++++++++++++++-----------------
1 file changed, 107 insertions(+), 59 deletions(-)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 9db4c61ebe1c..f5443b3102a5 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1323,6 +1323,103 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
return ERR_PTR(err);
}
+static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh *nh,
+ unsigned int *flags, bool skip_oif)
+{
+ if (nh->fib_nh_flags & RTNH_F_DEAD)
+ *flags |= RTNH_F_DEAD;
+
+ if (nh->fib_nh_flags & RTNH_F_LINKDOWN) {
+ *flags |= RTNH_F_LINKDOWN;
+
+ rcu_read_lock();
+ if (ip_ignore_linkdown(nh->fib_nh_dev))
+ *flags |= RTNH_F_DEAD;
+ rcu_read_unlock();
+ }
+
+ if (nh->fib_nh_gw4 &&
+ nla_put_in_addr(skb, RTA_GATEWAY, nh->fib_nh_gw4))
+ goto nla_put_failure;
+
+ *flags |= (nh->fib_nh_flags & RTNH_F_ONLINK);
+ if (nh->fib_nh_flags & RTNH_F_OFFLOAD)
+ *flags |= RTNH_F_OFFLOAD;
+
+ if (!skip_oif && nh->fib_nh_dev &&
+ nla_put_u32(skb, RTA_OIF, nh->fib_nh_dev->ifindex))
+ goto nla_put_failure;
+
+ if (nh->fib_nh_lws &&
+ lwtunnel_fill_encap(skb, nh->fib_nh_lws) < 0)
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh *nh)
+{
+ const struct net_device *dev = nh->fib_nh_dev;
+ struct rtnexthop *rtnh;
+ unsigned int flags = 0;
+
+ rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
+ if (!rtnh)
+ goto nla_put_failure;
+
+ rtnh->rtnh_hops = nh->fib_nh_weight - 1;
+ rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
+
+ if (fib_nexthop_info(skb, nh, &flags, true) < 0)
+ goto nla_put_failure;
+
+ rtnh->rtnh_flags = flags;
+
+ /* length of rtnetlink header + attributes */
+ rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh;
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
+{
+ struct nlattr *mp;
+
+ mp = nla_nest_start(skb, RTA_MULTIPATH);
+ if (!mp)
+ goto nla_put_failure;
+
+ for_nexthops(fi) {
+ if (fib_add_nexthop(skb, nh) < 0)
+ goto nla_put_failure;
+#ifdef CONFIG_IP_ROUTE_CLASSID
+ if (nh->nh_tclassid &&
+ nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
+ goto nla_put_failure;
+#endif
+ } endfor_nexthops(fi);
+
+ nla_nest_end(skb, mp);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+#else
+static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
+{
+ return 0;
+}
+#endif
+
int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos,
struct fib_info *fi, unsigned int flags)
@@ -1363,72 +1460,23 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc))
goto nla_put_failure;
if (fi->fib_nhs == 1) {
- if (fi->fib_nh->fib_nh_gw4 &&
- nla_put_in_addr(skb, RTA_GATEWAY, fi->fib_nh->fib_nh_gw4))
- goto nla_put_failure;
- if (fi->fib_nh->fib_nh_oif &&
- nla_put_u32(skb, RTA_OIF, fi->fib_nh->fib_nh_oif))
+ struct fib_nh *nh = &fi->fib_nh[0];
+ unsigned int flags = 0;
+
+ if (fib_nexthop_info(skb, nh, &flags, false) < 0)
goto nla_put_failure;
- if (fi->fib_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
- rcu_read_lock();
- if (ip_ignore_linkdown(fi->fib_nh->fib_nh_dev))
- rtm->rtm_flags |= RTNH_F_DEAD;
- rcu_read_unlock();
- }
- if (fi->fib_nh->fib_nh_flags & RTNH_F_OFFLOAD)
- rtm->rtm_flags |= RTNH_F_OFFLOAD;
+
+ rtm->rtm_flags = flags;
#ifdef CONFIG_IP_ROUTE_CLASSID
- if (fi->fib_nh[0].nh_tclassid &&
- nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
+ if (nh->nh_tclassid &&
+ nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
goto nla_put_failure;
#endif
- if (fi->fib_nh->fib_nh_lws &&
- lwtunnel_fill_encap(skb, fi->fib_nh->fib_nh_lws) < 0)
+ } else {
+ if (fib_add_multipath(skb, fi) < 0)
goto nla_put_failure;
}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (fi->fib_nhs > 1) {
- struct rtnexthop *rtnh;
- struct nlattr *mp;
-
- mp = nla_nest_start(skb, RTA_MULTIPATH);
- if (!mp)
- goto nla_put_failure;
- for_nexthops(fi) {
- rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
- if (!rtnh)
- goto nla_put_failure;
-
- rtnh->rtnh_flags = nh->fib_nh_flags & 0xFF;
- if (nh->fib_nh_flags & RTNH_F_LINKDOWN) {
- rcu_read_lock();
- if (ip_ignore_linkdown(nh->fib_nh_dev))
- rtnh->rtnh_flags |= RTNH_F_DEAD;
- rcu_read_unlock();
- }
- rtnh->rtnh_hops = nh->fib_nh_weight - 1;
- rtnh->rtnh_ifindex = nh->fib_nh_oif;
-
- if (nh->fib_nh_gw4 &&
- nla_put_in_addr(skb, RTA_GATEWAY, nh->fib_nh_gw4))
- goto nla_put_failure;
-#ifdef CONFIG_IP_ROUTE_CLASSID
- if (nh->nh_tclassid &&
- nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
- goto nla_put_failure;
-#endif
- if (nh->fib_nh_lws &&
- lwtunnel_fill_encap(skb, nh->fib_nh_lws) < 0)
- goto nla_put_failure;
-
- /* length of rtnetlink header + attributes */
- rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
- } endfor_nexthops(fi);
-
- nla_nest_end(skb, mp);
- }
-#endif
nlmsg_end(skb, nlh);
return 0;
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 7/8] ipv4: Change fib_nexthop_info and fib_add_nexthop to take fib_nh_common
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
` (5 preceding siblings ...)
2019-03-30 0:47 ` [PATCH net-next 6/8] ipv4: Refactor nexthop attributes in fib_dump_info David Ahern
@ 2019-03-30 0:47 ` David Ahern
2019-03-30 0:47 ` [PATCH net-next 8/8] ipv6: Flip to fib_nexthop_info David Ahern
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
With the exception of the nexthop weight, the nexthop attributes used by
fib_nexthop_info and fib_add_nexthop come from the fib_nh_common struct.
Update both to use it and change fib_nexthop_info to check the family
as needed.
nexthop weight comes from the common struct for existing use cases, but
for nexthop groups the weight is outside of the fib_nh_common to allow
the same nexthop definition to be used in multiple groups with different
weights.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/ipv4/fib_semantics.c | 50 ++++++++++++++++++++++++++++++------------------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f5443b3102a5..1efd6a88ccb5 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1323,35 +1323,44 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
return ERR_PTR(err);
}
-static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh *nh,
+static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
unsigned int *flags, bool skip_oif)
{
- if (nh->fib_nh_flags & RTNH_F_DEAD)
+ if (nh->nhc_flags & RTNH_F_DEAD)
*flags |= RTNH_F_DEAD;
- if (nh->fib_nh_flags & RTNH_F_LINKDOWN) {
+ if (nh->nhc_flags & RTNH_F_LINKDOWN) {
*flags |= RTNH_F_LINKDOWN;
rcu_read_lock();
- if (ip_ignore_linkdown(nh->fib_nh_dev))
- *flags |= RTNH_F_DEAD;
+ switch (nh->nhc_family) {
+ case AF_INET:
+ if (ip_ignore_linkdown(nh->nhc_dev))
+ *flags |= RTNH_F_DEAD;
+ break;
+ }
rcu_read_unlock();
}
- if (nh->fib_nh_gw4 &&
- nla_put_in_addr(skb, RTA_GATEWAY, nh->fib_nh_gw4))
- goto nla_put_failure;
+ if (nh->nhc_has_gw) {
+ switch (nh->nhc_family) {
+ case AF_INET:
+ if (nla_put_in_addr(skb, RTA_GATEWAY, nh->nhc_gw.ipv4))
+ goto nla_put_failure;
+ break;
+ }
+ }
- *flags |= (nh->fib_nh_flags & RTNH_F_ONLINK);
- if (nh->fib_nh_flags & RTNH_F_OFFLOAD)
+ *flags |= (nh->nhc_flags & RTNH_F_ONLINK);
+ if (nh->nhc_flags & RTNH_F_OFFLOAD)
*flags |= RTNH_F_OFFLOAD;
- if (!skip_oif && nh->fib_nh_dev &&
- nla_put_u32(skb, RTA_OIF, nh->fib_nh_dev->ifindex))
+ if (!skip_oif && nh->nhc_dev &&
+ nla_put_u32(skb, RTA_OIF, nh->nhc_dev->ifindex))
goto nla_put_failure;
- if (nh->fib_nh_lws &&
- lwtunnel_fill_encap(skb, nh->fib_nh_lws) < 0)
+ if (nh->nhc_lwtstate &&
+ lwtunnel_fill_encap(skb, nh->nhc_lwtstate) < 0)
goto nla_put_failure;
return 0;
@@ -1361,9 +1370,10 @@ static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh *nh,
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
-static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh *nh)
+static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
+ int nh_weight)
{
- const struct net_device *dev = nh->fib_nh_dev;
+ const struct net_device *dev = nh->nhc_dev;
struct rtnexthop *rtnh;
unsigned int flags = 0;
@@ -1371,7 +1381,7 @@ static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh *nh)
if (!rtnh)
goto nla_put_failure;
- rtnh->rtnh_hops = nh->fib_nh_weight - 1;
+ rtnh->rtnh_hops = nh_weight - 1;
rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
if (fib_nexthop_info(skb, nh, &flags, true) < 0)
@@ -1387,7 +1397,9 @@ static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh *nh)
nla_put_failure:
return -EMSGSIZE;
}
+#endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
{
struct nlattr *mp;
@@ -1397,7 +1409,7 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
goto nla_put_failure;
for_nexthops(fi) {
- if (fib_add_nexthop(skb, nh) < 0)
+ if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight) < 0)
goto nla_put_failure;
#ifdef CONFIG_IP_ROUTE_CLASSID
if (nh->nh_tclassid &&
@@ -1463,7 +1475,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
struct fib_nh *nh = &fi->fib_nh[0];
unsigned int flags = 0;
- if (fib_nexthop_info(skb, nh, &flags, false) < 0)
+ if (fib_nexthop_info(skb, &nh->nh_common, &flags, false) < 0)
goto nla_put_failure;
rtm->rtm_flags = flags;
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH net-next 8/8] ipv6: Flip to fib_nexthop_info
2019-03-30 0:47 [PATCH net-next 0/8] net: More movement to fib_nh_common David Ahern
` (6 preceding siblings ...)
2019-03-30 0:47 ` [PATCH net-next 7/8] ipv4: Change fib_nexthop_info and fib_add_nexthop to take fib_nh_common David Ahern
@ 2019-03-30 0:47 ` David Ahern
7 siblings, 0 replies; 11+ messages in thread
From: David Ahern @ 2019-03-30 0:47 UTC (permalink / raw)
To: davem, netdev; +Cc: idosch, David Ahern
From: David Ahern <dsahern@gmail.com>
Export fib_nexthop_info and fib_add_nexthop for use by IPv6 code.
Remove rt6_nexthop_info and rt6_add_nexthop in favor of the IPv4
versions. Update fib_nexthop_info for IPv6 linkdown check and
RTA_GATEWAY for AF_INET6.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/ip_fib.h | 5 ++++
net/ipv4/fib_semantics.c | 30 ++++++++++++++-----
net/ipv6/route.c | 78 +++++-------------------------------------------
3 files changed, 34 insertions(+), 79 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 9849c8901033..5b6f533eac92 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -495,4 +495,9 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
struct fib_dump_filter *filter,
struct netlink_callback *cb);
+
+int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
+ unsigned int *flags, bool skip_oif, bool for_ipv4);
+int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
+ int nh_weight, bool for_ipv4);
#endif /* _NET_FIB_H */
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 1efd6a88ccb5..efc487727d06 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -45,6 +45,7 @@
#include <net/nexthop.h>
#include <net/lwtunnel.h>
#include <net/fib_notifier.h>
+#include <net/addrconf.h>
#include "fib_lookup.h"
@@ -1323,8 +1324,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
return ERR_PTR(err);
}
-static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
- unsigned int *flags, bool skip_oif)
+int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
+ unsigned int *flags, bool skip_oif, bool for_ipv4)
{
if (nh->nhc_flags & RTNH_F_DEAD)
*flags |= RTNH_F_DEAD;
@@ -1338,6 +1339,10 @@ static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
if (ip_ignore_linkdown(nh->nhc_dev))
*flags |= RTNH_F_DEAD;
break;
+ case AF_INET6:
+ if (ip6_ignore_linkdown(nh->nhc_dev))
+ *flags |= RTNH_F_DEAD;
+ break;
}
rcu_read_unlock();
}
@@ -1348,6 +1353,11 @@ static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
if (nla_put_in_addr(skb, RTA_GATEWAY, nh->nhc_gw.ipv4))
goto nla_put_failure;
break;
+ case AF_INET6:
+ if (nla_put_in6_addr(skb, RTA_GATEWAY,
+ &nh->nhc_gw.ipv6) < 0)
+ goto nla_put_failure;
+ break;
}
}
@@ -1368,10 +1378,11 @@ static int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
nla_put_failure:
return -EMSGSIZE;
}
+EXPORT_SYMBOL_GPL(fib_nexthop_info);
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
- int nh_weight)
+#if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6)
+int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
+ int nh_weight, bool for_ipv4)
{
const struct net_device *dev = nh->nhc_dev;
struct rtnexthop *rtnh;
@@ -1384,7 +1395,7 @@ static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
rtnh->rtnh_hops = nh_weight - 1;
rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
- if (fib_nexthop_info(skb, nh, &flags, true) < 0)
+ if (fib_nexthop_info(skb, nh, &flags, true, for_ipv4) < 0)
goto nla_put_failure;
rtnh->rtnh_flags = flags;
@@ -1397,6 +1408,7 @@ static int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
nla_put_failure:
return -EMSGSIZE;
}
+EXPORT_SYMBOL_GPL(fib_add_nexthop);
#endif
#ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -1409,7 +1421,8 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
goto nla_put_failure;
for_nexthops(fi) {
- if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight) < 0)
+ if (fib_add_nexthop(skb, &nh->nh_common,
+ nh->fib_nh_weight, true) < 0)
goto nla_put_failure;
#ifdef CONFIG_IP_ROUTE_CLASSID
if (nh->nh_tclassid &&
@@ -1475,7 +1488,8 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
struct fib_nh *nh = &fi->fib_nh[0];
unsigned int flags = 0;
- if (fib_nexthop_info(skb, &nh->nh_common, &flags, false) < 0)
+ if (fib_nexthop_info(skb, &nh->nh_common, &flags,
+ false, true) < 0)
goto nla_put_failure;
rtm->rtm_flags = flags;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c66b9ac37036..26e058485fd2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -4624,73 +4624,6 @@ static size_t rt6_nlmsg_size(struct fib6_info *rt)
+ nexthop_len;
}
-static int rt6_nexthop_info(struct sk_buff *skb, const struct fib6_nh *fib6_nh,
- unsigned int *flags, bool skip_oif)
-{
- if (fib6_nh->fib_nh_flags & RTNH_F_DEAD)
- *flags |= RTNH_F_DEAD;
-
- if (fib6_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
- *flags |= RTNH_F_LINKDOWN;
-
- rcu_read_lock();
- if (ip6_ignore_linkdown(fib6_nh->fib_nh_dev))
- *flags |= RTNH_F_DEAD;
- rcu_read_unlock();
- }
-
- if (fib6_nh->fib_nh_has_gw) {
- if (nla_put_in6_addr(skb, RTA_GATEWAY, &fib6_nh->fib_nh_gw6) < 0)
- goto nla_put_failure;
- }
-
- *flags |= (fib6_nh->fib_nh_flags & RTNH_F_ONLINK);
- if (fib6_nh->fib_nh_flags & RTNH_F_OFFLOAD)
- *flags |= RTNH_F_OFFLOAD;
-
- /* not needed for multipath encoding b/c it has a rtnexthop struct */
- if (!skip_oif && fib6_nh->fib_nh_dev &&
- nla_put_u32(skb, RTA_OIF, fib6_nh->fib_nh_dev->ifindex))
- goto nla_put_failure;
-
- if (fib6_nh->fib_nh_lws &&
- lwtunnel_fill_encap(skb, fib6_nh->fib_nh_lws) < 0)
- goto nla_put_failure;
-
- return 0;
-
-nla_put_failure:
- return -EMSGSIZE;
-}
-
-/* add multipath next hop */
-static int rt6_add_nexthop(struct sk_buff *skb, const struct fib6_nh *fib6_nh)
-{
- const struct net_device *dev = fib6_nh->fib_nh_dev;
- struct rtnexthop *rtnh;
- unsigned int flags = 0;
-
- rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
- if (!rtnh)
- goto nla_put_failure;
-
- rtnh->rtnh_hops = fib6_nh->fib_nh_weight - 1;
- rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
-
- if (rt6_nexthop_info(skb, fib6_nh, &flags, true) < 0)
- goto nla_put_failure;
-
- rtnh->rtnh_flags = flags;
-
- /* length of rtnetlink header + attributes */
- rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh;
-
- return 0;
-
-nla_put_failure:
- return -EMSGSIZE;
-}
-
static int rt6_fill_node(struct net *net, struct sk_buff *skb,
struct fib6_info *rt, struct dst_entry *dst,
struct in6_addr *dest, struct in6_addr *src,
@@ -4807,19 +4740,22 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
if (!mp)
goto nla_put_failure;
- if (rt6_add_nexthop(skb, &rt->fib6_nh) < 0)
+ if (fib_add_nexthop(skb, &rt->fib6_nh.nh_common,
+ rt->fib6_nh.fib_nh_weight, false) < 0)
goto nla_put_failure;
list_for_each_entry_safe(sibling, next_sibling,
&rt->fib6_siblings, fib6_siblings) {
- if (rt6_add_nexthop(skb, &sibling->fib6_nh) < 0)
+ if (fib_add_nexthop(skb, &sibling->fib6_nh.nh_common,
+ sibling->fib6_nh.fib_nh_weight,
+ false) < 0)
goto nla_put_failure;
}
nla_nest_end(skb, mp);
} else {
- if (rt6_nexthop_info(skb, &rt->fib6_nh, &rtm->rtm_flags,
- false) < 0)
+ if (fib_nexthop_info(skb, &rt->fib6_nh.nh_common,
+ &rtm->rtm_flags, false, false) < 0)
goto nla_put_failure;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 11+ messages in thread