summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /net/core
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c2
-rw-r--r--net/core/dev.c570
-rw-r--r--net/core/dev_addr_lists.c4
-rw-r--r--net/core/drop_monitor.c15
-rw-r--r--net/core/ethtool.c3
-rw-r--r--net/core/fib_rules.c3
-rw-r--r--net/core/flow_dissector.c81
-rw-r--r--net/core/iovec.c5
-rw-r--r--net/core/neighbour.c2
-rw-r--r--net/core/net-sysfs.c16
-rw-r--r--net/core/netpoll.c31
-rw-r--r--net/core/netprio_cgroup.c3
-rw-r--r--net/core/pktgen.c7
-rw-r--r--net/core/rtnetlink.c12
-rw-r--r--net/core/secure_seq.c16
-rw-r--r--net/core/skbuff.c219
-rw-r--r--net/core/sock.c45
-rw-r--r--net/core/utils.c49
18 files changed, 348 insertions, 735 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index a16ed7b..af814e7 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -577,7 +577,7 @@ EXPORT_SYMBOL(skb_copy_datagram_from_iovec);
/**
* zerocopy_sg_from_iovec - Build a zerocopy datagram from an iovec
* @skb: buffer to copy
- * @from: io vector to copy from
+ * @from: io vector to copy to
* @offset: offset in the io vector to start copying from
* @count: amount of vectors to copy to buffer from
*
diff --git a/net/core/dev.c b/net/core/dev.c
index ba3b7ea..3430b1e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -131,7 +131,6 @@
#include <linux/static_key.h>
#include <linux/hashtable.h>
#include <linux/vmalloc.h>
-#include <linux/if_macvlan.h>
#include "net-sysfs.h"
@@ -1204,7 +1203,7 @@ void netdev_state_change(struct net_device *dev)
{
if (dev->flags & IFF_UP) {
call_netdevice_notifiers(NETDEV_CHANGE, dev);
- rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
}
}
EXPORT_SYMBOL(netdev_state_change);
@@ -1294,7 +1293,7 @@ int dev_open(struct net_device *dev)
if (ret < 0)
return ret;
- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
call_netdevice_notifiers(NETDEV_UP, dev);
return ret;
@@ -1308,7 +1307,7 @@ static int __dev_close_many(struct list_head *head)
ASSERT_RTNL();
might_sleep();
- list_for_each_entry(dev, head, close_list) {
+ list_for_each_entry(dev, head, unreg_list) {
call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
clear_bit(__LINK_STATE_START, &dev->state);
@@ -1324,7 +1323,7 @@ static int __dev_close_many(struct list_head *head)
dev_deactivate_many(head);
- list_for_each_entry(dev, head, close_list) {
+ list_for_each_entry(dev, head, unreg_list) {
const struct net_device_ops *ops = dev->netdev_ops;
/*
@@ -1352,7 +1351,7 @@ static int __dev_close(struct net_device *dev)
/* Temporarily disable netpoll until the interface is down */
netpoll_rx_disable(dev);
- list_add(&dev->close_list, &single);
+ list_add(&dev->unreg_list, &single);
retval = __dev_close_many(&single);
list_del(&single);
@@ -1363,20 +1362,21 @@ static int __dev_close(struct net_device *dev)
static int dev_close_many(struct list_head *head)
{
struct net_device *dev, *tmp;
+ LIST_HEAD(tmp_list);
- /* Remove the devices that don't need to be closed */
- list_for_each_entry_safe(dev, tmp, head, close_list)
+ list_for_each_entry_safe(dev, tmp, head, unreg_list)
if (!(dev->flags & IFF_UP))
- list_del_init(&dev->close_list);
+ list_move(&dev->unreg_list, &tmp_list);
__dev_close_many(head);
- list_for_each_entry_safe(dev, tmp, head, close_list) {
- rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING, GFP_KERNEL);
+ list_for_each_entry(dev, head, unreg_list) {
+ rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
call_netdevice_notifiers(NETDEV_DOWN, dev);
- list_del_init(&dev->close_list);
}
+ /* rollback_registered_many needs the complete original list */
+ list_splice(&tmp_list, head);
return 0;
}
@@ -1397,7 +1397,7 @@ int dev_close(struct net_device *dev)
/* Block netpoll rx while the interface is going down */
netpoll_rx_disable(dev);
- list_add(&dev->close_list, &single);
+ list_add(&dev->unreg_list, &single);
dev_close_many(&single);
list_del(&single);
@@ -1425,10 +1425,6 @@ void dev_disable_lro(struct net_device *dev)
if (is_vlan_dev(dev))
dev = vlan_dev_real_dev(dev);
- /* the same for macvlan devices */
- if (netif_is_macvlan(dev))
- dev = macvlan_dev_real_dev(dev);
-
dev->wanted_features &= ~NETIF_F_LRO;
netdev_update_features(dev);
@@ -1695,9 +1691,13 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
kfree_skb(skb);
return NET_RX_DROP;
}
+ skb->protocol = eth_type_trans(skb, dev);
+ /* eth_type_trans() can set pkt_type.
+ * call skb_scrub_packet() after it to clear pkt_type _after_ calling
+ * eth_type_trans().
+ */
skb_scrub_packet(skb, true);
- skb->protocol = eth_type_trans(skb, dev);
return netif_rx(skb);
}
@@ -2378,8 +2378,6 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
}
SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb);
- SKB_GSO_CB(skb)->encap_level = 0;
-
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
@@ -2539,7 +2537,7 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
}
int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
- struct netdev_queue *txq, void *accel_priv)
+ struct netdev_queue *txq)
{
const struct net_device_ops *ops = dev->netdev_ops;
int rc = NETDEV_TX_OK;
@@ -2605,13 +2603,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
dev_queue_xmit_nit(skb, dev);
skb_len = skb->len;
- if (accel_priv)
- rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
- else
- rc = ops->ndo_start_xmit(skb, dev);
-
+ rc = ops->ndo_start_xmit(skb, dev);
trace_net_dev_xmit(skb, rc, dev, skb_len);
- if (rc == NETDEV_TX_OK && txq)
+ if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
return rc;
}
@@ -2627,10 +2621,7 @@ gso:
dev_queue_xmit_nit(nskb, dev);
skb_len = nskb->len;
- if (accel_priv)
- rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
- else
- rc = ops->ndo_start_xmit(nskb, dev);
+ rc = ops->ndo_start_xmit(nskb, dev);
trace_net_dev_xmit(nskb, rc, dev, skb_len);
if (unlikely(rc != NETDEV_TX_OK)) {
if (rc & ~NETDEV_TX_MASK)
@@ -2655,7 +2646,6 @@ out_kfree_skb:
out:
return rc;
}
-EXPORT_SYMBOL_GPL(dev_hard_start_xmit);
static void qdisc_pkt_len_init(struct sk_buff *skb)
{
@@ -2863,7 +2853,7 @@ int dev_queue_xmit(struct sk_buff *skb)
if (!netif_xmit_stopped(txq)) {
__this_cpu_inc(xmit_recursion);
- rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+ rc = dev_hard_start_xmit(skb, dev, txq);
__this_cpu_dec(xmit_recursion);
if (dev_xmit_complete(rc)) {
HARD_TX_UNLOCK(dev, txq);
@@ -4384,40 +4374,42 @@ struct netdev_adjacent {
/* upper master flag, there can only be one master device per list */
bool master;
+ /* indicates that this dev is our first-level lower/upper device */
+ bool neighbour;
+
/* counter for the number of times this device was added to us */
u16 ref_nr;
- /* private field for the users */
- void *private;
-
struct list_head list;
struct rcu_head rcu;
};
-static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev,
- struct net_device *adj_dev,
- struct list_head *adj_list)
+static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
+ struct net_device *adj_dev,
+ bool upper)
{
struct netdev_adjacent *adj;
+ struct list_head *dev_list;
- list_for_each_entry_rcu(adj, adj_list, list) {
+ dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list;
+
+ list_for_each_entry(adj, dev_list, list) {
if (adj->dev == adj_dev)
return adj;
}
return NULL;
}
-static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
- struct net_device *adj_dev,
- struct list_head *adj_list)
+static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
+ struct net_device *udev)
{
- struct netdev_adjacent *adj;
+ return __netdev_find_adj(dev, udev, true);
+}
- list_for_each_entry(adj, adj_list, list) {
- if (adj->dev == adj_dev)
- return adj;
- }
- return NULL;
+static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_find_adj(dev, ldev, false);
}
/**
@@ -4434,7 +4426,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
{
ASSERT_RTNL();
- return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper);
+ return __netdev_find_upper(dev, upper_dev);
}
EXPORT_SYMBOL(netdev_has_upper_dev);
@@ -4449,7 +4441,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev)
{
ASSERT_RTNL();
- return !list_empty(&dev->all_adj_list.upper);
+ return !list_empty(&dev->upper_dev_list);
}
EXPORT_SYMBOL(netdev_has_any_upper_dev);
@@ -4466,10 +4458,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
ASSERT_RTNL();
- if (list_empty(&dev->adj_list.upper))
+ if (list_empty(&dev->upper_dev_list))
return NULL;
- upper = list_first_entry(&dev->adj_list.upper,
+ upper = list_first_entry(&dev->upper_dev_list,
struct netdev_adjacent, list);
if (likely(upper->master))
return upper->dev;
@@ -4477,26 +4469,15 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
-void *netdev_adjacent_get_private(struct list_head *adj_list)
-{
- struct netdev_adjacent *adj;
-
- adj = list_entry(adj_list, struct netdev_adjacent, list);
-
- return adj->private;
-}
-EXPORT_SYMBOL(netdev_adjacent_get_private);
-
-/**
- * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
+/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
* @dev: device
* @iter: list_head ** of the current position
*
* Gets the next device from the dev's upper list, starting from iter
* position. The caller must hold RCU read lock.
*/
-struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
- struct list_head **iter)
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *upper;
@@ -4504,71 +4485,14 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
- if (&upper->list == &dev->all_adj_list.upper)
+ if (&upper->list == &dev->upper_dev_list)
return NULL;
*iter = &upper->list;
return upper->dev;
}
-EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
-
-/**
- * netdev_lower_get_next_private - Get the next ->private from the
- * lower neighbour list
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent->private from the dev's lower neighbour
- * list, starting from iter position. The caller must hold either hold the
- * RTNL lock or its own locking that guarantees that the neighbour lower
- * list will remain unchainged.
- */
-void *netdev_lower_get_next_private(struct net_device *dev,
- struct list_head **iter)
-{
- struct netdev_adjacent *lower;
-
- lower = list_entry(*iter, struct netdev_adjacent, list);
-
- if (&lower->list == &dev->adj_list.lower)
- return NULL;
-
- if (iter)
- *iter = lower->list.next;
-
- return lower->private;
-}
-EXPORT_SYMBOL(netdev_lower_get_next_private);
-
-/**
- * netdev_lower_get_next_private_rcu - Get the next ->private from the
- * lower neighbour list, RCU
- * variant
- * @dev: device
- * @iter: list_head ** of the current position
- *
- * Gets the next netdev_adjacent->private from the dev's lower neighbour
- * list, starting from iter position. The caller must hold RCU read lock.
- */
-void *netdev_lower_get_next_private_rcu(struct net_device *dev,
- struct list_head **iter)
-{
- struct netdev_adjacent *lower;
-
- WARN_ON_ONCE(!rcu_read_lock_held());
-
- lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
-
- if (&lower->list == &dev->adj_list.lower)
- return NULL;
-
- if (iter)
- *iter = &lower->list;
-
- return lower->private;
-}
-EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
+EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
/**
* netdev_master_upper_dev_get_rcu - Get master upper device
@@ -4581,7 +4505,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
struct netdev_adjacent *upper;
- upper = list_first_or_null_rcu(&dev->adj_list.upper,
+ upper = list_first_or_null_rcu(&dev->upper_dev_list,
struct netdev_adjacent, list);
if (upper && likely(upper->master))
return upper->dev;
@@ -4591,16 +4515,15 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
- struct list_head *dev_list,
- void *private, bool master)
+ bool neighbour, bool master,
+ bool upper)
{
struct netdev_adjacent *adj;
- char linkname[IFNAMSIZ+7];
- int ret;
- adj = __netdev_find_adj(dev, adj_dev, dev_list);
+ adj = __netdev_find_adj(dev, adj_dev, upper);
if (adj) {
+ BUG_ON(neighbour);
adj->ref_nr++;
return 0;
}
@@ -4611,179 +4534,124 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
+ adj->neighbour = neighbour;
adj->ref_nr = 1;
- adj->private = private;
- dev_hold(adj_dev);
- pr_debug("dev_hold for %s, because of link added from %s to %s\n",
- adj_dev->name, dev->name, adj_dev->name);
+ dev_hold(adj_dev);
+ pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
- if (dev_list == &dev->adj_list.lower) {
- sprintf(linkname, "lower_%s", adj_dev->name);
- ret = sysfs_create_link(&(dev->dev.kobj),
- &(adj_dev->dev.kobj), linkname);
- if (ret)
- goto free_adj;
- } else if (dev_list == &dev->adj_list.upper) {
- sprintf(linkname, "upper_%s", adj_dev->name);
- ret = sysfs_create_link(&(dev->dev.kobj),
- &(adj_dev->dev.kobj), linkname);
- if (ret)
- goto free_adj;
+ if (!upper) {
+ list_add_tail_rcu(&adj->list, &dev->lower_dev_list);
+ return 0;
}
- /* Ensure that master link is always the first item in list. */
- if (master) {
- ret = sysfs_create_link(&(dev->dev.kobj),
- &(adj_dev->dev.kobj), "master");
- if (ret)
- goto remove_symlinks;
-
- list_add_rcu(&adj->list, dev_list);
- } else {
- list_add_tail_rcu(&adj->list, dev_list);
- }
+ /* Ensure that master upper link is always the first item in list. */
+ if (master)
+ list_add_rcu(&adj->list, &dev->upper_dev_list);
+ else
+ list_add_tail_rcu(&adj->list, &dev->upper_dev_list);
return 0;
+}
-remove_symlinks:
- if (dev_list == &dev->adj_list.lower) {
- sprintf(linkname, "lower_%s", adj_dev->name);
- sysfs_remove_link(&(dev->dev.kobj), linkname);
- } else if (dev_list == &dev->adj_list.upper) {
- sprintf(linkname, "upper_%s", adj_dev->name);
- sysfs_remove_link(&(dev->dev.kobj), linkname);
- }
-
-free_adj:
- kfree(adj);
- dev_put(adj_dev);
+static inline int __netdev_upper_dev_insert(struct net_device *dev,
+ struct net_device *udev,
+ bool master, bool neighbour)
+{
+ return __netdev_adjacent_dev_insert(dev, udev, neighbour, master,
+ true);
+}
- return ret;
+static inline int __netdev_lower_dev_insert(struct net_device *dev,
+ struct net_device *ldev,
+ bool neighbour)
+{
+ return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false,
+ false);
}
void __netdev_adjacent_dev_remove(struct net_device *dev,
- struct net_device *adj_dev,
- struct list_head *dev_list)
+ struct net_device *adj_dev, bool upper)
{
struct netdev_adjacent *adj;
- char linkname[IFNAMSIZ+7];
- adj = __netdev_find_adj(dev, adj_dev, dev_list);
+ if (upper)
+ adj = __netdev_find_upper(dev, adj_dev);
+ else
+ adj = __netdev_find_lower(dev, adj_dev);
- if (!adj) {
- pr_err("tried to remove device %s from %s\n",
- dev->name, adj_dev->name);
+ if (!adj)
BUG();
- }
if (adj->ref_nr > 1) {
- pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name,
- adj->ref_nr-1);
adj->ref_nr--;
return;
}
- if (adj->master)
- sysfs_remove_link(&(dev->dev.kobj), "master");
-
- if (dev_list == &dev->adj_list.lower) {
- sprintf(linkname, "lower_%s", adj_dev->name);
- sysfs_remove_link(&(dev->dev.kobj), linkname);
- } else if (dev_list == &dev->adj_list.upper) {
- sprintf(linkname, "upper_%s", adj_dev->name);
- sysfs_remove_link(&(dev->dev.kobj), linkname);
- }
-
list_del_rcu(&adj->list);
- pr_debug("dev_put for %s, because link removed from %s to %s\n",
- adj_dev->name, dev->name, adj_dev->name);
+ pr_debug("dev_put for %s, because of %s link removed from %s to %s\n",
+ adj_dev->name, upper ? "upper" : "lower", dev->name,
+ adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
}
-int __netdev_adjacent_dev_link_lists(struct net_device *dev,
- struct net_device *upper_dev,
- struct list_head *up_list,
- struct list_head *down_list,
- void *private, bool master)
+static inline void __netdev_upper_dev_remove(struct net_device *dev,
+ struct net_device *udev)
+{
+ return __netdev_adjacent_dev_remove(dev, udev, true);
+}
+
+static inline void __netdev_lower_dev_remove(struct net_device *dev,
+ struct net_device *ldev)
+{
+ return __netdev_adjacent_dev_remove(dev, ldev, false);
+}
+
+int __netdev_adjacent_dev_insert_link(struct net_device *dev,
+ struct net_device *upper_dev,
+ bool master, bool neighbour)
{
int ret;
- ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private,
- master);
+ ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour);
if (ret)
return ret;
- ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private,
- false);
+ ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour);
if (ret) {
- __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
+ __netdev_upper_dev_remove(dev, upper_dev);
return ret;
}
return 0;
}
-int __netdev_adjacent_dev_link(struct net_device *dev,
- struct net_device *upper_dev)
+static inline int __netdev_adjacent_dev_link(struct net_device *dev,
+ struct net_device *udev)
{
- return __netdev_adjacent_dev_link_lists(dev, upper_dev,
- &dev->all_adj_list.upper,
- &upper_dev->all_adj_list.lower,
- NULL, false);
+ return __netdev_adjacent_dev_insert_link(dev, udev, false, false);
}
-void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
- struct net_device *upper_dev,
- struct list_head *up_list,
- struct list_head *down_list)
+static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
+ struct net_device *udev,
+ bool master)
{
- __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
- __netdev_adjacent_dev_remove(upper_dev, dev, down_list);
+ return __netdev_adjacent_dev_insert_link(dev, udev, master, true);
}
void __netdev_adjacent_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
- &dev->all_adj_list.upper,
- &upper_dev->all_adj_list.lower);
+ __netdev_upper_dev_remove(dev, upper_dev);
+ __netdev_lower_dev_remove(upper_dev, dev);
}
-int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
- struct net_device *upper_dev,
- void *private, bool master)
-{
- int ret = __netdev_adjacent_dev_link(dev, upper_dev);
-
- if (ret)
- return ret;
-
- ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
- &dev->adj_list.upper,
- &upper_dev->adj_list.lower,
- private, master);
- if (ret) {
- __netdev_adjacent_dev_unlink(dev, upper_dev);
- return ret;
- }
-
- return 0;
-}
-
-void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
- struct net_device *upper_dev)
-{
- __netdev_adjacent_dev_unlink(dev, upper_dev);
- __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
- &dev->adj_list.upper,
- &upper_dev->adj_list.lower);
-}
static int __netdev_upper_dev_link(struct net_device *dev,
- struct net_device *upper_dev, bool master,
- void *private)
+ struct net_device *upper_dev, bool master)
{
struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0;
@@ -4794,29 +4662,26 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
+ if (__netdev_find_upper(upper_dev, dev))
return -EBUSY;
- if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper))
+ if (__netdev_find_upper(dev, upper_dev))
return -EEXIST;
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
- master);
+ ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master);
if (ret)
return ret;
/* Now that we linked these devs, make all the upper_dev's
- * all_adj_list.upper visible to every dev's all_adj_list.lower an
+ * upper_dev_list visible to every dev's lower_dev_list and vice
* versa, and don't forget the devices itself. All of these
* links are non-neighbours.
*/
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
- pr_debug("Interlinking %s with %s, non-neighbour\n",
- i->dev->name, j->dev->name);
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
ret = __netdev_adjacent_dev_link(i->dev, j->dev);
if (ret)
goto rollback_mesh;
@@ -4824,18 +4689,14 @@ static int __netdev_upper_dev_link(struct net_device *dev,
}
/* add dev to every upper_dev's upper device */
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
- pr_debug("linking %s's upper device %s with %s\n",
- upper_dev->name, i->dev->name, dev->name);
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
ret = __netdev_adjacent_dev_link(dev, i->dev);
if (ret)
goto rollback_upper_mesh;
}
/* add upper_dev to every dev's lower device */
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- pr_debug("linking %s's lower device %s with %s\n", dev->name,
- i->dev->name, upper_dev->name);
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
if (ret)
goto rollback_lower_mesh;
@@ -4846,7 +4707,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
rollback_lower_mesh:
to_i = i;
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
@@ -4856,7 +4717,7 @@ rollback_lower_mesh:
rollback_upper_mesh:
to_i = i;
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(dev, i->dev);
@@ -4867,8 +4728,8 @@ rollback_upper_mesh:
rollback_mesh:
to_i = i;
to_j = j;
- list_for_each_entry(i, &dev->all_adj_list.lower, list) {
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
+ list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
if (i == to_i && j == to_j)
break;
__netdev_adjacent_dev_unlink(i->dev, j->dev);
@@ -4877,7 +4738,7 @@ rollback_mesh:
break;
}
- __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
return ret;
}
@@ -4895,7 +4756,7 @@ rollback_mesh:
int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, false, NULL);
+ return __netdev_upper_dev_link(dev, upper_dev, false);
}
EXPORT_SYMBOL(netdev_upper_dev_link);
@@ -4913,18 +4774,10 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, true, NULL);
+ return __netdev_upper_dev_link(dev, upper_dev, true);
}
EXPORT_SYMBOL(netdev_master_upper_dev_link);
-int netdev_master_upper_dev_link_private(struct net_device *dev,
- struct net_device *upper_dev,
- void *private)
-{
- return __netdev_upper_dev_link(dev, upper_dev, true, private);
-}
-EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
-
/**
* netdev_upper_dev_unlink - Removes a link to upper device
* @dev: device
@@ -4939,68 +4792,38 @@ void netdev_upper_dev_unlink(struct net_device *dev,
struct netdev_adjacent *i, *j;
ASSERT_RTNL();
- __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
/* Here is the tricky part. We must remove all dev's lower
* devices from all upper_dev's upper devices and vice
* versa, to maintain the graph relationship.
*/
- list_for_each_entry(i, &dev->all_adj_list.lower, list)
- list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
+ list_for_each_entry(i, &dev->lower_dev_list, list)
+ list_for_each_entry(j, &upper_dev->upper_dev_list, list)
__netdev_adjacent_dev_unlink(i->dev, j->dev);
/* remove also the devices itself from lower/upper device
* list
*/
- list_for_each_entry(i, &dev->all_adj_list.lower, list)
+ list_for_each_entry(i, &dev->lower_dev_list, list)
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
- list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
+ list_for_each_entry(i, &upper_dev->upper_dev_list, list)
__netdev_adjacent_dev_unlink(dev, i->dev);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
-void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
- struct net_device *lower_dev)
-{
- struct netdev_adjacent *lower;
-
- if (!lower_dev)
- return NULL;
- lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower);
- if (!lower)
- return NULL;
-
- return lower->private;
-}
-EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
-
-void *netdev_lower_dev_get_private(struct net_device *dev,
- struct net_device *lower_dev)
-{
- struct netdev_adjacent *lower;
-
- if (!lower_dev)
- return NULL;
- lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower);
- if (!lower)
- return NULL;
-
- return lower->private;
-}
-EXPORT_SYMBOL(netdev_lower_dev_get_private);
-
static void dev_change_rx_flags(struct net_device *dev, int flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
- if (ops->ndo_change_rx_flags)
+ if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags)
ops->ndo_change_rx_flags(dev, flags);
}
-static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)
+static int __dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned int old_flags = dev->flags;
kuid_t uid;
@@ -5043,8 +4866,6 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc, bool notify)
dev_change_rx_flags(dev, IFF_PROMISC);
}
- if (notify)
- __dev_notify_flags(dev, old_flags, IFF_PROMISC);
return 0;
}
@@ -5064,7 +4885,7 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
unsigned int old_flags = dev->flags;
int err;
- err = __dev_set_promiscuity(dev, inc, true);
+ err = __dev_set_promiscuity(dev, inc);
if (err < 0)
return err;
if (dev->flags != old_flags)
@@ -5073,9 +4894,22 @@ int dev_set_promiscuity(struct net_device *dev, int inc)
}
EXPORT_SYMBOL(dev_set_promiscuity);
-static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify)
+/**
+ * dev_set_allmulti - update allmulti count on a device
+ * @dev: device
+ * @inc: modifier
+ *
+ * Add or remove reception of all multicast frames to a device. While the
+ * count in the device remains above zero the interface remains listening
+ * to all interfaces. Once it hits zero the device reverts back to normal
+ * filtering operation. A negative @inc value is used to drop the counter
+ * when releasing a resource needing all multicasts.
+ * Return 0 if successful or a negative errno code on error.
+ */
+
+int dev_set_allmulti(struct net_device *dev, int inc)
{
- unsigned int old_flags = dev->flags, old_gflags = dev->gflags;
+ unsigned int old_flags = dev->flags;
ASSERT_RTNL();
@@ -5098,30 +4932,9 @@ static int __dev_set_allmulti(struct net_device *dev, int inc, bool notify)
if (dev->flags ^ old_flags) {
dev_change_rx_flags(dev, IFF_ALLMULTI);
dev_set_rx_mode(dev);
- if (notify)
- __dev_notify_flags(dev, old_flags,
- dev->gflags ^ old_gflags);
}
return 0;
}
-
-/**
- * dev_set_allmulti - update allmulti count on a device
- * @dev: device
- * @inc: modifier
- *
- * Add or remove reception of all multicast frames to a device. While the
- * count in the device remains above zero the interface remains listening
- * to all interfaces. Once it hits zero the device reverts back to normal
- * filtering operation. A negative @inc value is used to drop the counter
- * when releasing a resource needing all multicasts.
- * Return 0 if successful or a negative errno code on error.
- */
-
-int dev_set_allmulti(struct net_device *dev, int inc)
-{
- return __dev_set_allmulti(dev, inc, true);
-}
EXPORT_SYMBOL(dev_set_allmulti);
/*
@@ -5146,10 +4959,10 @@ void __dev_set_rx_mode(struct net_device *dev)
* therefore calling __dev_set_promiscuity here is safe.
*/
if (!netdev_uc_empty(dev) && !dev->uc_promisc) {
- __dev_set_promiscuity(dev, 1, false);
+ __dev_set_promiscuity(dev, 1);
dev->uc_promisc = true;
} else if (netdev_uc_empty(dev) && dev->uc_promisc) {
- __dev_set_promiscuity(dev, -1, false);
+ __dev_set_promiscuity(dev, -1);
dev->uc_promisc = false;
}
}
@@ -5238,13 +5051,9 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
if ((flags ^ dev->gflags) & IFF_PROMISC) {
int inc = (flags & IFF_PROMISC) ? 1 : -1;
- unsigned int old_flags = dev->flags;
dev->gflags ^= IFF_PROMISC;
-
- if (__dev_set_promiscuity(dev, inc, false) >= 0)
- if (dev->flags != old_flags)
- dev_set_rx_mode(dev);
+ dev_set_promiscuity(dev, inc);
}
/* NOTE: order of synchronization of IFF_PROMISC and IFF_ALLMULTI
@@ -5255,20 +5064,16 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags)
int inc = (flags & IFF_ALLMULTI) ? 1 : -1;
dev->gflags ^= IFF_ALLMULTI;
- __dev_set_allmulti(dev, inc, false);
+ dev_set_allmulti(dev, inc);
}
return ret;
}
-void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
- unsigned int gchanges)
+void __dev_notify_flags(struct net_device *dev, unsigned int old_flags)
{
unsigned int changes = dev->flags ^ old_flags;
- if (gchanges)
- rtmsg_ifinfo(RTM_NEWLINK, dev, gchanges, GFP_ATOMIC);
-
if (changes & IFF_UP) {
if (dev->flags & IFF_UP)
call_netdevice_notifiers(NETDEV_UP, dev);
@@ -5297,14 +5102,17 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
int dev_change_flags(struct net_device *dev, unsigned int flags)
{
int ret;
- unsigned int changes, old_flags = dev->flags, old_gflags = dev->gflags;
+ unsigned int changes, old_flags = dev->flags;
ret = __dev_change_flags(dev, flags);
if (ret < 0)
return ret;
- changes = (old_flags ^ dev->flags) | (old_gflags ^ dev->gflags);
- __dev_notify_flags(dev, old_flags, changes);
+ changes = old_flags ^ dev->flags;
+ if (changes)
+ rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
+
+ __dev_notify_flags(dev, old_flags);
return ret;
}
EXPORT_SYMBOL(dev_change_flags);
@@ -5451,7 +5259,6 @@ static void net_set_todo(struct net_device *dev)
static void rollback_registered_many(struct list_head *head)
{
struct net_device *dev, *tmp;
- LIST_HEAD(close_head);
BUG_ON(dev_boot_phase);
ASSERT_RTNL();
@@ -5474,9 +5281,7 @@ static void rollback_registered_many(struct list_head *head)
}
/* If device is running, close it first. */
- list_for_each_entry(dev, head, unreg_list)
- list_add_tail(&dev->close_list, &close_head);
- dev_close_many(&close_head);
+ dev_close_many(head);
list_for_each_entry(dev, head, unreg_list) {
/* And unlink it from device chain. */
@@ -5499,7 +5304,7 @@ static void rollback_registered_many(struct list_head *head)
if (!dev->rtnl_link_ops ||
dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
- rtmsg_ifinfo(RTM_DELLINK, dev, ~0U, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
/*
* Flush the unicast and multicast chains
@@ -5898,7 +5703,7 @@ int register_netdevice(struct net_device *dev)
*/
if (!dev->rtnl_link_ops ||
dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
- rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
out:
return ret;
@@ -6205,16 +6010,6 @@ void netdev_set_default_ethtool_ops(struct net_device *dev,
}
EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops);
-void netdev_freemem(struct net_device *dev)
-{
- char *addr = (char *)dev - dev->padded;
-
- if (is_vmalloc_addr(addr))
- vfree(addr);
- else
- kfree(addr);
-}
-
/**
* alloc_netdev_mqs - allocate network device
* @sizeof_priv: size of private data to allocate space for
@@ -6258,9 +6053,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
/* ensure 32-byte alignment of whole construct */
alloc_size += NETDEV_ALIGN - 1;
- p = kzalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
- if (!p)
- p = vzalloc(alloc_size);
+ p = kzalloc(alloc_size, GFP_KERNEL);
if (!p)
return NULL;
@@ -6269,7 +6062,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
dev->pcpu_refcnt = alloc_percpu(int);
if (!dev->pcpu_refcnt)
- goto free_dev;
+ goto free_p;
if (dev_addr_init(dev))
goto free_pcpu;
@@ -6284,12 +6077,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
- INIT_LIST_HEAD(&dev->close_list);
INIT_LIST_HEAD(&dev->link_watch_list);
- INIT_LIST_HEAD(&dev->adj_list.upper);
- INIT_LIST_HEAD(&dev->adj_list.lower);
- INIT_LIST_HEAD(&dev->all_adj_list.upper);
- INIT_LIST_HEAD(&dev->all_adj_list.lower);
+ INIT_LIST_HEAD(&dev->upper_dev_list);
+ INIT_LIST_HEAD(&dev->lower_dev_list);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
@@ -6322,8 +6112,8 @@ free_pcpu:
kfree(dev->_rx);
#endif
-free_dev:
- netdev_freemem(dev);
+free_p:
+ kfree(p);
return NULL;
}
EXPORT_SYMBOL(alloc_netdev_mqs);
@@ -6360,7 +6150,7 @@ void free_netdev(struct net_device *dev)
/* Compatibility with error handling in drivers */
if (dev->reg_state == NETREG_UNINITIALIZED) {
- netdev_freemem(dev);
+ kfree((char *)dev - dev->padded);
return;
}
@@ -6522,7 +6312,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
rcu_barrier();
call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev);
- rtmsg_ifinfo(RTM_DELLINK, dev, ~0U, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
/*
* Flush the unicast and multicast chains
@@ -6561,7 +6351,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
* Prevent userspace races by waiting until the network
* device is fully setup before sending notifications.
*/
- rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
synchronize_net();
err = 0;
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index ec40a84..6cda4e2 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -752,7 +752,7 @@ int dev_mc_del_global(struct net_device *dev, const unsigned char *addr)
EXPORT_SYMBOL(dev_mc_del_global);
/**
- * dev_mc_sync - Synchronize device's multicast list to another device
+ * dev_mc_sync - Synchronize device's unicast list to another device
* @to: destination device
* @from: source device
*
@@ -780,7 +780,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from)
EXPORT_SYMBOL(dev_mc_sync);
/**
- * dev_mc_sync_multiple - Synchronize device's multicast list to another
+ * dev_mc_sync_multiple - Synchronize device's unicast list to another
* device, but allow for multiple calls to sync to multiple devices.
* @to: destination device
* @from: source device
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 9589718..5e78d44 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -106,10 +106,6 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
return skb;
}
-static struct genl_multicast_group dropmon_mcgrps[] = {
- { .name = "events", },
-};
-
static void send_dm_alert(struct work_struct *work)
{
struct sk_buff *skb;
@@ -120,8 +116,7 @@ static void send_dm_alert(struct work_struct *work)
skb = reset_per_cpu_data(data);
if (skb)
- genlmsg_multicast(&net_drop_monitor_family, skb, 0,
- 0, GFP_KERNEL);
+ genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
}
/*
@@ -338,7 +333,7 @@ out:
return NOTIFY_DONE;
}
-static const struct genl_ops dropmon_ops[] = {
+static struct genl_ops dropmon_ops[] = {
{
.cmd = NET_DM_CMD_CONFIG,
.doit = net_dm_cmd_config,
@@ -369,13 +364,13 @@ static int __init init_net_drop_monitor(void)
return -ENOSPC;
}
- rc = genl_register_family_with_ops_groups(&net_drop_monitor_family,
- dropmon_ops, dropmon_mcgrps);
+ rc = genl_register_family_with_ops(&net_drop_monitor_family,
+ dropmon_ops,
+ ARRAY_SIZE(dropmon_ops));
if (rc) {
pr_err("Could not create drop monitor netlink family\n");
return rc;
}
- WARN_ON(net_drop_monitor_family.mcgrp_offset != NET_DM_GRP_ALERT);
rc = register_netdevice_notifier(&dropmon_net_notifier);
if (rc < 0) {
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 30071de..78e9d92 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -81,8 +81,6 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation",
[NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
[NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
- [NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation",
- [NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation",
[NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
[NETIF_F_GSO_MPLS_BIT] = "tx-mpls-segmentation",
@@ -96,7 +94,6 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_LOOPBACK_BIT] = "loopback",
[NETIF_F_RXFCS_BIT] = "rx-fcs",
[NETIF_F_RXALL_BIT] = "rx-all",
- [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload",
};
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index f409e0b..2e65413 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -460,8 +460,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
if (frh->action && (frh->action != rule->action))
continue;
- if (frh_get_table(frh, tb) &&
- (frh_get_table(frh, tb) != rule->table))
+ if (frh->table && (frh_get_table(frh, tb) != rule->table))
continue;
if (tb[FRA_PRIORITY] &&
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index d6ef173..8d7d0dd 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -25,35 +25,9 @@ static void iph_to_flow_copy_addrs(struct flow_keys *flow, const struct iphdr *i
memcpy(&flow->src, &iph->saddr, sizeof(flow->src) + sizeof(flow->dst));
}
-/**
- * skb_flow_get_ports - extract the upper layer ports and return them
- * @skb: buffer to extract the ports from
- * @thoff: transport header offset
- * @ip_proto: protocol for which to get port offset
- *
- * The function will try to retrieve the ports at offset thoff + poff where poff
- * is the protocol port offset returned from proto_ports_offset
- */
-__be32 skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto)
-{
- int poff = proto_ports_offset(ip_proto);
-
- if (poff >= 0) {
- __be32 *ports, _ports;
-
- ports = skb_header_pointer(skb, thoff + poff,
- sizeof(_ports), &_ports);
- if (ports)
- return *ports;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(skb_flow_get_ports);
-
bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow)
{
- int nhoff = skb_network_offset(skb);
+ int poff, nhoff = skb_network_offset(skb);
u8 ip_proto;
__be16 proto = skb->protocol;
@@ -66,15 +40,15 @@ again:
struct iphdr _iph;
ip:
iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
- if (!iph || iph->ihl < 5)
+ if (!iph)
return false;
- nhoff += iph->ihl * 4;
- ip_proto = iph->protocol;
if (ip_is_fragment(iph))
ip_proto = 0;
-
+ else
+ ip_proto = iph->protocol;
iph_to_flow_copy_addrs(flow, iph);
+ nhoff += iph->ihl * 4;
break;
}
case __constant_htons(ETH_P_IPV6): {
@@ -176,7 +150,16 @@ ipv6:
}
flow->ip_proto = ip_proto;
- flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto);
+ poff = proto_ports_offset(ip_proto);
+ if (poff >= 0) {
+ __be32 *ports, _ports;
+
+ ports = skb_header_pointer(skb, nhoff + poff,
+ sizeof(_ports), &_ports);
+ if (ports)
+ flow->ports = *ports;
+ }
+
flow->thoff = (u16) nhoff;
return true;
@@ -184,22 +167,6 @@ ipv6:
EXPORT_SYMBOL(skb_flow_dissect);
static u32 hashrnd __read_mostly;
-static __always_inline void __flow_hash_secret_init(void)
-{
- net_get_random_once(&hashrnd, sizeof(hashrnd));
-}
-
-static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c)
-{
- __flow_hash_secret_init();
- return jhash_3words(a, b, c, hashrnd);
-}
-
-static __always_inline u32 __flow_hash_1word(u32 a)
-{
- __flow_hash_secret_init();
- return jhash_1word(a, hashrnd);
-}
/*
* __skb_get_rxhash: calculate a flow hash based on src/dst addresses
@@ -226,9 +193,9 @@ void __skb_get_rxhash(struct sk_buff *skb)
swap(keys.port16[0], keys.port16[1]);
}
- hash = __flow_hash_3words((__force u32)keys.dst,
- (__force u32)keys.src,
- (__force u32)keys.ports);
+ hash = jhash_3words((__force u32)keys.dst,
+ (__force u32)keys.src,
+ (__force u32)keys.ports, hashrnd);
if (!hash)
hash = 1;
@@ -264,7 +231,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
hash = skb->sk->sk_hash;
else
hash = (__force u16) skb->protocol;
- hash = __flow_hash_1word(hash);
+ hash = jhash_1word(hash, hashrnd);
return (u16) (((u64) hash * qcount) >> 32) + qoffset;
}
@@ -356,7 +323,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
else
hash = (__force u16) skb->protocol ^
skb->rxhash;
- hash = __flow_hash_1word(hash);
+ hash = jhash_1word(hash, hashrnd);
queue_index = map->queues[
((u64)hash * map->len) >> 32];
}
@@ -411,3 +378,11 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,
skb_set_queue_mapping(skb, queue_index);
return netdev_get_tx_queue(dev, queue_index);
}
+
+static int __init initialize_hashrnd(void)
+{
+ get_random_bytes(&hashrnd, sizeof(hashrnd));
+ return 0;
+}
+
+late_initcall_sync(initialize_hashrnd);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index b618694..b77eeec 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -48,8 +48,7 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
if (err < 0)
return err;
}
- if (m->msg_name)
- m->msg_name = address;
+ m->msg_name = address;
} else {
m->msg_name = NULL;
}
@@ -101,7 +100,7 @@ int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
EXPORT_SYMBOL(memcpy_toiovecend);
/*
- * Copy iovec to kernel. Returns -EFAULT on error.
+ * Copy iovec from kernel. Returns -EFAULT on error.
*/
int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index ca15f32..6072610 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -867,7 +867,7 @@ static void neigh_invalidate(struct neighbour *neigh)
static void neigh_probe(struct neighbour *neigh)
__releases(neigh->lock)
{
- struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
+ struct sk_buff *skb = skb_peek(&neigh->arp_queue);
/* keep skb alive even if arp_queue overflows */
if (skb)
skb = skb_copy(skb, GFP_ATOMIC);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index f3edf96..d954b56 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1263,7 +1263,7 @@ static void netdev_release(struct device *d)
BUG_ON(dev->reg_state != NETREG_RELEASED);
kfree(dev->ifalias);
- netdev_freemem(dev);
+ kfree((char *)dev - dev->padded);
}
static const void *net_namespace(struct device *d)
@@ -1344,19 +1344,17 @@ int netdev_register_kobject(struct net_device *net)
return error;
}
-int netdev_class_create_file_ns(struct class_attribute *class_attr,
- const void *ns)
+int netdev_class_create_file(struct class_attribute *class_attr)
{
- return class_create_file_ns(&net_class, class_attr, ns);
+ return class_create_file(&net_class, class_attr);
}
-EXPORT_SYMBOL(netdev_class_create_file_ns);
+EXPORT_SYMBOL(netdev_class_create_file);
-void netdev_class_remove_file_ns(struct class_attribute *class_attr,
- const void *ns)
+void netdev_class_remove_file(struct class_attribute *class_attr)
{
- class_remove_file_ns(&net_class, class_attr, ns);
+ class_remove_file(&net_class, class_attr);
}
-EXPORT_SYMBOL(netdev_class_remove_file_ns);
+EXPORT_SYMBOL(netdev_class_remove_file);
int netdev_kobject_init(void)
{
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 8f97199..fc75c9e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -636,9 +636,8 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
netpoll_send_skb(np, send_skb);
- /* If there are several rx_skb_hooks for the same
- * address we're fine by sending a single reply
- */
+ /* If there are several rx_hooks for the same address,
+ we're fine by sending a single reply */
break;
}
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
@@ -720,9 +719,8 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
netpoll_send_skb(np, send_skb);
- /* If there are several rx_skb_hooks for the same
- * address, we're fine by sending a single reply
- */
+ /* If there are several rx_hooks for the same address,
+ we're fine by sending a single reply */
break;
}
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
@@ -758,12 +756,11 @@ static bool pkt_is_ns(struct sk_buff *skb)
int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
{
- int proto, len, ulen, data_len;
- int hits = 0, offset;
+ int proto, len, ulen;
+ int hits = 0;
const struct iphdr *iph;
struct udphdr *uh;
struct netpoll *np, *tmp;
- uint16_t source;
if (list_empty(&npinfo->rx_np))
goto out;
@@ -823,10 +820,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
len -= iph->ihl*4;
uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
- offset = (unsigned char *)(uh + 1) - skb->data;
ulen = ntohs(uh->len);
- data_len = skb->len - offset;
- source = ntohs(uh->source);
if (ulen != len)
goto out;
@@ -840,7 +834,9 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
if (np->local_port && np->local_port != ntohs(uh->dest))
continue;
- np->rx_skb_hook(np, source, skb, offset, data_len);
+ np->rx_hook(np, ntohs(uh->source),
+ (char *)(uh+1),
+ ulen - sizeof(struct udphdr));
hits++;
}
} else {
@@ -863,10 +859,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
if (!pskb_may_pull(skb, sizeof(struct udphdr)))
goto out;
uh = udp_hdr(skb);
- offset = (unsigned char *)(uh + 1) - skb->data;
ulen = ntohs(uh->len);
- data_len = skb->len - offset;
- source = ntohs(uh->source);
if (ulen != skb->len)
goto out;
if (udp6_csum_init(skb, uh, IPPROTO_UDP))
@@ -879,7 +872,9 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
if (np->local_port && np->local_port != ntohs(uh->dest))
continue;
- np->rx_skb_hook(np, source, skb, offset, data_len);
+ np->rx_hook(np, ntohs(uh->source),
+ (char *)(uh+1),
+ ulen - sizeof(struct udphdr));
hits++;
}
#endif
@@ -1067,7 +1062,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
npinfo->netpoll = np;
- if (np->rx_skb_hook) {
+ if (np->rx_hook) {
spin_lock_irqsave(&npinfo->rx_lock, flags);
npinfo->rx_flags |= NETPOLL_RX_ENABLED;
list_add_tail(&np->rx, &npinfo->rx_np);
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c
index 9b7cf6c..d9cd627 100644
--- a/net/core/netprio_cgroup.c
+++ b/net/core/netprio_cgroup.c
@@ -222,10 +222,11 @@ static void net_prio_attach(struct cgroup_subsys_state *css,
struct cgroup_taskset *tset)
{
struct task_struct *p;
- void *v = (void *)(unsigned long)css->cgroup->id;
+ void *v;
cgroup_taskset_for_each(p, css, tset) {
task_lock(p);
+ v = (void *)(unsigned long)task_netprioidx(p);
iterate_fd(p->files, 0, update_netprio, v);
task_unlock(p);
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index a797fff..261357a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2527,8 +2527,6 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
if (x) {
int ret;
__u8 *eth;
- struct iphdr *iph;
-
nhead = x->props.header_len - skb_headroom(skb);
if (nhead > 0) {
ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
@@ -2550,11 +2548,6 @@ static int process_ipsec(struct pktgen_dev *pkt_dev,
eth = (__u8 *) skb_push(skb, ETH_HLEN);
memcpy(eth, pkt_dev->hh, 12);
*(u16 *) &eth[12] = protocol;
-
- /* Update IPv4 header len as well as checksum value */
- iph = ip_hdr(skb);
- iph->tot_len = htons(skb->len - ETH_HLEN);
- ip_send_check(iph);
}
}
return 1;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index cf67144..2a0e21d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1647,8 +1647,9 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
}
dev->rtnl_link_state = RTNL_LINK_INITIALIZED;
+ rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
- __dev_notify_flags(dev, old_flags, ~0U);
+ __dev_notify_flags(dev, old_flags);
return 0;
}
EXPORT_SYMBOL(rtnl_configure_link);
@@ -1984,15 +1985,14 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
-void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
- gfp_t flags)
+void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change)
{
struct net *net = dev_net(dev);
struct sk_buff *skb;
int err = -ENOBUFS;
size_t if_info_size;
- skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), flags);
+ skb = nlmsg_new((if_info_size = if_nlmsg_size(dev, 0)), GFP_KERNEL);
if (skb == NULL)
goto errout;
@@ -2003,7 +2003,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
kfree_skb(skb);
goto errout;
}
- rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags);
+ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
return;
errout:
if (err < 0)
@@ -2717,7 +2717,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
case NETDEV_JOIN:
break;
default:
- rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
+ rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
break;
}
return NOTIFY_DONE;
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 897da56..8d9d05e 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -7,7 +7,6 @@
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/string.h>
-#include <linux/net.h>
#include <net/secure_seq.h>
@@ -16,9 +15,20 @@
static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
-static __always_inline void net_secret_init(void)
+static void net_secret_init(void)
{
- net_get_random_once(net_secret, sizeof(net_secret));
+ u32 tmp;
+ int i;
+
+ if (likely(net_secret[0]))
+ return;
+
+ for (i = NET_SECRET_SIZE; i > 0;) {
+ do {
+ get_random_bytes(&tmp, sizeof(tmp));
+ } while (!tmp);
+ cmpxchg(&net_secret[--i], 0, tmp);
+ }
}
#endif
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 2718fed..d81cff1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -476,18 +476,6 @@ void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
}
EXPORT_SYMBOL(skb_add_rx_frag);
-void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size,
- unsigned int truesize)
-{
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- skb_frag_size_add(frag, size);
- skb->len += size;
- skb->data_len += size;
- skb->truesize += truesize;
-}
-EXPORT_SYMBOL(skb_coalesce_rx_frag);
-
static void skb_drop_list(struct sk_buff **listp)
{
kfree_skb_list(*listp);
@@ -592,6 +580,9 @@ static void skb_release_head_state(struct sk_buff *skb)
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
nf_conntrack_put(skb->nfct);
#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
+ nf_conntrack_put_reasm(skb->nfct_reasm);
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(skb->nf_bridge);
#endif
@@ -912,9 +903,6 @@ EXPORT_SYMBOL(skb_clone);
static void skb_headers_offset_update(struct sk_buff *skb, int off)
{
- /* Only adjust this if it actually is csum_start rather than csum */
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- skb->csum_start += off;
/* {transport,network,mac}_header and tail are relative to skb->head */
skb->transport_header += off;
skb->network_header += off;
@@ -1048,8 +1036,8 @@ EXPORT_SYMBOL(__pskb_copy);
* @ntail: room to add at tail
* @gfp_mask: allocation priority
*
- * Expands (or creates identical copy, if @nhead and @ntail are zero)
- * header of @skb. &sk_buff itself is not changed. &sk_buff MUST have
+ * Expands (or creates identical copy, if &nhead and &ntail are zero)
+ * header of skb. &sk_buff itself is not changed. &sk_buff MUST have
* reference count of 1. Returns zero in the case of success or error,
* if expansion failed. In the last case, &sk_buff is not changed.
*
@@ -1121,6 +1109,9 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
#endif
skb->tail += off;
skb_headers_offset_update(skb, nhead);
+ /* Only adjust this if it actually is csum_start rather than csum */
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ skb->csum_start += nhead;
skb->cloned = 0;
skb->hdr_len = 0;
skb->nohdr = 0;
@@ -1185,6 +1176,7 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
NUMA_NO_NODE);
int oldheadroom = skb_headroom(skb);
int head_copy_len, head_copy_off;
+ int off;
if (!n)
return NULL;
@@ -1208,7 +1200,11 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
copy_skb_header(n, skb);
- skb_headers_offset_update(n, newheadroom - oldheadroom);
+ off = newheadroom - oldheadroom;
+ if (n->ip_summed == CHECKSUM_PARTIAL)
+ n->csum_start += off;
+
+ skb_headers_offset_update(n, off);
return n;
}
@@ -1261,29 +1257,6 @@ free_skb:
EXPORT_SYMBOL(skb_pad);
/**
- * pskb_put - add data to the tail of a potentially fragmented buffer
- * @skb: start of the buffer to use
- * @tail: tail fragment of the buffer to use
- * @len: amount of data to add
- *
- * This function extends the used data area of the potentially
- * fragmented buffer. @tail must be the last fragment of @skb -- or
- * @skb itself. 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 *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
-{
- if (tail != skb) {
- skb->data_len += len;
- skb->len += len;
- }
- return skb_put(tail, len);
-}
-EXPORT_SYMBOL_GPL(pskb_put);
-
-/**
* skb_put - add data to a buffer
* @skb: buffer to use
* @len: amount of data to add
@@ -1960,8 +1933,9 @@ fault:
EXPORT_SYMBOL(skb_store_bits);
/* Checksum skb data. */
-__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
- __wsum csum, const struct skb_checksum_ops *ops)
+
+__wsum skb_checksum(const struct sk_buff *skb, int offset,
+ int len, __wsum csum)
{
int start = skb_headlen(skb);
int i, copy = start - offset;
@@ -1972,7 +1946,7 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
if (copy > 0) {
if (copy > len)
copy = len;
- csum = ops->update(skb->data + offset, copy, csum);
+ csum = csum_partial(skb->data + offset, copy, csum);
if ((len -= copy) == 0)
return csum;
offset += copy;
@@ -1993,10 +1967,10 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
if (copy > len)
copy = len;
vaddr = kmap_atomic(skb_frag_page(frag));
- csum2 = ops->update(vaddr + frag->page_offset +
- offset - start, copy, 0);
+ csum2 = csum_partial(vaddr + frag->page_offset +
+ offset - start, copy, 0);
kunmap_atomic(vaddr);
- csum = ops->combine(csum, csum2, pos, copy);
+ csum = csum_block_add(csum, csum2, pos);
if (!(len -= copy))
return csum;
offset += copy;
@@ -2015,9 +1989,9 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
__wsum csum2;
if (copy > len)
copy = len;
- csum2 = __skb_checksum(frag_iter, offset - start,
- copy, 0, ops);
- csum = ops->combine(csum, csum2, pos, copy);
+ csum2 = skb_checksum(frag_iter, offset - start,
+ copy, 0);
+ csum = csum_block_add(csum, csum2, pos);
if ((len -= copy) == 0)
return csum;
offset += copy;
@@ -2029,18 +2003,6 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
return csum;
}
-EXPORT_SYMBOL(__skb_checksum);
-
-__wsum skb_checksum(const struct sk_buff *skb, int offset,
- int len, __wsum csum)
-{
- const struct skb_checksum_ops ops = {
- .update = csum_partial_ext,
- .combine = csum_block_add_ext,
- };
-
- return __skb_checksum(skb, offset, len, csum, &ops);
-}
EXPORT_SYMBOL(skb_checksum);
/* Both of above in one bottle. */
@@ -2560,14 +2522,14 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
* @data: destination pointer for data to be returned
* @st: state variable
*
- * Reads a block of skb data at @consumed relative to the
+ * Reads a block of skb data at &consumed relative to the
* lower offset specified to skb_prepare_seq_read(). Assigns
- * the head of the data block to @data and returns the length
+ * the head of the data block to &data and returns the length
* of the block or 0 if the end of the skb data or the upper
* offset has been reached.
*
* The caller is not required to consume all of the data
- * returned, i.e. @consumed is typically set to the number
+ * returned, i.e. &consumed is typically set to the number
* of bytes already consumed and the next call to
* skb_seq_read() will return the remaining part of the block.
*
@@ -2796,7 +2758,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
- skb_frag_t *skb_frag = skb_shinfo(skb)->frags;
unsigned int mss = skb_shinfo(skb)->gso_size;
unsigned int doffset = skb->data - skb_mac_header(skb);
unsigned int offset = doffset;
@@ -2836,38 +2797,16 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
if (hsize > len || !sg)
hsize = len;
- if (!hsize && i >= nfrags && skb_headlen(fskb) &&
- (skb_headlen(fskb) == len || sg)) {
- BUG_ON(skb_headlen(fskb) > len);
-
- i = 0;
- nfrags = skb_shinfo(fskb)->nr_frags;
- skb_frag = skb_shinfo(fskb)->frags;
- pos += skb_headlen(fskb);
-
- while (pos < offset + len) {
- BUG_ON(i >= nfrags);
-
- size = skb_frag_size(skb_frag);
- if (pos + size > offset + len)
- break;
-
- i++;
- pos += size;
- skb_frag++;
- }
+ if (!hsize && i >= nfrags) {
+ BUG_ON(fskb->len != len);
+ pos += len;
nskb = skb_clone(fskb, GFP_ATOMIC);
fskb = fskb->next;
if (unlikely(!nskb))
goto err;
- if (unlikely(pskb_trim(nskb, len))) {
- kfree_skb(nskb);
- goto err;
- }
-
hsize = skb_end_offset(nskb);
if (skb_cow_head(nskb, doffset + headroom)) {
kfree_skb(nskb);
@@ -2898,13 +2837,20 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
__copy_skb_header(nskb, skb);
nskb->mac_len = skb->mac_len;
- skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
+ /* nskb and skb might have different headroom */
+ if (nskb->ip_summed == CHECKSUM_PARTIAL)
+ nskb->csum_start += skb_headroom(nskb) - headroom;
+
+ skb_reset_mac_header(nskb);
+ skb_set_network_header(nskb, skb->mac_len);
+ nskb->transport_header = (nskb->network_header +
+ skb_network_header_len(skb));
skb_copy_from_linear_data_offset(skb, -tnl_hlen,
nskb->data - tnl_hlen,
doffset + tnl_hlen);
- if (nskb->len == len + doffset)
+ if (fskb != skb_shinfo(skb)->frag_list)
goto perform_csum_check;
if (!sg) {
@@ -2922,28 +2868,8 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
- while (pos < offset + len) {
- if (i >= nfrags) {
- BUG_ON(skb_headlen(fskb));
-
- i = 0;
- nfrags = skb_shinfo(fskb)->nr_frags;
- skb_frag = skb_shinfo(fskb)->frags;
-
- BUG_ON(!nfrags);
-
- fskb = fskb->next;
- }
-
- if (unlikely(skb_shinfo(nskb)->nr_frags >=
- MAX_SKB_FRAGS)) {
- net_warn_ratelimited(
- "skb_segment: too many frags: %u %u\n",
- pos, mss);
- goto err;
- }
-
- *frag = *skb_frag;
+ while (pos < offset + len && i < nfrags) {
+ *frag = skb_shinfo(skb)->frags[i];
__skb_frag_ref(frag);
size = skb_frag_size(frag);
@@ -2956,7 +2882,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
if (pos + size <= offset + len) {
i++;
- skb_frag++;
pos += size;
} else {
skb_frag_size_sub(frag, pos + size - (offset + len));
@@ -2966,6 +2891,25 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
frag++;
}
+ if (pos < offset + len) {
+ struct sk_buff *fskb2 = fskb;
+
+ BUG_ON(pos + fskb->len != offset + len);
+
+ pos += fskb->len;
+ fskb = fskb->next;
+
+ if (fskb2->next) {
+ fskb2 = skb_clone(fskb2, GFP_ATOMIC);
+ if (!fskb2)
+ goto err;
+ } else
+ skb_get(fskb2);
+
+ SKB_FRAG_ASSERT(nskb);
+ skb_shinfo(nskb)->frag_list = fskb2;
+ }
+
skip_fraglist:
nskb->data_len = len - hsize;
nskb->len += nskb->data_len;
@@ -2992,30 +2936,32 @@ EXPORT_SYMBOL_GPL(skb_segment);
int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
{
- struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
+ struct sk_buff *p = *head;
+ struct sk_buff *nskb;
+ struct skb_shared_info *skbinfo = skb_shinfo(skb);
+ struct skb_shared_info *pinfo = skb_shinfo(p);
+ unsigned int headroom;
+ unsigned int len = skb_gro_len(skb);
unsigned int offset = skb_gro_offset(skb);
unsigned int headlen = skb_headlen(skb);
- struct sk_buff *nskb, *lp, *p = *head;
- unsigned int len = skb_gro_len(skb);
unsigned int delta_truesize;
- unsigned int headroom;
- if (unlikely(p->len + len >= 65536))
+ if (p->len + len >= 65536)
return -E2BIG;
- lp = NAPI_GRO_CB(p)->last ?: p;
- pinfo = skb_shinfo(lp);
-
- if (headlen <= offset) {
+ if (pinfo->frag_list)
+ goto merge;
+ else if (headlen <= offset) {
skb_frag_t *frag;
skb_frag_t *frag2;
int i = skbinfo->nr_frags;
int nr_frags = pinfo->nr_frags + i;
+ offset -= headlen;
+
if (nr_frags > MAX_SKB_FRAGS)
- goto merge;
+ return -E2BIG;
- offset -= headlen;
pinfo->nr_frags = nr_frags;
skbinfo->nr_frags = 0;
@@ -3046,7 +2992,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
unsigned int first_offset;
if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS)
- goto merge;
+ return -E2BIG;
first_offset = skb->data -
(unsigned char *)page_address(page) +
@@ -3064,10 +3010,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
delta_truesize = skb->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
goto done;
- }
- if (pinfo->frag_list)
- goto merge;
- if (skb_gro_len(p) != pinfo->gso_size)
+ } else if (skb_gro_len(p) != pinfo->gso_size)
return -E2BIG;
headroom = skb_headroom(p);
@@ -3119,24 +3062,16 @@ merge:
__skb_pull(skb, offset);
- if (!NAPI_GRO_CB(p)->last)
- skb_shinfo(p)->frag_list = skb;
- else
- NAPI_GRO_CB(p)->last->next = skb;
+ NAPI_GRO_CB(p)->last->next = skb;
NAPI_GRO_CB(p)->last = skb;
skb_header_release(skb);
- lp = p;
done:
NAPI_GRO_CB(p)->count++;
p->data_len += len;
p->truesize += delta_truesize;
p->len += len;
- if (lp != p) {
- lp->data_len += len;
- lp->truesize += delta_truesize;
- lp->len += len;
- }
+
NAPI_GRO_CB(skb)->same_flow = 1;
return 0;
}
diff --git a/net/core/sock.c b/net/core/sock.c
index ab20ed9..0b39e7a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -475,6 +475,12 @@ discard_and_relse:
}
EXPORT_SYMBOL(sk_receive_skb);
+void sk_reset_txq(struct sock *sk)
+{
+ sk_tx_queue_clear(sk);
+}
+EXPORT_SYMBOL(sk_reset_txq);
+
struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
{
struct dst_entry *dst = __sk_dst_get(sk);
@@ -908,13 +914,6 @@ set_rcvbuf:
}
break;
#endif
-
- case SO_MAX_PACING_RATE:
- sk->sk_max_pacing_rate = val;
- sk->sk_pacing_rate = min(sk->sk_pacing_rate,
- sk->sk_max_pacing_rate);
- break;
-
default:
ret = -ENOPROTOOPT;
break;
@@ -1178,10 +1177,6 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break;
#endif
- case SO_MAX_PACING_RATE:
- v.val = sk->sk_max_pacing_rate;
- break;
-
default:
return -ENOPROTOOPT;
}
@@ -1841,17 +1836,7 @@ EXPORT_SYMBOL(sock_alloc_send_skb);
/* On 32bit arches, an skb frag is limited to 2^15 */
#define SKB_FRAG_PAGE_ORDER get_order(32768)
-/**
- * skb_page_frag_refill - check that a page_frag contains enough room
- * @sz: minimum size of the fragment we want to get
- * @pfrag: pointer to page_frag
- * @prio: priority for memory allocation
- *
- * Note: While this allocator tries to use high order pages, there is
- * no guarantee that allocations succeed. Therefore, @sz MUST be
- * less or equal than PAGE_SIZE.
- */
-bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
+bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)
{
int order;
@@ -1860,16 +1845,16 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
pfrag->offset = 0;
return true;
}
- if (pfrag->offset + sz <= pfrag->size)
+ if (pfrag->offset < pfrag->size)
return true;
put_page(pfrag->page);
}
/* We restrict high order allocations to users that can afford to wait */
- order = (prio & __GFP_WAIT) ? SKB_FRAG_PAGE_ORDER : 0;
+ order = (sk->sk_allocation & __GFP_WAIT) ? SKB_FRAG_PAGE_ORDER : 0;
do {
- gfp_t gfp = prio;
+ gfp_t gfp = sk->sk_allocation;
if (order)
gfp |= __GFP_COMP | __GFP_NOWARN;
@@ -1881,15 +1866,6 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
}
} while (--order >= 0);
- return false;
-}
-EXPORT_SYMBOL(skb_page_frag_refill);
-
-bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag)
-{
- if (likely(skb_page_frag_refill(32U, pfrag, sk->sk_allocation)))
- return true;
-
sk_enter_memory_pressure(sk);
sk_stream_moderate_sndbuf(sk);
return false;
@@ -2343,7 +2319,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_ll_usec = sysctl_net_busy_read;
#endif
- sk->sk_max_pacing_rate = ~0U;
sk->sk_pacing_rate = ~0U;
/*
* Before updating sk_refcnt, we must commit prior changes to memory
diff --git a/net/core/utils.c b/net/core/utils.c
index 2f737bf..aa88e23 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -338,52 +338,3 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
csum_unfold(*sum)));
}
EXPORT_SYMBOL(inet_proto_csum_replace16);
-
-struct __net_random_once_work {
- struct work_struct work;
- struct static_key *key;
-};
-
-static void __net_random_once_deferred(struct work_struct *w)
-{
- struct __net_random_once_work *work =
- container_of(w, struct __net_random_once_work, work);
- if (!static_key_enabled(work->key))
- static_key_slow_inc(work->key);
- kfree(work);
-}
-
-static void __net_random_once_disable_jump(struct static_key *key)
-{
- struct __net_random_once_work *w;
-
- w = kmalloc(sizeof(*w), GFP_ATOMIC);
- if (!w)
- return;
-
- INIT_WORK(&w->work, __net_random_once_deferred);
- w->key = key;
- schedule_work(&w->work);
-}
-
-bool __net_get_random_once(void *buf, int nbytes, bool *done,
- struct static_key *done_key)
-{
- static DEFINE_SPINLOCK(lock);
- unsigned long flags;
-
- spin_lock_irqsave(&lock, flags);
- if (*done) {
- spin_unlock_irqrestore(&lock, flags);
- return false;
- }
-
- get_random_bytes(buf, nbytes);
- *done = true;
- spin_unlock_irqrestore(&lock, flags);
-
- __net_random_once_disable_jump(done_key);
-
- return true;
-}
-EXPORT_SYMBOL(__net_get_random_once);