net: ipv4: refactor __ip_route_output_key_hash
A later patch wants access to the fib result on an output route lookup with the rcu lock held. Refactor __ip_route_output_key_hash, pushing the logic between rcu_read_lock ... rcu_read_unlock into a new helper with the fib_result as an input arg. To keep the name length under control remove the leading underscores from the name and add _rcu to the name of the new helper indicating it is called with the rcu read lock held. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
5dafc87f40
Коммит
3abd1ade67
|
@ -113,13 +113,16 @@ struct in_device;
|
||||||
int ip_rt_init(void);
|
int ip_rt_init(void);
|
||||||
void rt_cache_flush(struct net *net);
|
void rt_cache_flush(struct net *net);
|
||||||
void rt_flush_dev(struct net_device *dev);
|
void rt_flush_dev(struct net_device *dev);
|
||||||
struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
|
struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
|
||||||
const struct sk_buff *skb);
|
const struct sk_buff *skb);
|
||||||
|
struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *flp,
|
||||||
|
struct fib_result *res,
|
||||||
|
const struct sk_buff *skb);
|
||||||
|
|
||||||
static inline struct rtable *__ip_route_output_key(struct net *net,
|
static inline struct rtable *__ip_route_output_key(struct net *net,
|
||||||
struct flowi4 *flp)
|
struct flowi4 *flp)
|
||||||
{
|
{
|
||||||
return __ip_route_output_key_hash(net, flp, NULL);
|
return ip_route_output_key_hash(net, flp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
|
struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
|
||||||
|
|
|
@ -489,7 +489,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
||||||
fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
|
fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
|
||||||
|
|
||||||
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
|
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
|
||||||
rt = __ip_route_output_key_hash(net, fl4, skb_in);
|
rt = ip_route_output_key_hash(net, fl4, skb_in);
|
||||||
if (IS_ERR(rt))
|
if (IS_ERR(rt))
|
||||||
return rt;
|
return rt;
|
||||||
|
|
||||||
|
|
|
@ -2246,29 +2246,40 @@ add:
|
||||||
* Major route resolver routine.
|
* Major route resolver routine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||||
const struct sk_buff *skb)
|
const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct net_device *dev_out = NULL;
|
|
||||||
__u8 tos = RT_FL_TOS(fl4);
|
__u8 tos = RT_FL_TOS(fl4);
|
||||||
unsigned int flags = 0;
|
|
||||||
struct fib_result res;
|
struct fib_result res;
|
||||||
struct rtable *rth;
|
struct rtable *rth;
|
||||||
int orig_oif;
|
|
||||||
int err = -ENETUNREACH;
|
|
||||||
|
|
||||||
res.tclassid = 0;
|
res.tclassid = 0;
|
||||||
res.fi = NULL;
|
res.fi = NULL;
|
||||||
res.table = NULL;
|
res.table = NULL;
|
||||||
|
|
||||||
orig_oif = fl4->flowi4_oif;
|
|
||||||
|
|
||||||
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
fl4->flowi4_iif = LOOPBACK_IFINDEX;
|
||||||
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
|
fl4->flowi4_tos = tos & IPTOS_RT_MASK;
|
||||||
fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
|
fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
|
||||||
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
rth = ip_route_output_key_hash_rcu(net, fl4, &res, skb);
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return rth;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ip_route_output_key_hash);
|
||||||
|
|
||||||
|
struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
|
||||||
|
struct fib_result *res,
|
||||||
|
const struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct net_device *dev_out = NULL;
|
||||||
|
int orig_oif = fl4->flowi4_oif;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
struct rtable *rth;
|
||||||
|
int err = -ENETUNREACH;
|
||||||
|
|
||||||
if (fl4->saddr) {
|
if (fl4->saddr) {
|
||||||
rth = ERR_PTR(-EINVAL);
|
rth = ERR_PTR(-EINVAL);
|
||||||
if (ipv4_is_multicast(fl4->saddr) ||
|
if (ipv4_is_multicast(fl4->saddr) ||
|
||||||
|
@ -2354,15 +2365,15 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||||
fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
|
fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
|
||||||
dev_out = net->loopback_dev;
|
dev_out = net->loopback_dev;
|
||||||
fl4->flowi4_oif = LOOPBACK_IFINDEX;
|
fl4->flowi4_oif = LOOPBACK_IFINDEX;
|
||||||
res.type = RTN_LOCAL;
|
res->type = RTN_LOCAL;
|
||||||
flags |= RTCF_LOCAL;
|
flags |= RTCF_LOCAL;
|
||||||
goto make_route;
|
goto make_route;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fib_lookup(net, fl4, &res, 0);
|
err = fib_lookup(net, fl4, res, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
res.fi = NULL;
|
res->fi = NULL;
|
||||||
res.table = NULL;
|
res->table = NULL;
|
||||||
if (fl4->flowi4_oif &&
|
if (fl4->flowi4_oif &&
|
||||||
(ipv4_is_multicast(fl4->daddr) ||
|
(ipv4_is_multicast(fl4->daddr) ||
|
||||||
!netif_index_is_l3_master(net, fl4->flowi4_oif))) {
|
!netif_index_is_l3_master(net, fl4->flowi4_oif))) {
|
||||||
|
@ -2387,43 +2398,41 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
||||||
if (fl4->saddr == 0)
|
if (fl4->saddr == 0)
|
||||||
fl4->saddr = inet_select_addr(dev_out, 0,
|
fl4->saddr = inet_select_addr(dev_out, 0,
|
||||||
RT_SCOPE_LINK);
|
RT_SCOPE_LINK);
|
||||||
res.type = RTN_UNICAST;
|
res->type = RTN_UNICAST;
|
||||||
goto make_route;
|
goto make_route;
|
||||||
}
|
}
|
||||||
rth = ERR_PTR(err);
|
rth = ERR_PTR(err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.type == RTN_LOCAL) {
|
if (res->type == RTN_LOCAL) {
|
||||||
if (!fl4->saddr) {
|
if (!fl4->saddr) {
|
||||||
if (res.fi->fib_prefsrc)
|
if (res->fi->fib_prefsrc)
|
||||||
fl4->saddr = res.fi->fib_prefsrc;
|
fl4->saddr = res->fi->fib_prefsrc;
|
||||||
else
|
else
|
||||||
fl4->saddr = fl4->daddr;
|
fl4->saddr = fl4->daddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* L3 master device is the loopback for that domain */
|
/* L3 master device is the loopback for that domain */
|
||||||
dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
|
dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(*res)) ? :
|
||||||
net->loopback_dev;
|
net->loopback_dev;
|
||||||
fl4->flowi4_oif = dev_out->ifindex;
|
fl4->flowi4_oif = dev_out->ifindex;
|
||||||
flags |= RTCF_LOCAL;
|
flags |= RTCF_LOCAL;
|
||||||
goto make_route;
|
goto make_route;
|
||||||
}
|
}
|
||||||
|
|
||||||
fib_select_path(net, &res, fl4, skb);
|
fib_select_path(net, res, fl4, skb);
|
||||||
|
|
||||||
dev_out = FIB_RES_DEV(res);
|
dev_out = FIB_RES_DEV(*res);
|
||||||
fl4->flowi4_oif = dev_out->ifindex;
|
fl4->flowi4_oif = dev_out->ifindex;
|
||||||
|
|
||||||
|
|
||||||
make_route:
|
make_route:
|
||||||
rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
|
rth = __mkroute_output(res, fl4, orig_oif, dev_out, flags);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
rcu_read_unlock();
|
|
||||||
return rth;
|
return rth;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__ip_route_output_key_hash);
|
|
||||||
|
|
||||||
static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
|
static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче