aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-06-23 23:12:48 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-23 23:12:48 -0400
commit31aa02c53c84658f6694f319f09e232ede27be5a (patch)
tree3af5cce958dcce744548b312a043aa4a0b769a50
parent34008d8c631d067caffa136313260525f3ae48a2 (diff)
[NET]: Eliminate netif_rx massive packet drops.
Eliminate the throttling behaviour when the netif receive queue fills because it behaves badly when using high speed networks under load. The throttling cause multiple packet drops that cause TCP to go into slow start mode. The same effective patch has been part of BIC TCP and H-TCP as well as part of Web100. The existing code drops 100's of packets when the queue fills; this changes it to individual packet drop-tail. Signed-off-by: Stephen Hemmminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h4
-rw-r--r--net/core/dev.c21
2 files changed, 3 insertions, 22 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 718ad579c65c..3a0ed7f9e801 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -164,7 +164,6 @@ struct netif_rx_stats
164 unsigned total; 164 unsigned total;
165 unsigned dropped; 165 unsigned dropped;
166 unsigned time_squeeze; 166 unsigned time_squeeze;
167 unsigned throttled;
168 unsigned cpu_collision; 167 unsigned cpu_collision;
169}; 168};
170 169
@@ -557,10 +556,9 @@ static inline int unregister_gifconf(unsigned int family)
557 556
558struct softnet_data 557struct softnet_data
559{ 558{
560 int throttle; 559 struct net_device *output_queue;
561 struct sk_buff_head input_pkt_queue; 560 struct sk_buff_head input_pkt_queue;
562 struct list_head poll_list; 561 struct list_head poll_list;
563 struct net_device *output_queue;
564 struct sk_buff *completion_queue; 562 struct sk_buff *completion_queue;
565 563
566 struct net_device backlog_dev; /* Sorry. 8) */ 564 struct net_device backlog_dev; /* Sorry. 8) */
diff --git a/net/core/dev.c b/net/core/dev.c
index 3156df699f01..1a64508e527f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -198,7 +198,7 @@ static struct notifier_block *netdev_chain;
198 * Device drivers call our routines to queue packets here. We empty the 198 * Device drivers call our routines to queue packets here. We empty the
199 * queue in the local softnet handler. 199 * queue in the local softnet handler.
200 */ 200 */
201DEFINE_PER_CPU(struct softnet_data, softnet_data) = { 0, }; 201DEFINE_PER_CPU(struct softnet_data, softnet_data) = { NULL };
202 202
203#ifdef CONFIG_SYSFS 203#ifdef CONFIG_SYSFS
204extern int netdev_sysfs_init(void); 204extern int netdev_sysfs_init(void);
@@ -1372,7 +1372,6 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
1372 1372
1373int netif_rx(struct sk_buff *skb) 1373int netif_rx(struct sk_buff *skb)
1374{ 1374{
1375 int this_cpu;
1376 struct softnet_data *queue; 1375 struct softnet_data *queue;
1377 unsigned long flags; 1376 unsigned long flags;
1378 1377
@@ -1388,15 +1387,11 @@ int netif_rx(struct sk_buff *skb)
1388 * short when CPU is congested, but is still operating. 1387 * short when CPU is congested, but is still operating.
1389 */ 1388 */
1390 local_irq_save(flags); 1389 local_irq_save(flags);
1391 this_cpu = smp_processor_id();
1392 queue = &__get_cpu_var(softnet_data); 1390 queue = &__get_cpu_var(softnet_data);
1393 1391
1394 __get_cpu_var(netdev_rx_stat).total++; 1392 __get_cpu_var(netdev_rx_stat).total++;
1395 if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { 1393 if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
1396 if (queue->input_pkt_queue.qlen) { 1394 if (queue->input_pkt_queue.qlen) {
1397 if (queue->throttle)
1398 goto drop;
1399
1400enqueue: 1395enqueue:
1401 dev_hold(skb->dev); 1396 dev_hold(skb->dev);
1402 __skb_queue_tail(&queue->input_pkt_queue, skb); 1397 __skb_queue_tail(&queue->input_pkt_queue, skb);
@@ -1404,19 +1399,10 @@ enqueue:
1404 return NET_RX_SUCCESS; 1399 return NET_RX_SUCCESS;
1405 } 1400 }
1406 1401
1407 if (queue->throttle)
1408 queue->throttle = 0;
1409
1410 netif_rx_schedule(&queue->backlog_dev); 1402 netif_rx_schedule(&queue->backlog_dev);
1411 goto enqueue; 1403 goto enqueue;
1412 } 1404 }
1413 1405
1414 if (!queue->throttle) {
1415 queue->throttle = 1;
1416 __get_cpu_var(netdev_rx_stat).throttled++;
1417 }
1418
1419drop:
1420 __get_cpu_var(netdev_rx_stat).dropped++; 1406 __get_cpu_var(netdev_rx_stat).dropped++;
1421 local_irq_restore(flags); 1407 local_irq_restore(flags);
1422 1408
@@ -1701,8 +1687,6 @@ job_done:
1701 smp_mb__before_clear_bit(); 1687 smp_mb__before_clear_bit();
1702 netif_poll_enable(backlog_dev); 1688 netif_poll_enable(backlog_dev);
1703 1689
1704 if (queue->throttle)
1705 queue->throttle = 0;
1706 local_irq_enable(); 1690 local_irq_enable();
1707 return 0; 1691 return 0;
1708} 1692}
@@ -1976,7 +1960,7 @@ static int softnet_seq_show(struct seq_file *seq, void *v)
1976 struct netif_rx_stats *s = v; 1960 struct netif_rx_stats *s = v;
1977 1961
1978 seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", 1962 seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
1979 s->total, s->dropped, s->time_squeeze, s->throttled, 1963 s->total, s->dropped, s->time_squeeze, 0,
1980 0, 0, 0, 0, /* was fastroute */ 1964 0, 0, 0, 0, /* was fastroute */
1981 s->cpu_collision ); 1965 s->cpu_collision );
1982 return 0; 1966 return 0;
@@ -3220,7 +3204,6 @@ static int __init net_dev_init(void)
3220 3204
3221 queue = &per_cpu(softnet_data, i); 3205 queue = &per_cpu(softnet_data, i);
3222 skb_queue_head_init(&queue->input_pkt_queue); 3206 skb_queue_head_init(&queue->input_pkt_queue);
3223 queue->throttle = 0;
3224 queue->completion_queue = NULL; 3207 queue->completion_queue = NULL;
3225 INIT_LIST_HEAD(&queue->poll_list); 3208 INIT_LIST_HEAD(&queue->poll_list);
3226 set_bit(__LINK_STATE_START, &queue->backlog_dev.state); 3209 set_bit(__LINK_STATE_START, &queue->backlog_dev.state);