aboutsummaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c28
-rw-r--r--net/core/dev_mcast.c37
-rw-r--r--net/core/dst.c15
-rw-r--r--net/core/fib_rules.c8
-rw-r--r--net/core/neighbour.c61
-rw-r--r--net/core/netpoll.c6
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/core/rtnetlink.c16
-rw-r--r--net/core/skbuff.c90
-rw-r--r--net/core/sock.c35
10 files changed, 198 insertions, 100 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 460e7f99ce3..7aa01125287 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -216,7 +216,7 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
/* Device list insertion */
static int list_netdevice(struct net_device *dev)
{
- struct net *net = dev->nd_net;
+ struct net *net = dev_net(dev);
ASSERT_RTNL();
@@ -852,8 +852,8 @@ int dev_alloc_name(struct net_device *dev, const char *name)
struct net *net;
int ret;
- BUG_ON(!dev->nd_net);
- net = dev->nd_net;
+ BUG_ON(!dev_net(dev));
+ net = dev_net(dev);
ret = __dev_alloc_name(net, name, buf);
if (ret >= 0)
strlcpy(dev->name, buf, IFNAMSIZ);
@@ -877,9 +877,9 @@ int dev_change_name(struct net_device *dev, char *newname)
struct net *net;
ASSERT_RTNL();
- BUG_ON(!dev->nd_net);
+ BUG_ON(!dev_net(dev));
- net = dev->nd_net;
+ net = dev_net(dev);
if (dev->flags & IFF_UP)
return -EBUSY;
@@ -2615,7 +2615,7 @@ static int ptype_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
seq_puts(seq, "Type Device Function\n");
- else {
+ else if (pt->dev == NULL || dev_net(pt->dev) == seq_file_net(seq)) {
if (pt->type == htons(ETH_P_ALL))
seq_puts(seq, "ALL ");
else
@@ -2639,7 +2639,8 @@ static const struct seq_operations ptype_seq_ops = {
static int ptype_seq_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &ptype_seq_ops);
+ return seq_open_net(inode, file, &ptype_seq_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations ptype_seq_fops = {
@@ -2647,7 +2648,7 @@ static const struct file_operations ptype_seq_fops = {
.open = ptype_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = seq_release_net,
};
@@ -3688,8 +3689,8 @@ int register_netdevice(struct net_device *dev)
/* When net_device's are persistent, this will be fatal. */
BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
- BUG_ON(!dev->nd_net);
- net = dev->nd_net;
+ BUG_ON(!dev_net(dev));
+ net = dev_net(dev);
spin_lock_init(&dev->queue_lock);
spin_lock_init(&dev->_xmit_lock);
@@ -4010,7 +4011,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
dev = (struct net_device *)
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
dev->padded = (char *)dev - (char *)p;
- dev->nd_net = &init_net;
+ dev_net_set(dev, &init_net);
if (sizeof_priv) {
dev->priv = ((char *)dev +
@@ -4021,6 +4022,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
}
dev->egress_subqueue_count = queue_count;
+ dev->gso_max_size = GSO_MAX_SIZE;
dev->get_stats = internal_stats;
netpoll_netdev_init(dev);
@@ -4134,7 +4136,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
/* Get out if there is nothing todo */
err = 0;
- if (dev->nd_net == net)
+ if (net_eq(dev_net(dev), net))
goto out;
/* Pick the destination device name, and ensure
@@ -4185,7 +4187,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev_addr_discard(dev);
/* Actually switch the network namespace */
- dev->nd_net = net;
+ dev_net_set(dev, net);
/* Assign the new device name */
if (destname != dev->name)
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index cec582563e0..f8a3455f449 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -156,39 +156,14 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
EXPORT_SYMBOL(dev_mc_unsync);
#ifdef CONFIG_PROC_FS
-static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
- __acquires(dev_base_lock)
-{
- struct net *net = seq_file_net(seq);
- struct net_device *dev;
- loff_t off = 0;
-
- read_lock(&dev_base_lock);
- for_each_netdev(net, dev) {
- if (off++ == *pos)
- return dev;
- }
- return NULL;
-}
-
-static void *dev_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
- ++*pos;
- return next_net_device((struct net_device *)v);
-}
-
-static void dev_mc_seq_stop(struct seq_file *seq, void *v)
- __releases(dev_base_lock)
-{
- read_unlock(&dev_base_lock);
-}
-
-
static int dev_mc_seq_show(struct seq_file *seq, void *v)
{
struct dev_addr_list *m;
struct net_device *dev = v;
+ if (v == SEQ_START_TOKEN)
+ return 0;
+
netif_tx_lock_bh(dev);
for (m = dev->mc_list; m; m = m->next) {
int i;
@@ -206,9 +181,9 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v)
}
static const struct seq_operations dev_mc_seq_ops = {
- .start = dev_mc_seq_start,
- .next = dev_mc_seq_next,
- .stop = dev_mc_seq_stop,
+ .start = dev_seq_start,
+ .next = dev_seq_next,
+ .stop = dev_seq_stop,
.show = dev_mc_seq_show,
};
diff --git a/net/core/dst.c b/net/core/dst.c
index 7deef483c79..fe03266130b 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -259,6 +259,16 @@ again:
return NULL;
}
+void dst_release(struct dst_entry *dst)
+{
+ if (dst) {
+ WARN_ON(atomic_read(&dst->__refcnt) < 1);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&dst->__refcnt);
+ }
+}
+EXPORT_SYMBOL(dst_release);
+
/* Dirty hack. We did it in 2.2 (in __dst_free),
* we have _very_ good reasons not to repeat
* this mistake in 2.3, but we have no choice
@@ -279,7 +289,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
if (!unregister) {
dst->input = dst->output = dst_discard;
} else {
- dst->dev = dst->dev->nd_net->loopback_dev;
+ dst->dev = dev_net(dst->dev)->loopback_dev;
dev_hold(dst->dev);
dev_put(dev);
if (dst->neighbour && dst->neighbour->dev == dev) {
@@ -295,9 +305,6 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
struct net_device *dev = ptr;
struct dst_entry *dst, *last = NULL;
- if (dev->nd_net != &init_net)
- return NOTIFY_DONE;
-
switch (event) {
case NETDEV_UNREGISTER:
case NETDEV_DOWN:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 42ccaf5b850..540c07283e3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -214,7 +214,7 @@ errout:
static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct fib_rule_hdr *frh = nlmsg_data(nlh);
struct fib_rules_ops *ops = NULL;
struct fib_rule *rule, *r, *last = NULL;
@@ -352,7 +352,7 @@ errout:
static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct fib_rule_hdr *frh = nlmsg_data(nlh);
struct fib_rules_ops *ops = NULL;
struct fib_rule *rule, *tmp;
@@ -534,7 +534,7 @@ skip:
static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct fib_rules_ops *ops;
int idx = 0, family;
@@ -618,7 +618,7 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
struct net_device *dev = ptr;
- struct net *net = dev->nd_net;
+ struct net *net = dev_net(dev);
struct fib_rules_ops *ops;
ASSERT_RTNL();
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 19b8e003f15..d8d0ca99c65 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -388,7 +388,7 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
hash_val = tbl->hash(pkey, NULL);
for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
if (!memcmp(n->primary_key, pkey, key_len) &&
- (net == n->dev->nd_net)) {
+ net_eq(dev_net(n->dev), net)) {
neigh_hold(n);
NEIGH_CACHE_STAT_INC(tbl, hits);
break;
@@ -480,7 +480,7 @@ struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
if (!memcmp(n->key, pkey, key_len) &&
- (n->net == net) &&
+ (pneigh_net(n) == net) &&
(n->dev == dev || !n->dev))
break;
}
@@ -505,7 +505,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
if (!memcmp(n->key, pkey, key_len) &&
- (n->net == net) &&
+ net_eq(pneigh_net(n), net) &&
(n->dev == dev || !n->dev)) {
read_unlock_bh(&tbl->lock);
goto out;
@@ -522,7 +522,9 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
if (!n)
goto out;
+#ifdef CONFIG_NET_NS
n->net = hold_net(net);
+#endif
memcpy(n->key, pkey, key_len);
n->dev = dev;
if (dev)
@@ -562,14 +564,14 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
np = &n->next) {
if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
- (n->net == net)) {
+ net_eq(pneigh_net(n), net)) {
*np = n->next;
write_unlock_bh(&tbl->lock);
if (tbl->pdestructor)
tbl->pdestructor(n);
if (n->dev)
dev_put(n->dev);
- release_net(n->net);
+ release_net(pneigh_net(n));
kfree(n);
return 0;
}
@@ -592,7 +594,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
tbl->pdestructor(n);
if (n->dev)
dev_put(n->dev);
- release_net(n->net);
+ release_net(pneigh_net(n));
kfree(n);
continue;
}
@@ -1306,9 +1308,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
struct neigh_parms *p;
for (p = &tbl->parms; p; p = p->next) {
- if (p->net != net)
- continue;
- if ((p->dev && p->dev->ifindex == ifindex) ||
+ if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
(!p->dev && !ifindex))
return p;
}
@@ -1322,7 +1322,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
struct neigh_parms *p, *ref;
struct net *net;
- net = dev->nd_net;
+ net = dev_net(dev);
ref = lookup_neigh_params(tbl, net, 0);
if (!ref)
return NULL;
@@ -1342,7 +1342,9 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
dev_hold(dev);
p->dev = dev;
+#ifdef CONFIG_NET_NS
p->net = hold_net(net);
+#endif
p->sysctl_table = NULL;
write_lock_bh(&tbl->lock);
p->next = tbl->parms.next;
@@ -1384,7 +1386,7 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
static void neigh_parms_destroy(struct neigh_parms *parms)
{
- release_net(parms->net);
+ release_net(neigh_parms_net(parms));
kfree(parms);
}
@@ -1395,7 +1397,9 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
unsigned long now = jiffies;
unsigned long phsize;
+#ifdef CONFIG_NET_NS
tbl->parms.net = &init_net;
+#endif
atomic_set(&tbl->parms.refcnt, 1);
INIT_RCU_HEAD(&tbl->parms.rcu_head);
tbl->parms.reachable_time =
@@ -1502,7 +1506,7 @@ int neigh_table_clear(struct neigh_table *tbl)
static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct ndmsg *ndm;
struct nlattr *dst_attr;
struct neigh_table *tbl;
@@ -1568,7 +1572,7 @@ out:
static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct ndmsg *ndm;
struct nlattr *tb[NDA_MAX+1];
struct neigh_table *tbl;
@@ -1836,7 +1840,7 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct neigh_table *tbl;
struct ndtmsg *ndtmsg;
struct nlattr *tb[NDTA_MAX+1];
@@ -1961,7 +1965,7 @@ errout:
static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
int family, tidx, nidx = 0;
int tbl_skip = cb->args[0];
int neigh_skip = cb->args[1];
@@ -1982,7 +1986,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
break;
for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
- if (net != p->net)
+ if (!net_eq(neigh_parms_net(p), net))
continue;
if (nidx++ < neigh_skip)
@@ -2061,7 +2065,7 @@ static void neigh_update_notify(struct neighbour *neigh)
static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
struct netlink_callback *cb)
{
- struct net * net = skb->sk->sk_net;
+ struct net * net = sock_net(skb->sk);
struct neighbour *n;
int rc, h, s_h = cb->args[1];
int idx, s_idx = idx = cb->args[2];
@@ -2074,7 +2078,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
s_idx = 0;
for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) {
int lidx;
- if (n->dev->nd_net != net)
+ if (dev_net(n->dev) != net)
continue;
lidx = idx++;
if (lidx < s_idx)
@@ -2169,7 +2173,7 @@ EXPORT_SYMBOL(__neigh_for_each_release);
static struct neighbour *neigh_get_first(struct seq_file *seq)
{
struct neigh_seq_state *state = seq->private;
- struct net *net = state->p.net;
+ struct net *net = seq_file_net(seq);
struct neigh_table *tbl = state->tbl;
struct neighbour *n = NULL;
int bucket = state->bucket;
@@ -2179,7 +2183,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
n = tbl->hash_buckets[bucket];
while (n) {
- if (n->dev->nd_net != net)
+ if (!net_eq(dev_net(n->dev), net))
goto next;
if (state->neigh_sub_iter) {
loff_t fakep = 0;
@@ -2210,7 +2214,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
loff_t *pos)
{
struct neigh_seq_state *state = seq->private;
- struct net *net = state->p.net;
+ struct net *net = seq_file_net(seq);
struct neigh_table *tbl = state->tbl;
if (state->neigh_sub_iter) {
@@ -2222,7 +2226,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
while (1) {
while (n) {
- if (n->dev->nd_net != net)
+ if (!net_eq(dev_net(n->dev), net))
goto next;
if (state->neigh_sub_iter) {
void *v = state->neigh_sub_iter(state, n, pos);
@@ -2270,7 +2274,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
{
struct neigh_seq_state *state = seq->private;
- struct net * net = state->p.net;
+ struct net *net = seq_file_net(seq);
struct neigh_table *tbl = state->tbl;
struct pneigh_entry *pn = NULL;
int bucket = state->bucket;
@@ -2278,7 +2282,7 @@ static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
state->flags |= NEIGH_SEQ_IS_PNEIGH;
for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
pn = tbl->phash_buckets[bucket];
- while (pn && (pn->net != net))
+ while (pn && !net_eq(pneigh_net(pn), net))
pn = pn->next;
if (pn)
break;
@@ -2293,7 +2297,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
loff_t *pos)
{
struct neigh_seq_state *state = seq->private;
- struct net * net = state->p.net;
+ struct net *net = seq_file_net(seq);
struct neigh_table *tbl = state->tbl;
pn = pn->next;
@@ -2301,7 +2305,7 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
if (++state->bucket > PNEIGH_HASHMASK)
break;
pn = tbl->phash_buckets[state->bucket];
- while (pn && (pn->net != net))
+ while (pn && !net_eq(pneigh_net(pn), net))
pn = pn->next;
if (pn)
break;
@@ -2506,7 +2510,7 @@ static inline size_t neigh_nlmsg_size(void)
static void __neigh_notify(struct neighbour *n, int type, int flags)
{
- struct net *net = n->dev->nd_net;
+ struct net *net = dev_net(n->dev);
struct sk_buff *skb;
int err = -ENOBUFS;
@@ -2763,7 +2767,8 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
neigh_path[NEIGH_CTL_PATH_PROTO].ctl_name = p_id;
- t->sysctl_header = register_sysctl_paths(neigh_path, t->neigh_vars);
+ t->sysctl_header =
+ register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars);
if (!t->sysctl_header)
goto free_procname;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index c635de52526..b04d643fc3c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -390,9 +390,7 @@ static void arp_reply(struct sk_buff *skb)
if (skb->dev->flags & IFF_NOARP)
return;
- if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
- (2 * skb->dev->addr_len) +
- (2 * sizeof(u32)))))
+ if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
return;
skb_reset_network_header(skb);
@@ -420,7 +418,7 @@ static void arp_reply(struct sk_buff *skb)
ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
return;
- size = sizeof(struct arphdr) + 2 * (skb->dev->addr_len + 4);
+ size = arp_hdr_len(skb->dev);
send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev),
LL_RESERVED_SPACE(np->dev));
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 20e63b302ba..a803b442234 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1874,7 +1874,7 @@ static int pktgen_device_event(struct notifier_block *unused,
{
struct net_device *dev = ptr;
- if (dev->nd_net != &init_net)
+ if (dev_net(dev) != &init_net)
return NOTIFY_DONE;
/* It is OK that we do not hold the group lock right now,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2bd9c5f7627..da99ac0871b 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -662,7 +662,7 @@ nla_put_failure:
static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
int idx;
int s_idx = cb->args[0];
struct net_device *dev;
@@ -879,7 +879,7 @@ errout:
static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct ifinfomsg *ifm;
struct net_device *dev;
int err;
@@ -921,7 +921,7 @@ errout:
static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
const struct rtnl_link_ops *ops;
struct net_device *dev;
struct ifinfomsg *ifm;
@@ -972,7 +972,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname,
goto err_free;
}
- dev->nd_net = net;
+ dev_net_set(dev, net);
dev->rtnl_link_ops = ops;
if (tb[IFLA_MTU])
@@ -1000,7 +1000,7 @@ err:
static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
const struct rtnl_link_ops *ops;
struct net_device *dev;
struct ifinfomsg *ifm;
@@ -1132,7 +1132,7 @@ replay:
static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
struct ifinfomsg *ifm;
struct nlattr *tb[IFLA_MAX+1];
struct net_device *dev = NULL;
@@ -1198,7 +1198,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
{
- struct net *net = dev->nd_net;
+ struct net *net = dev_net(dev);
struct sk_buff *skb;
int err = -ENOBUFS;
@@ -1227,7 +1227,7 @@ static int rtattr_max;
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
- struct net *net = skb->sk->sk_net;
+ struct net *net = sock_net(skb->sk);
rtnl_doit_func doit;
int sz_idx, kind;
int min_len;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 0d0fd28a904..86e5682728b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -263,6 +263,24 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
return skb;
}
+/**
+ * dev_alloc_skb - allocate an skbuff for receiving
+ * @length: length to allocate
+ *
+ * Allocate a new &sk_buff and assign it a usage count of one. The
+ * buffer has unspecified headroom built in. Users should allocate
+ * the headroom they think they need without accounting for the
+ * built in space. The built in space is used for optimisations.
+ *
+ * %NULL is returned if there is no free memory. Although this function
+ * allocates memory it can be called from an interrupt.
+ */
+struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ return __dev_alloc_skb(length, GFP_ATOMIC);
+}
+EXPORT_SYMBOL(dev_alloc_skb);
+
static void skb_drop_list(struct sk_buff **listp)
{
struct sk_buff *list = *listp;
@@ -857,6 +875,78 @@ free_skb:
return err;
}
+/**
+ * skb_put - add data to a buffer
+ * @skb: buffer to use
+ * @len: amount of data to add
+ *
+ * This function extends the used data area of the buffer. If this would
+ * exceed the total buffer size the kernel will panic. A pointer to the
+ * first byte of the extra data is returned.
+ */
+unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+{
+ unsigned char *tmp = skb_tail_pointer(skb);
+ SKB_LINEAR_ASSERT(skb);
+ skb->tail += len;
+ skb->len += len;
+ if (unlikely(skb->tail > skb->end))
+ skb_over_panic(skb, len, __builtin_return_address(0));
+ return tmp;
+}
+EXPORT_SYMBOL(skb_put);
+
+/**
+ * skb_push - add data to the start of a buffer
+ * @skb: buffer to use
+ * @len: amount of data to add
+ *
+ * This function extends the used data area of the buffer at the buffer
+ * start. If this would exceed the total buffer headroom the kernel will
+ * panic. A pointer to the first byte of the extra data is returned.
+ */
+unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+{
+ skb->data -= len;
+ skb->len += len;
+ if (unlikely(skb->data<skb->head))
+ skb_under_panic(skb, len, __builtin_return_address(0));
+ return skb->data;
+}
+EXPORT_SYMBOL(skb_push);
+
+/**
+ * skb_pull - remove data from the start of a buffer
+ * @skb: buffer to use
+ * @len: amount of data to remove
+ *
+ * This function removes data from the start of a buffer, returning
+ * the memory to the headroom. A pointer to the next data in the buffer
+ * is returned. Once the data has been pulled future pushes will overwrite
+ * the old data.
+ */
+unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
+}
+EXPORT_SYMBOL(skb_pull);
+
+/**
+ * skb_trim - remove end from a buffer
+ * @skb: buffer to alter
+ * @len: new length
+ *
+ * Cut the length of a buffer down by removing data from the tail. If
+ * the buffer is already under the length specified it is not modified.
+ * The skb must be linear.
+ */
+void skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (skb->len > len)
+ __skb_trim(skb, len);
+}
+EXPORT_SYMBOL(skb_trim);
+
/* Trims skb to length len. It can change skb pointers.
*/
diff --git a/net/core/sock.c b/net/core/sock.c
index 09cb3a74de7..3ee95060dbd 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -372,7 +372,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
{
int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES
- struct net *net = sk->sk_net;
+ struct net *net = sock_net(sk);
char devname[IFNAMSIZ];
int index;
@@ -958,7 +958,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
*/
sk->sk_prot = sk->sk_prot_creator = prot;
sock_lock_init(sk);
- sk->sk_net = get_net(net);
+ sock_net_set(sk, get_net(net));
}
return sk;
@@ -981,12 +981,31 @@ void sk_free(struct sock *sk)
if (atomic_read(&sk->sk_omem_alloc))
printk(KERN_DEBUG "%s: optmem leakage (%d bytes) detected.\n",
- __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
+ __func__, atomic_read(&sk->sk_omem_alloc));
- put_net(sk->sk_net);
+ put_net(sock_net(sk));
sk_prot_free(sk->sk_prot_creator, sk);
}
+/*
+ * Last sock_put should drop referrence to sk->sk_net. It has already
+ * been dropped in sk_change_net. Taking referrence to stopping namespace
+ * is not an option.
+ * Take referrence to a socket to remove it from hash _alive_ and after that
+ * destroy it in the context of init_net.
+ */
+void sk_release_kernel(struct sock *sk)
+{
+ if (sk == NULL || sk->sk_socket == NULL)
+ return;
+
+ sock_hold(sk);
+ sock_release(sk->sk_socket);
+ sock_net_set(sk, get_net(&init_net));
+ sock_put(sk);
+}
+EXPORT_SYMBOL(sk_release_kernel);
+
struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
{
struct sock *newsk;
@@ -998,7 +1017,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
sock_copy(newsk, sk);
/* SANITY */
- get_net(newsk->sk_net);
+ get_net(sock_net(newsk));
sk_node_init(&newsk->sk_node);
sock_lock_init(newsk);
bh_lock_sock(newsk);
@@ -1076,10 +1095,12 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
if (sk->sk_route_caps & NETIF_F_GSO)
sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
if (sk_can_gso(sk)) {
- if (dst->header_len)
+ if (dst->header_len) {
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
- else
+ } else {
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ sk->sk_gso_max_size = dst->dev->gso_max_size;
+ }
}
}
EXPORT_SYMBOL_GPL(sk_setup_caps);