Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: reimplement softnet_data.output_queue as a FIFO queue

reimplement softnet_data.output_queue as a FIFO queue to keep the
fairness among the qdiscs rescheduled.

Signed-off-by: Changli Gao <xiaosuo@gmail.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
----
include/linux/netdevice.h | 1 +
net/core/dev.c | 22 ++++++++++++----------
2 files changed, 13 insertions(+), 10 deletions(-)
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Changli Gao and committed by
David S. Miller
a9cbd588 bb611874

+13 -10
+1
include/linux/netdevice.h
··· 1385 1385 */ 1386 1386 struct softnet_data { 1387 1387 struct Qdisc *output_queue; 1388 + struct Qdisc **output_queue_tailp; 1388 1389 struct list_head poll_list; 1389 1390 struct sk_buff *completion_queue; 1390 1391
+12 -10
net/core/dev.c
··· 1557 1557 1558 1558 local_irq_save(flags); 1559 1559 sd = &__get_cpu_var(softnet_data); 1560 - q->next_sched = sd->output_queue; 1561 - sd->output_queue = q; 1560 + q->next_sched = NULL; 1561 + *sd->output_queue_tailp = q; 1562 + sd->output_queue_tailp = &q->next_sched; 1562 1563 raise_softirq_irqoff(NET_TX_SOFTIRQ); 1563 1564 local_irq_restore(flags); 1564 1565 } ··· 2530 2529 local_irq_disable(); 2531 2530 head = sd->output_queue; 2532 2531 sd->output_queue = NULL; 2532 + sd->output_queue_tailp = &sd->output_queue; 2533 2533 local_irq_enable(); 2534 2534 2535 2535 while (head) { ··· 5596 5594 void *ocpu) 5597 5595 { 5598 5596 struct sk_buff **list_skb; 5599 - struct Qdisc **list_net; 5600 5597 struct sk_buff *skb; 5601 5598 unsigned int cpu, oldcpu = (unsigned long)ocpu; 5602 5599 struct softnet_data *sd, *oldsd; ··· 5616 5615 *list_skb = oldsd->completion_queue; 5617 5616 oldsd->completion_queue = NULL; 5618 5617 5619 - /* Find end of our output_queue. */ 5620 - list_net = &sd->output_queue; 5621 - while (*list_net) 5622 - list_net = &(*list_net)->next_sched; 5623 5618 /* Append output queue from offline CPU. */ 5624 - *list_net = oldsd->output_queue; 5625 - oldsd->output_queue = NULL; 5619 + if (oldsd->output_queue) { 5620 + *sd->output_queue_tailp = oldsd->output_queue; 5621 + sd->output_queue_tailp = oldsd->output_queue_tailp; 5622 + oldsd->output_queue = NULL; 5623 + oldsd->output_queue_tailp = &oldsd->output_queue; 5624 + } 5626 5625 5627 5626 raise_softirq_irqoff(NET_TX_SOFTIRQ); 5628 5627 local_irq_enable(); ··· 5852 5851 skb_queue_head_init(&sd->input_pkt_queue); 5853 5852 sd->completion_queue = NULL; 5854 5853 INIT_LIST_HEAD(&sd->poll_list); 5855 - 5854 + sd->output_queue = NULL; 5855 + sd->output_queue_tailp = &sd->output_queue; 5856 5856 #ifdef CONFIG_RPS 5857 5857 sd->csd.func = rps_trigger_softirq; 5858 5858 sd->csd.info = sd;