summaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c72
-rw-r--r--net/core/neighbour.c13
-rw-r--r--net/core/netpoll.c1
-rw-r--r--net/core/pktgen.c54
-rw-r--r--net/core/skbuff.c3
5 files changed, 95 insertions, 48 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 8d13a9b9f1d..600bb23c4c2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1796,7 +1796,7 @@ gso:
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
#endif
if (q->enqueue) {
- spinlock_t *root_lock = qdisc_root_lock(q);
+ spinlock_t *root_lock = qdisc_lock(q);
spin_lock(root_lock);
@@ -1805,7 +1805,6 @@ gso:
spin_unlock(root_lock);
- rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
goto out;
}
@@ -1909,7 +1908,6 @@ int netif_rx(struct sk_buff *skb)
if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
if (queue->input_pkt_queue.qlen) {
enqueue:
- dev_hold(skb->dev);
__skb_queue_tail(&queue->input_pkt_queue, skb);
local_irq_restore(flags);
return NET_RX_SUCCESS;
@@ -1941,22 +1939,6 @@ int netif_rx_ni(struct sk_buff *skb)
EXPORT_SYMBOL(netif_rx_ni);
-static inline struct net_device *skb_bond(struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
-
- if (dev->master) {
- if (skb_bond_should_drop(skb)) {
- kfree_skb(skb);
- return NULL;
- }
- skb->dev = dev->master;
- }
-
- return dev;
-}
-
-
static void net_tx_action(struct softirq_action *h)
{
struct softnet_data *sd = &__get_cpu_var(softnet_data);
@@ -1995,7 +1977,7 @@ static void net_tx_action(struct softirq_action *h)
smp_mb__before_clear_bit();
clear_bit(__QDISC_STATE_SCHED, &q->state);
- root_lock = qdisc_root_lock(q);
+ root_lock = qdisc_lock(q);
if (spin_trylock(root_lock)) {
qdisc_run(q);
spin_unlock(root_lock);
@@ -2100,7 +2082,7 @@ static int ing_filter(struct sk_buff *skb)
rxq = &dev->rx_queue;
q = rxq->qdisc;
- if (q) {
+ if (q != &noop_qdisc) {
spin_lock(qdisc_lock(q));
result = qdisc_enqueue_root(skb, q);
spin_unlock(qdisc_lock(q));
@@ -2113,7 +2095,7 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb,
struct packet_type **pt_prev,
int *ret, struct net_device *orig_dev)
{
- if (!skb->dev->rx_queue.qdisc)
+ if (skb->dev->rx_queue.qdisc == &noop_qdisc)
goto out;
if (*pt_prev) {
@@ -2183,6 +2165,7 @@ int netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
struct net_device *orig_dev;
+ struct net_device *null_or_orig;
int ret = NET_RX_DROP;
__be16 type;
@@ -2196,10 +2179,14 @@ int netif_receive_skb(struct sk_buff *skb)
if (!skb->iif)
skb->iif = skb->dev->ifindex;
- orig_dev = skb_bond(skb);
-
- if (!orig_dev)
- return NET_RX_DROP;
+ null_or_orig = NULL;
+ orig_dev = skb->dev;
+ if (orig_dev->master) {
+ if (skb_bond_should_drop(skb))
+ null_or_orig = orig_dev; /* deliver only exact match */
+ else
+ skb->dev = orig_dev->master;
+ }
__get_cpu_var(netdev_rx_stat).total++;
@@ -2223,7 +2210,8 @@ int netif_receive_skb(struct sk_buff *skb)
#endif
list_for_each_entry_rcu(ptype, &ptype_all, list) {
- if (!ptype->dev || ptype->dev == skb->dev) {
+ if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
+ ptype->dev == orig_dev) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
@@ -2248,7 +2236,8 @@ ncls:
list_for_each_entry_rcu(ptype,
&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
if (ptype->type == type &&
- (!ptype->dev || ptype->dev == skb->dev)) {
+ (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
+ ptype->dev == orig_dev)) {
if (pt_prev)
ret = deliver_skb(skb, pt_prev, orig_dev);
pt_prev = ptype;
@@ -2270,6 +2259,20 @@ out:
return ret;
}
+/* Network device is going away, flush any packets still pending */
+static void flush_backlog(void *arg)
+{
+ struct net_device *dev = arg;
+ struct softnet_data *queue = &__get_cpu_var(softnet_data);
+ struct sk_buff *skb, *tmp;
+
+ skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp)
+ if (skb->dev == dev) {
+ __skb_unlink(skb, &queue->input_pkt_queue);
+ kfree_skb(skb);
+ }
+}
+
static int process_backlog(struct napi_struct *napi, int quota)
{
int work = 0;
@@ -2279,7 +2282,6 @@ static int process_backlog(struct napi_struct *napi, int quota)
napi->weight = weight_p;
do {
struct sk_buff *skb;
- struct net_device *dev;
local_irq_disable();
skb = __skb_dequeue(&queue->input_pkt_queue);
@@ -2288,14 +2290,9 @@ static int process_backlog(struct napi_struct *napi, int quota)
local_irq_enable();
break;
}
-
local_irq_enable();
- dev = skb->dev;
-
netif_receive_skb(skb);
-
- dev_put(dev);
} while (++work < quota && jiffies == start_time);
return work;
@@ -3988,6 +3985,10 @@ int register_netdevice(struct net_device *dev)
}
}
+ /* Enable software GSO if SG is supported. */
+ if (dev->features & NETIF_F_SG)
+ dev->features |= NETIF_F_GSO;
+
netdev_initialize_kobject(dev);
ret = netdev_register_kobject(dev);
if (ret)
@@ -4165,6 +4166,8 @@ void netdev_run_todo(void)
dev->reg_state = NETREG_UNREGISTERED;
+ on_each_cpu(flush_backlog, dev, 1);
+
netdev_wait_allrefs(dev);
/* paranoia */
@@ -4200,6 +4203,7 @@ static void netdev_init_queues(struct net_device *dev)
{
netdev_init_one_queue(dev, &dev->rx_queue, NULL);
netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
+ spin_lock_init(&dev->tx_global_lock);
}
/**
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f62c8af85d3..9d92e41826e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2281,6 +2281,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
struct neighbour *n = neigh_get_first(seq);
if (n) {
+ --(*pos);
while (*pos) {
n = neigh_get_next(seq, n, pos);
if (!n)
@@ -2341,6 +2342,7 @@ static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
struct pneigh_entry *pn = pneigh_get_first(seq);
if (pn) {
+ --(*pos);
while (*pos) {
pn = pneigh_get_next(seq, pn, pos);
if (!pn)
@@ -2354,10 +2356,11 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
{
struct neigh_seq_state *state = seq->private;
void *rc;
+ loff_t idxpos = *pos;
- rc = neigh_get_idx(seq, pos);
+ rc = neigh_get_idx(seq, &idxpos);
if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
- rc = pneigh_get_idx(seq, pos);
+ rc = pneigh_get_idx(seq, &idxpos);
return rc;
}
@@ -2366,7 +2369,6 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
__acquires(tbl->lock)
{
struct neigh_seq_state *state = seq->private;
- loff_t pos_minus_one;
state->tbl = tbl;
state->bucket = 0;
@@ -2374,8 +2376,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
read_lock_bh(&tbl->lock);
- pos_minus_one = *pos - 1;
- return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;
+ return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
}
EXPORT_SYMBOL(neigh_seq_start);
@@ -2385,7 +2386,7 @@ void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
void *rc;
if (v == SEQ_START_TOKEN) {
- rc = neigh_get_idx(seq, pos);
+ rc = neigh_get_first(seq);
goto out;
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index c12720895ec..6c7af390be0 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -70,6 +70,7 @@ static void queue_process(struct work_struct *work)
local_irq_save(flags);
__netif_tx_lock(txq, smp_processor_id());
if (netif_tx_queue_stopped(txq) ||
+ netif_tx_queue_frozen(txq) ||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
skb_queue_head(&npinfo->txq, skb);
__netif_tx_unlock(txq);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index c7d484f7e1c..52623645390 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -168,7 +168,7 @@
#include <asm/div64.h> /* do_div */
#include <asm/timex.h>
-#define VERSION "pktgen v2.69: Packet Generator for packet performance testing.\n"
+#define VERSION "pktgen v2.70: Packet Generator for packet performance testing.\n"
#define IP_NAME_SZ 32
#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
@@ -189,6 +189,7 @@
#define F_FLOW_SEQ (1<<11) /* Sequential flows */
#define F_IPSEC_ON (1<<12) /* ipsec on for flows */
#define F_QUEUE_MAP_RND (1<<13) /* queue map Random */
+#define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */
/* Thread control flag bits */
#define T_TERMINATE (1<<0)
@@ -621,6 +622,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
if (pkt_dev->flags & F_QUEUE_MAP_RND)
seq_printf(seq, "QUEUE_MAP_RND ");
+ if (pkt_dev->flags & F_QUEUE_MAP_CPU)
+ seq_printf(seq, "QUEUE_MAP_CPU ");
+
if (pkt_dev->cflows) {
if (pkt_dev->flags & F_FLOW_SEQ)
seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/
@@ -1134,6 +1138,12 @@ static ssize_t pktgen_if_write(struct file *file,
else if (strcmp(f, "!QUEUE_MAP_RND") == 0)
pkt_dev->flags &= ~F_QUEUE_MAP_RND;
+
+ else if (strcmp(f, "QUEUE_MAP_CPU") == 0)
+ pkt_dev->flags |= F_QUEUE_MAP_CPU;
+
+ else if (strcmp(f, "!QUEUE_MAP_CPU") == 0)
+ pkt_dev->flags &= ~F_QUEUE_MAP_CPU;
#ifdef CONFIG_XFRM
else if (strcmp(f, "IPSEC") == 0)
pkt_dev->flags |= F_IPSEC_ON;
@@ -1895,6 +1905,23 @@ static int pktgen_device_event(struct notifier_block *unused,
return NOTIFY_DONE;
}
+static struct net_device *pktgen_dev_get_by_name(struct pktgen_dev *pkt_dev, const char *ifname)
+{
+ char b[IFNAMSIZ+5];
+ int i = 0;
+
+ for(i=0; ifname[i] != '@'; i++) {
+ if(i == IFNAMSIZ)
+ break;
+
+ b[i] = ifname[i];
+ }
+ b[i] = 0;
+
+ return dev_get_by_name(&init_net, b);
+}
+
+
/* Associate pktgen_dev with a device. */
static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
@@ -1908,7 +1935,7 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
pkt_dev->odev = NULL;
}
- odev = dev_get_by_name(&init_net, ifname);
+ odev = pktgen_dev_get_by_name(pkt_dev, ifname);
if (!odev) {
printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname);
return -ENODEV;
@@ -2085,15 +2112,19 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)
if (pkt_dev->flows[flow].count >= pkt_dev->lflow) {
/* reset time */
pkt_dev->flows[flow].count = 0;
+ pkt_dev->flows[flow].flags = 0;
pkt_dev->curfl += 1;
if (pkt_dev->curfl >= pkt_dev->cflows)
pkt_dev->curfl = 0; /*reset */
}
} else {
flow = random32() % pkt_dev->cflows;
+ pkt_dev->curfl = flow;
- if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+ if (pkt_dev->flows[flow].count > pkt_dev->lflow) {
pkt_dev->flows[flow].count = 0;
+ pkt_dev->flows[flow].flags = 0;
+ }
}
return pkt_dev->curfl;
@@ -2125,7 +2156,11 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
#endif
static void set_cur_queue_map(struct pktgen_dev *pkt_dev)
{
- if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) {
+
+ if (pkt_dev->flags & F_QUEUE_MAP_CPU)
+ pkt_dev->cur_queue_map = smp_processor_id();
+
+ else if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) {
__u16 t;
if (pkt_dev->flags & F_QUEUE_MAP_RND) {
t = random32() %
@@ -2162,7 +2197,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
mc = random32() % pkt_dev->src_mac_count;
else {
mc = pkt_dev->cur_src_mac_offset++;
- if (pkt_dev->cur_src_mac_offset >
+ if (pkt_dev->cur_src_mac_offset >=
pkt_dev->src_mac_count)
pkt_dev->cur_src_mac_offset = 0;
}
@@ -2189,7 +2224,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
else {
mc = pkt_dev->cur_dst_mac_offset++;
- if (pkt_dev->cur_dst_mac_offset >
+ if (pkt_dev->cur_dst_mac_offset >=
pkt_dev->dst_mac_count) {
pkt_dev->cur_dst_mac_offset = 0;
}
@@ -3305,6 +3340,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
txq = netdev_get_tx_queue(odev, queue_map);
if (netif_tx_queue_stopped(txq) ||
+ netif_tx_queue_frozen(txq) ||
need_resched()) {
idle_start = getCurUs();
@@ -3320,7 +3356,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->idle_acc += getCurUs() - idle_start;
- if (netif_tx_queue_stopped(txq)) {
+ if (netif_tx_queue_stopped(txq) ||
+ netif_tx_queue_frozen(txq)) {
pkt_dev->next_tx_us = getCurUs(); /* TODO */
pkt_dev->next_tx_ns = 0;
goto out; /* Try the next interface */
@@ -3352,7 +3389,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
txq = netdev_get_tx_queue(odev, queue_map);
__netif_tx_lock_bh(txq);
- if (!netif_tx_queue_stopped(txq)) {
+ if (!netif_tx_queue_stopped(txq) &&
+ !netif_tx_queue_frozen(txq)) {
atomic_inc(&(pkt_dev->skb->users));
retry_now:
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 4e0c9227418..84640172d65 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -485,6 +485,9 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
C(head);
C(data);
C(truesize);
+#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
+ C(do_not_encrypt);
+#endif
atomic_set(&n->users, 1);
atomic_inc(&(skb_shinfo(skb)->dataref));