Commit 5c1e6aa3 authored by David S. Miller's avatar David S. Miller

net: Make dst_alloc() take more explicit initializations.

Now the dst->dev, dev->obsolete, and dst->flags values can
be specified as well.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 778865a5
...@@ -350,7 +350,8 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) ...@@ -350,7 +350,8 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
} }
extern int dst_discard(struct sk_buff *skb); extern int dst_discard(struct sk_buff *skb);
extern void *dst_alloc(struct dst_ops * ops, int initial_ref); extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev,
int initial_ref, int initial_obsolete, int flags);
extern void __dst_free(struct dst_entry * dst); extern void __dst_free(struct dst_entry * dst);
extern struct dst_entry *dst_destroy(struct dst_entry * dst); extern struct dst_entry *dst_destroy(struct dst_entry * dst);
......
...@@ -166,7 +166,8 @@ EXPORT_SYMBOL(dst_discard); ...@@ -166,7 +166,8 @@ EXPORT_SYMBOL(dst_discard);
const u32 dst_default_metrics[RTAX_MAX]; const u32 dst_default_metrics[RTAX_MAX];
void *dst_alloc(struct dst_ops *ops, int initial_ref) void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
int initial_ref, int initial_obsolete, int flags)
{ {
struct dst_entry *dst; struct dst_entry *dst;
...@@ -177,12 +178,19 @@ void *dst_alloc(struct dst_ops *ops, int initial_ref) ...@@ -177,12 +178,19 @@ void *dst_alloc(struct dst_ops *ops, int initial_ref)
dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC); dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC);
if (!dst) if (!dst)
return NULL; return NULL;
atomic_set(&dst->__refcnt, initial_ref);
dst->ops = ops; dst->ops = ops;
dst->lastuse = jiffies; dst->dev = dev;
dst->path = dst; if (dev)
dst->input = dst->output = dst_discard; dev_hold(dev);
dst_init_metrics(dst, dst_default_metrics, true); dst_init_metrics(dst, dst_default_metrics, true);
dst->path = dst;
dst->input = dst_discard;
dst->output = dst_discard;
dst->obsolete = initial_obsolete;
atomic_set(&dst->__refcnt, initial_ref);
dst->lastuse = jiffies;
dst->flags = flags;
#if RT_CACHE_DEBUG >= 2 #if RT_CACHE_DEBUG >= 2
atomic_inc(&dst_total); atomic_inc(&dst_total);
#endif #endif
......
...@@ -1125,13 +1125,10 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o ...@@ -1125,13 +1125,10 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o
if (dev_out->flags & IFF_LOOPBACK) if (dev_out->flags & IFF_LOOPBACK)
flags |= RTCF_LOCAL; flags |= RTCF_LOCAL;
rt = dst_alloc(&dn_dst_ops, 0); rt = dst_alloc(&dn_dst_ops, dev_out, 1, 0, DST_HOST);
if (rt == NULL) if (rt == NULL)
goto e_nobufs; goto e_nobufs;
atomic_set(&rt->dst.__refcnt, 1);
rt->dst.flags = DST_HOST;
rt->fld.saddr = oldflp->saddr; rt->fld.saddr = oldflp->saddr;
rt->fld.daddr = oldflp->daddr; rt->fld.daddr = oldflp->daddr;
rt->fld.flowidn_oif = oldflp->flowidn_oif; rt->fld.flowidn_oif = oldflp->flowidn_oif;
...@@ -1146,8 +1143,6 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o ...@@ -1146,8 +1143,6 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o
rt->rt_dst_map = fld.daddr; rt->rt_dst_map = fld.daddr;
rt->rt_src_map = fld.saddr; rt->rt_src_map = fld.saddr;
rt->dst.dev = dev_out;
dev_hold(dev_out);
rt->dst.neighbour = neigh; rt->dst.neighbour = neigh;
neigh = NULL; neigh = NULL;
...@@ -1399,7 +1394,7 @@ static int dn_route_input_slow(struct sk_buff *skb) ...@@ -1399,7 +1394,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
} }
make_route: make_route:
rt = dst_alloc(&dn_dst_ops, 0); rt = dst_alloc(&dn_dst_ops, out_dev, 0, 0, DST_HOST);
if (rt == NULL) if (rt == NULL)
goto e_nobufs; goto e_nobufs;
...@@ -1419,9 +1414,7 @@ static int dn_route_input_slow(struct sk_buff *skb) ...@@ -1419,9 +1414,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
rt->fld.flowidn_iif = in_dev->ifindex; rt->fld.flowidn_iif = in_dev->ifindex;
rt->fld.flowidn_mark = fld.flowidn_mark; rt->fld.flowidn_mark = fld.flowidn_mark;
rt->dst.flags = DST_HOST;
rt->dst.neighbour = neigh; rt->dst.neighbour = neigh;
rt->dst.dev = out_dev;
rt->dst.lastuse = jiffies; rt->dst.lastuse = jiffies;
rt->dst.output = dn_rt_bug; rt->dst.output = dn_rt_bug;
switch(res.type) { switch(res.type) {
...@@ -1440,8 +1433,6 @@ static int dn_route_input_slow(struct sk_buff *skb) ...@@ -1440,8 +1433,6 @@ static int dn_route_input_slow(struct sk_buff *skb)
rt->dst.input = dst_discard; rt->dst.input = dst_discard;
} }
rt->rt_flags = flags; rt->rt_flags = flags;
if (rt->dst.dev)
dev_hold(rt->dst.dev);
err = dn_rt_set_next_hop(rt, &res); err = dn_rt_set_next_hop(rt, &res);
if (err) if (err)
......
...@@ -1833,17 +1833,13 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, ...@@ -1833,17 +1833,13 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4,
rt->rt_type = type; rt->rt_type = type;
} }
static struct rtable *rt_dst_alloc(bool nopolicy, bool noxfrm) static struct rtable *rt_dst_alloc(struct net_device *dev,
bool nopolicy, bool noxfrm)
{ {
struct rtable *rt = dst_alloc(&ipv4_dst_ops, 1); return dst_alloc(&ipv4_dst_ops, dev, 1, -1,
if (rt) { DST_HOST |
rt->dst.obsolete = -1; (nopolicy ? DST_NOPOLICY : 0) |
(noxfrm ? DST_NOXFRM : 0));
rt->dst.flags = DST_HOST |
(nopolicy ? DST_NOPOLICY : 0) |
(noxfrm ? DST_NOXFRM : 0);
}
return rt;
} }
/* called in rcu_read_lock() section */ /* called in rcu_read_lock() section */
...@@ -1876,7 +1872,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -1876,7 +1872,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (err < 0) if (err < 0)
goto e_err; goto e_err;
} }
rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); rth = rt_dst_alloc(init_net.loopback_dev,
IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
if (!rth) if (!rth)
goto e_nobufs; goto e_nobufs;
...@@ -1893,8 +1890,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, ...@@ -1893,8 +1890,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
#endif #endif
rth->rt_route_iif = dev->ifindex; rth->rt_route_iif = dev->ifindex;
rth->rt_iif = dev->ifindex; rth->rt_iif = dev->ifindex;
rth->dst.dev = init_net.loopback_dev;
dev_hold(rth->dst.dev);
rth->rt_oif = 0; rth->rt_oif = 0;
rth->rt_gateway = daddr; rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst; rth->rt_spec_dst= spec_dst;
...@@ -2013,7 +2008,8 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -2013,7 +2008,8 @@ static int __mkroute_input(struct sk_buff *skb,
} }
} }
rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), rth = rt_dst_alloc(out_dev->dev,
IN_DEV_CONF_GET(in_dev, NOPOLICY),
IN_DEV_CONF_GET(out_dev, NOXFRM)); IN_DEV_CONF_GET(out_dev, NOXFRM));
if (!rth) { if (!rth) {
err = -ENOBUFS; err = -ENOBUFS;
...@@ -2029,8 +2025,6 @@ static int __mkroute_input(struct sk_buff *skb, ...@@ -2029,8 +2025,6 @@ static int __mkroute_input(struct sk_buff *skb,
rth->rt_gateway = daddr; rth->rt_gateway = daddr;
rth->rt_route_iif = in_dev->dev->ifindex; rth->rt_route_iif = in_dev->dev->ifindex;
rth->rt_iif = in_dev->dev->ifindex; rth->rt_iif = in_dev->dev->ifindex;
rth->dst.dev = (out_dev)->dev;
dev_hold(rth->dst.dev);
rth->rt_oif = 0; rth->rt_oif = 0;
rth->rt_spec_dst= spec_dst; rth->rt_spec_dst= spec_dst;
...@@ -2188,7 +2182,8 @@ out: return err; ...@@ -2188,7 +2182,8 @@ out: return err;
RT_CACHE_STAT_INC(in_brd); RT_CACHE_STAT_INC(in_brd);
local_input: local_input:
rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); rth = rt_dst_alloc(net->loopback_dev,
IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
if (!rth) if (!rth)
goto e_nobufs; goto e_nobufs;
...@@ -2206,8 +2201,6 @@ out: return err; ...@@ -2206,8 +2201,6 @@ out: return err;
#endif #endif
rth->rt_route_iif = dev->ifindex; rth->rt_route_iif = dev->ifindex;
rth->rt_iif = dev->ifindex; rth->rt_iif = dev->ifindex;
rth->dst.dev = net->loopback_dev;
dev_hold(rth->dst.dev);
rth->rt_gateway = daddr; rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst; rth->rt_spec_dst= spec_dst;
rth->dst.input= ip_local_deliver; rth->dst.input= ip_local_deliver;
...@@ -2392,7 +2385,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2392,7 +2385,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
fi = NULL; fi = NULL;
} }
rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), rth = rt_dst_alloc(dev_out,
IN_DEV_CONF_GET(in_dev, NOPOLICY),
IN_DEV_CONF_GET(in_dev, NOXFRM)); IN_DEV_CONF_GET(in_dev, NOXFRM));
if (!rth) if (!rth)
return ERR_PTR(-ENOBUFS); return ERR_PTR(-ENOBUFS);
...@@ -2406,10 +2400,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res, ...@@ -2406,10 +2400,6 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
rth->rt_src = fl4->saddr; rth->rt_src = fl4->saddr;
rth->rt_route_iif = 0; rth->rt_route_iif = 0;
rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex; rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex;
/* get references to the devices that are to be hold by the routing
cache entry */
rth->dst.dev = dev_out;
dev_hold(dev_out);
rth->rt_gateway = fl4->daddr; rth->rt_gateway = fl4->daddr;
rth->rt_spec_dst= fl4->saddr; rth->rt_spec_dst= fl4->saddr;
...@@ -2711,7 +2701,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { ...@@ -2711,7 +2701,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
{ {
struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, 1); struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, NULL, 1, 0, 0);
struct rtable *ort = (struct rtable *) dst_orig; struct rtable *ort = (struct rtable *) dst_orig;
if (rt) { if (rt) {
......
...@@ -227,9 +227,10 @@ static struct rt6_info ip6_blk_hole_entry_template = { ...@@ -227,9 +227,10 @@ static struct rt6_info ip6_blk_hole_entry_template = {
#endif #endif
/* allocate dst with ip6_dst_ops */ /* allocate dst with ip6_dst_ops */
static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops,
struct net_device *dev)
{ {
return (struct rt6_info *)dst_alloc(ops, 0); return (struct rt6_info *)dst_alloc(ops, dev, 0, 0, 0);
} }
static void ip6_dst_destroy(struct dst_entry *dst) static void ip6_dst_destroy(struct dst_entry *dst)
...@@ -881,10 +882,10 @@ EXPORT_SYMBOL(ip6_route_output); ...@@ -881,10 +882,10 @@ EXPORT_SYMBOL(ip6_route_output);
struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
{ {
struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
struct rt6_info *ort = (struct rt6_info *) dst_orig;
struct dst_entry *new = NULL; struct dst_entry *new = NULL;
rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0);
if (rt) { if (rt) {
new = &rt->dst; new = &rt->dst;
...@@ -893,9 +894,6 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori ...@@ -893,9 +894,6 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
new->output = dst_discard; new->output = dst_discard;
dst_copy_metrics(new, &ort->dst); dst_copy_metrics(new, &ort->dst);
new->dev = ort->dst.dev;
if (new->dev)
dev_hold(new->dev);
rt->rt6i_idev = ort->rt6i_idev; rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev) if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev); in6_dev_hold(rt->rt6i_idev);
...@@ -1038,13 +1036,12 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, ...@@ -1038,13 +1036,12 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
if (unlikely(idev == NULL)) if (unlikely(idev == NULL))
return NULL; return NULL;
rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev);
if (unlikely(rt == NULL)) { if (unlikely(rt == NULL)) {
in6_dev_put(idev); in6_dev_put(idev);
goto out; goto out;
} }
dev_hold(dev);
if (neigh) if (neigh)
neigh_hold(neigh); neigh_hold(neigh);
else { else {
...@@ -1053,7 +1050,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, ...@@ -1053,7 +1050,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
neigh = NULL; neigh = NULL;
} }
rt->rt6i_dev = dev;
rt->rt6i_idev = idev; rt->rt6i_idev = idev;
rt->rt6i_nexthop = neigh; rt->rt6i_nexthop = neigh;
atomic_set(&rt->dst.__refcnt, 1); atomic_set(&rt->dst.__refcnt, 1);
...@@ -1212,7 +1208,7 @@ int ip6_route_add(struct fib6_config *cfg) ...@@ -1212,7 +1208,7 @@ int ip6_route_add(struct fib6_config *cfg)
goto out; goto out;
} }
rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL);
if (rt == NULL) { if (rt == NULL) {
err = -ENOMEM; err = -ENOMEM;
...@@ -1731,7 +1727,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad ...@@ -1731,7 +1727,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad
static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
{ {
struct net *net = dev_net(ort->rt6i_dev); struct net *net = dev_net(ort->rt6i_dev);
struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
ort->dst.dev);
if (rt) { if (rt) {
rt->dst.input = ort->dst.input; rt->dst.input = ort->dst.input;
...@@ -1739,9 +1736,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) ...@@ -1739,9 +1736,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
dst_copy_metrics(&rt->dst, &ort->dst); dst_copy_metrics(&rt->dst, &ort->dst);
rt->dst.error = ort->dst.error; rt->dst.error = ort->dst.error;
rt->dst.dev = ort->dst.dev;
if (rt->dst.dev)
dev_hold(rt->dst.dev);
rt->rt6i_idev = ort->rt6i_idev; rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev) if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev); in6_dev_hold(rt->rt6i_idev);
...@@ -2011,7 +2005,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, ...@@ -2011,7 +2005,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
int anycast) int anycast)
{ {
struct net *net = dev_net(idev->dev); struct net *net = dev_net(idev->dev);
struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
net->loopback_dev);
struct neighbour *neigh; struct neighbour *neigh;
if (rt == NULL) { if (rt == NULL) {
...@@ -2021,13 +2016,11 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, ...@@ -2021,13 +2016,11 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
dev_hold(net->loopback_dev);
in6_dev_hold(idev); in6_dev_hold(idev);
rt->dst.flags = DST_HOST; rt->dst.flags = DST_HOST;
rt->dst.input = ip6_input; rt->dst.input = ip6_input;
rt->dst.output = ip6_output; rt->dst.output = ip6_output;
rt->rt6i_dev = net->loopback_dev;
rt->rt6i_idev = idev; rt->rt6i_idev = idev;
rt->dst.obsolete = -1; rt->dst.obsolete = -1;
......
...@@ -1348,7 +1348,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) ...@@ -1348,7 +1348,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
default: default:
BUG(); BUG();
} }
xdst = dst_alloc(dst_ops, 0); xdst = dst_alloc(dst_ops, NULL, 0, 0, 0);
xfrm_policy_put_afinfo(afinfo); xfrm_policy_put_afinfo(afinfo);
if (likely(xdst)) if (likely(xdst))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment