ipv4: Move exception bucket to nh_common
Similar to the cached routes, make IPv4 exceptions accessible when using an IPv6 nexthop struct with IPv4 routes. Simplify the exception functions by passing in fib_nh_common since that is all it needs, and then cleanup the call sites that have extraneous fib_nh conversions. As with the cached routes this is a change in location only, from fib_nh up to fib_nh_common; no functional change intended. Signed-off-by: David Ahern <dsahern@gmail.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
87063a1fa6
commit
a5995e7107
|
@ -100,6 +100,7 @@ struct fib_nh_common {
|
||||||
/* v4 specific, but allows fib6_nh with v4 routes */
|
/* v4 specific, but allows fib6_nh with v4 routes */
|
||||||
struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
|
struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
|
||||||
struct rtable __rcu *nhc_rth_input;
|
struct rtable __rcu *nhc_rth_input;
|
||||||
|
struct fnhe_hash_bucket __rcu *nhc_exceptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fib_nh {
|
struct fib_nh {
|
||||||
|
@ -111,7 +112,6 @@ struct fib_nh {
|
||||||
#endif
|
#endif
|
||||||
__be32 nh_saddr;
|
__be32 nh_saddr;
|
||||||
int nh_saddr_genid;
|
int nh_saddr_genid;
|
||||||
struct fnhe_hash_bucket __rcu *nh_exceptions;
|
|
||||||
#define fib_nh_family nh_common.nhc_family
|
#define fib_nh_family nh_common.nhc_family
|
||||||
#define fib_nh_dev nh_common.nhc_dev
|
#define fib_nh_dev nh_common.nhc_dev
|
||||||
#define fib_nh_oif nh_common.nhc_oif
|
#define fib_nh_oif nh_common.nhc_oif
|
||||||
|
|
|
@ -159,12 +159,12 @@ static void rt_fibinfo_free(struct rtable __rcu **rtp)
|
||||||
dst_release_immediate(&rt->dst);
|
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;
|
struct fnhe_hash_bucket *hash;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
hash = rcu_dereference_protected(nh->nh_exceptions, 1);
|
hash = rcu_dereference_protected(nhc->nhc_exceptions, 1);
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < FNHE_HASH_SIZE; i++) {
|
for (i = 0; i < FNHE_HASH_SIZE; i++) {
|
||||||
|
@ -214,6 +214,7 @@ void fib_nh_common_release(struct fib_nh_common *nhc)
|
||||||
lwtstate_put(nhc->nhc_lwtstate);
|
lwtstate_put(nhc->nhc_lwtstate);
|
||||||
rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
|
rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
|
||||||
rt_fibinfo_free(&nhc->nhc_rth_input);
|
rt_fibinfo_free(&nhc->nhc_rth_input);
|
||||||
|
free_nh_exceptions(nhc);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fib_nh_common_release);
|
EXPORT_SYMBOL_GPL(fib_nh_common_release);
|
||||||
|
|
||||||
|
@ -224,7 +225,6 @@ void fib_nh_release(struct net *net, struct fib_nh *fib_nh)
|
||||||
net->ipv4.fib_num_tclassid_users--;
|
net->ipv4.fib_num_tclassid_users--;
|
||||||
#endif
|
#endif
|
||||||
fib_nh_common_release(&fib_nh->nh_common);
|
fib_nh_common_release(&fib_nh->nh_common);
|
||||||
free_nh_exceptions(fib_nh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release a nexthop info record */
|
/* Release a nexthop info record */
|
||||||
|
@ -1713,12 +1713,12 @@ static int call_fib_nh_notifiers(struct fib_nh *nh,
|
||||||
* - if the new MTU is greater than the PMTU, don't make any change
|
* - if the new MTU is greater than the PMTU, don't make any change
|
||||||
* - otherwise, unlock and set PMTU
|
* - otherwise, unlock and set PMTU
|
||||||
*/
|
*/
|
||||||
static void nh_update_mtu(struct fib_nh *nh, u32 new, u32 orig)
|
static void nh_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig)
|
||||||
{
|
{
|
||||||
struct fnhe_hash_bucket *bucket;
|
struct fnhe_hash_bucket *bucket;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bucket = rcu_dereference_protected(nh->nh_exceptions, 1);
|
bucket = rcu_dereference_protected(nhc->nhc_exceptions, 1);
|
||||||
if (!bucket)
|
if (!bucket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1749,7 +1749,7 @@ void fib_sync_mtu(struct net_device *dev, u32 orig_mtu)
|
||||||
|
|
||||||
hlist_for_each_entry(nh, head, nh_hash) {
|
hlist_for_each_entry(nh, head, nh_hash) {
|
||||||
if (nh->fib_nh_dev == dev)
|
if (nh->fib_nh_dev == dev)
|
||||||
nh_update_mtu(nh, dev->mtu, orig_mtu);
|
nh_update_mtu(&nh->nh_common, dev->mtu, orig_mtu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -643,10 +643,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,
|
static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
|
||||||
u32 pmtu, bool lock, unsigned long expires)
|
__be32 gw, u32 pmtu, bool lock,
|
||||||
|
unsigned long expires)
|
||||||
{
|
{
|
||||||
struct fib_nh_common *nhc = &nh->nh_common;
|
|
||||||
struct fnhe_hash_bucket *hash;
|
struct fnhe_hash_bucket *hash;
|
||||||
struct fib_nh_exception *fnhe;
|
struct fib_nh_exception *fnhe;
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
|
@ -654,17 +654,17 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int depth;
|
int depth;
|
||||||
|
|
||||||
genid = fnhe_genid(dev_net(nh->fib_nh_dev));
|
genid = fnhe_genid(dev_net(nhc->nhc_dev));
|
||||||
hval = fnhe_hashfun(daddr);
|
hval = fnhe_hashfun(daddr);
|
||||||
|
|
||||||
spin_lock_bh(&fnhe_lock);
|
spin_lock_bh(&fnhe_lock);
|
||||||
|
|
||||||
hash = rcu_dereference(nh->nh_exceptions);
|
hash = rcu_dereference(nhc->nhc_exceptions);
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
hash = kcalloc(FNHE_HASH_SIZE, sizeof(*hash), GFP_ATOMIC);
|
hash = kcalloc(FNHE_HASH_SIZE, sizeof(*hash), GFP_ATOMIC);
|
||||||
if (!hash)
|
if (!hash)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
rcu_assign_pointer(nh->nh_exceptions, hash);
|
rcu_assign_pointer(nhc->nhc_exceptions, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash += hval;
|
hash += hval;
|
||||||
|
@ -789,10 +789,8 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
|
||||||
} else {
|
} else {
|
||||||
if (fib_lookup(net, fl4, &res, 0) == 0) {
|
if (fib_lookup(net, fl4, &res, 0) == 0) {
|
||||||
struct fib_nh_common *nhc = FIB_RES_NHC(res);
|
struct fib_nh_common *nhc = FIB_RES_NHC(res);
|
||||||
struct fib_nh *nh;
|
|
||||||
|
|
||||||
nh = container_of(nhc, struct fib_nh, nh_common);
|
update_or_create_fnhe(nhc, fl4->daddr, new_gw,
|
||||||
update_or_create_fnhe(nh, fl4->daddr, new_gw,
|
|
||||||
0, false,
|
0, false,
|
||||||
jiffies + ip_rt_gc_timeout);
|
jiffies + ip_rt_gc_timeout);
|
||||||
}
|
}
|
||||||
|
@ -1040,10 +1038,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
|
if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
|
||||||
struct fib_nh_common *nhc = FIB_RES_NHC(res);
|
struct fib_nh_common *nhc = FIB_RES_NHC(res);
|
||||||
struct fib_nh *nh;
|
|
||||||
|
|
||||||
nh = container_of(nhc, struct fib_nh, nh_common);
|
update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock,
|
||||||
update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock,
|
|
||||||
jiffies + ip_rt_mtu_expires);
|
jiffies + ip_rt_mtu_expires);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -1329,7 +1325,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
||||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
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 fnhe_hash_bucket *hash;
|
||||||
struct fib_nh_exception *fnhe, __rcu **fnhe_p;
|
struct fib_nh_exception *fnhe, __rcu **fnhe_p;
|
||||||
|
@ -1337,7 +1333,7 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
|
||||||
|
|
||||||
spin_lock_bh(&fnhe_lock);
|
spin_lock_bh(&fnhe_lock);
|
||||||
|
|
||||||
hash = rcu_dereference_protected(nh->nh_exceptions,
|
hash = rcu_dereference_protected(nhc->nhc_exceptions,
|
||||||
lockdep_is_held(&fnhe_lock));
|
lockdep_is_held(&fnhe_lock));
|
||||||
hash += hval;
|
hash += hval;
|
||||||
|
|
||||||
|
@ -1363,9 +1359,10 @@ static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr)
|
||||||
spin_unlock_bh(&fnhe_lock);
|
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 = rcu_dereference(nhc->nhc_exceptions);
|
||||||
struct fib_nh_exception *fnhe;
|
struct fib_nh_exception *fnhe;
|
||||||
u32 hval;
|
u32 hval;
|
||||||
|
|
||||||
|
@ -1379,7 +1376,7 @@ static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr)
|
||||||
if (fnhe->fnhe_daddr == daddr) {
|
if (fnhe->fnhe_daddr == daddr) {
|
||||||
if (fnhe->fnhe_expires &&
|
if (fnhe->fnhe_expires &&
|
||||||
time_after(jiffies, fnhe->fnhe_expires)) {
|
time_after(jiffies, fnhe->fnhe_expires)) {
|
||||||
ip_del_fnhe(nh, daddr);
|
ip_del_fnhe(nhc, daddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return fnhe;
|
return fnhe;
|
||||||
|
@ -1406,10 +1403,9 @@ u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr)
|
||||||
mtu = fi->fib_mtu;
|
mtu = fi->fib_mtu;
|
||||||
|
|
||||||
if (likely(!mtu)) {
|
if (likely(!mtu)) {
|
||||||
struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
|
|
||||||
struct fib_nh_exception *fnhe;
|
struct fib_nh_exception *fnhe;
|
||||||
|
|
||||||
fnhe = find_exception(nh, daddr);
|
fnhe = find_exception(nhc, daddr);
|
||||||
if (fnhe && !time_after_eq(jiffies, fnhe->fnhe_expires))
|
if (fnhe && !time_after_eq(jiffies, fnhe->fnhe_expires))
|
||||||
mtu = fnhe->fnhe_pmtu;
|
mtu = fnhe->fnhe_pmtu;
|
||||||
}
|
}
|
||||||
|
@ -1760,7 +1756,6 @@ static int __mkroute_input(struct sk_buff *skb,
|
||||||
struct net_device *dev = nhc->nhc_dev;
|
struct net_device *dev = nhc->nhc_dev;
|
||||||
struct fib_nh_exception *fnhe;
|
struct fib_nh_exception *fnhe;
|
||||||
struct rtable *rth;
|
struct rtable *rth;
|
||||||
struct fib_nh *nh;
|
|
||||||
int err;
|
int err;
|
||||||
struct in_device *out_dev;
|
struct in_device *out_dev;
|
||||||
bool do_cache;
|
bool do_cache;
|
||||||
|
@ -1808,8 +1803,7 @@ static int __mkroute_input(struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nh = container_of(nhc, struct fib_nh, nh_common);
|
fnhe = find_exception(nhc, daddr);
|
||||||
fnhe = find_exception(nh, daddr);
|
|
||||||
if (do_cache) {
|
if (do_cache) {
|
||||||
if (fnhe)
|
if (fnhe)
|
||||||
rth = rcu_dereference(fnhe->fnhe_rth_input);
|
rth = rcu_dereference(fnhe->fnhe_rth_input);
|
||||||
|
@ -2321,10 +2315,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
|
||||||
do_cache &= fi != NULL;
|
do_cache &= fi != NULL;
|
||||||
if (fi) {
|
if (fi) {
|
||||||
struct fib_nh_common *nhc = FIB_RES_NHC(*res);
|
struct fib_nh_common *nhc = FIB_RES_NHC(*res);
|
||||||
struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
|
|
||||||
struct rtable __rcu **prth;
|
struct rtable __rcu **prth;
|
||||||
|
|
||||||
fnhe = find_exception(nh, fl4->daddr);
|
fnhe = find_exception(nhc, fl4->daddr);
|
||||||
if (!do_cache)
|
if (!do_cache)
|
||||||
goto add;
|
goto add;
|
||||||
if (fnhe) {
|
if (fnhe) {
|
||||||
|
|
Loading…
Reference in New Issue