}
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 struct dst_entry *dst_destroy(struct dst_entry * dst);
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;
dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC);
if (!dst)
return NULL;
- atomic_set(&dst->__refcnt, initial_ref);
dst->ops = ops;
- dst->lastuse = jiffies;
- dst->path = dst;
- dst->input = dst->output = dst_discard;
+ dst->dev = dev;
+ if (dev)
+ dev_hold(dev);
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
atomic_inc(&dst_total);
#endif
if (dev_out->flags & IFF_LOOPBACK)
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)
goto e_nobufs;
- atomic_set(&rt->dst.__refcnt, 1);
- rt->dst.flags = DST_HOST;
-
rt->fld.saddr = oldflp->saddr;
rt->fld.daddr = oldflp->daddr;
rt->fld.flowidn_oif = oldflp->flowidn_oif;
rt->rt_dst_map = fld.daddr;
rt->rt_src_map = fld.saddr;
- rt->dst.dev = dev_out;
- dev_hold(dev_out);
rt->dst.neighbour = neigh;
neigh = NULL;
}
make_route:
- rt = dst_alloc(&dn_dst_ops, 0);
+ rt = dst_alloc(&dn_dst_ops, out_dev, 0, 0, DST_HOST);
if (rt == NULL)
goto e_nobufs;
rt->fld.flowidn_iif = in_dev->ifindex;
rt->fld.flowidn_mark = fld.flowidn_mark;
- rt->dst.flags = DST_HOST;
rt->dst.neighbour = neigh;
- rt->dst.dev = out_dev;
rt->dst.lastuse = jiffies;
rt->dst.output = dn_rt_bug;
switch(res.type) {
rt->dst.input = dst_discard;
}
rt->rt_flags = flags;
- if (rt->dst.dev)
- dev_hold(rt->dst.dev);
err = dn_rt_set_next_hop(rt, &res);
if (err)
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);
- if (rt) {
- rt->dst.obsolete = -1;
-
- rt->dst.flags = DST_HOST |
- (nopolicy ? DST_NOPOLICY : 0) |
- (noxfrm ? DST_NOXFRM : 0);
- }
- return rt;
+ return dst_alloc(&ipv4_dst_ops, dev, 1, -1,
+ DST_HOST |
+ (nopolicy ? DST_NOPOLICY : 0) |
+ (noxfrm ? DST_NOXFRM : 0));
}
/* called in rcu_read_lock() section */
if (err < 0)
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)
goto e_nobufs;
#endif
rth->rt_route_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_gateway = daddr;
rth->rt_spec_dst= spec_dst;
}
}
- 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));
if (!rth) {
err = -ENOBUFS;
rth->rt_gateway = daddr;
rth->rt_route_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_spec_dst= spec_dst;
RT_CACHE_STAT_INC(in_brd);
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)
goto e_nobufs;
#endif
rth->rt_route_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_spec_dst= spec_dst;
rth->dst.input= ip_local_deliver;
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));
if (!rth)
return ERR_PTR(-ENOBUFS);
rth->rt_src = fl4->saddr;
rth->rt_route_iif = 0;
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_spec_dst= fl4->saddr;
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;
if (rt) {
#endif
/* 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)
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 *ort = (struct rt6_info *) dst_orig;
+ struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
struct dst_entry *new = NULL;
+ rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0);
if (rt) {
new = &rt->dst;
new->output = dst_discard;
dst_copy_metrics(new, &ort->dst);
- new->dev = ort->dst.dev;
- if (new->dev)
- dev_hold(new->dev);
rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
if (unlikely(idev == 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)) {
in6_dev_put(idev);
goto out;
}
- dev_hold(dev);
if (neigh)
neigh_hold(neigh);
else {
neigh = NULL;
}
- rt->rt6i_dev = dev;
rt->rt6i_idev = idev;
rt->rt6i_nexthop = neigh;
atomic_set(&rt->dst.__refcnt, 1);
goto out;
}
- rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
+ rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL);
if (rt == NULL) {
err = -ENOMEM;
static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
{
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) {
rt->dst.input = ort->dst.input;
dst_copy_metrics(&rt->dst, &ort->dst);
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;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
int anycast)
{
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;
if (rt == NULL) {
return ERR_PTR(-ENOMEM);
}
- dev_hold(net->loopback_dev);
in6_dev_hold(idev);
rt->dst.flags = DST_HOST;
rt->dst.input = ip6_input;
rt->dst.output = ip6_output;
- rt->rt6i_dev = net->loopback_dev;
rt->rt6i_idev = idev;
rt->dst.obsolete = -1;
default:
BUG();
}
- xdst = dst_alloc(dst_ops, 0);
+ xdst = dst_alloc(dst_ops, NULL, 0, 0, 0);
xfrm_policy_put_afinfo(afinfo);
if (likely(xdst))