aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c59
1 files changed, 44 insertions, 15 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1e0a1847c3bb..09cb3f6dc40c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3300,18 +3300,18 @@ ncls:
3300 && !skb_pfmemalloc_protocol(skb)) 3300 && !skb_pfmemalloc_protocol(skb))
3301 goto drop; 3301 goto drop;
3302 3302
3303 rx_handler = rcu_dereference(skb->dev->rx_handler);
3304 if (vlan_tx_tag_present(skb)) { 3303 if (vlan_tx_tag_present(skb)) {
3305 if (pt_prev) { 3304 if (pt_prev) {
3306 ret = deliver_skb(skb, pt_prev, orig_dev); 3305 ret = deliver_skb(skb, pt_prev, orig_dev);
3307 pt_prev = NULL; 3306 pt_prev = NULL;
3308 } 3307 }
3309 if (vlan_do_receive(&skb, !rx_handler)) 3308 if (vlan_do_receive(&skb))
3310 goto another_round; 3309 goto another_round;
3311 else if (unlikely(!skb)) 3310 else if (unlikely(!skb))
3312 goto unlock; 3311 goto unlock;
3313 } 3312 }
3314 3313
3314 rx_handler = rcu_dereference(skb->dev->rx_handler);
3315 if (rx_handler) { 3315 if (rx_handler) {
3316 if (pt_prev) { 3316 if (pt_prev) {
3317 ret = deliver_skb(skb, pt_prev, orig_dev); 3317 ret = deliver_skb(skb, pt_prev, orig_dev);
@@ -3331,6 +3331,9 @@ ncls:
3331 } 3331 }
3332 } 3332 }
3333 3333
3334 if (vlan_tx_nonzero_tag_present(skb))
3335 skb->pkt_type = PACKET_OTHERHOST;
3336
3334 /* deliver only exact match when indicated */ 3337 /* deliver only exact match when indicated */
3335 null_or_dev = deliver_exact ? skb->dev : NULL; 3338 null_or_dev = deliver_exact ? skb->dev : NULL;
3336 3339
@@ -3471,17 +3474,31 @@ out:
3471 return netif_receive_skb(skb); 3474 return netif_receive_skb(skb);
3472} 3475}
3473 3476
3474inline void napi_gro_flush(struct napi_struct *napi) 3477/* napi->gro_list contains packets ordered by age.
3478 * youngest packets at the head of it.
3479 * Complete skbs in reverse order to reduce latencies.
3480 */
3481void napi_gro_flush(struct napi_struct *napi, bool flush_old)
3475{ 3482{
3476 struct sk_buff *skb, *next; 3483 struct sk_buff *skb, *prev = NULL;
3477 3484
3478 for (skb = napi->gro_list; skb; skb = next) { 3485 /* scan list and build reverse chain */
3479 next = skb->next; 3486 for (skb = napi->gro_list; skb != NULL; skb = skb->next) {
3487 skb->prev = prev;
3488 prev = skb;
3489 }
3490
3491 for (skb = prev; skb; skb = prev) {
3480 skb->next = NULL; 3492 skb->next = NULL;
3493
3494 if (flush_old && NAPI_GRO_CB(skb)->age == jiffies)
3495 return;
3496
3497 prev = skb->prev;
3481 napi_gro_complete(skb); 3498 napi_gro_complete(skb);
3499 napi->gro_count--;
3482 } 3500 }
3483 3501
3484 napi->gro_count = 0;
3485 napi->gro_list = NULL; 3502 napi->gro_list = NULL;
3486} 3503}
3487EXPORT_SYMBOL(napi_gro_flush); 3504EXPORT_SYMBOL(napi_gro_flush);
@@ -3542,6 +3559,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
3542 3559
3543 napi->gro_count++; 3560 napi->gro_count++;
3544 NAPI_GRO_CB(skb)->count = 1; 3561 NAPI_GRO_CB(skb)->count = 1;
3562 NAPI_GRO_CB(skb)->age = jiffies;
3545 skb_shinfo(skb)->gso_size = skb_gro_len(skb); 3563 skb_shinfo(skb)->gso_size = skb_gro_len(skb);
3546 skb->next = napi->gro_list; 3564 skb->next = napi->gro_list;
3547 napi->gro_list = skb; 3565 napi->gro_list = skb;
@@ -3631,20 +3649,22 @@ gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
3631} 3649}
3632EXPORT_SYMBOL(napi_skb_finish); 3650EXPORT_SYMBOL(napi_skb_finish);
3633 3651
3634void skb_gro_reset_offset(struct sk_buff *skb) 3652static void skb_gro_reset_offset(struct sk_buff *skb)
3635{ 3653{
3654 const struct skb_shared_info *pinfo = skb_shinfo(skb);
3655 const skb_frag_t *frag0 = &pinfo->frags[0];
3656
3636 NAPI_GRO_CB(skb)->data_offset = 0; 3657 NAPI_GRO_CB(skb)->data_offset = 0;
3637 NAPI_GRO_CB(skb)->frag0 = NULL; 3658 NAPI_GRO_CB(skb)->frag0 = NULL;
3638 NAPI_GRO_CB(skb)->frag0_len = 0; 3659 NAPI_GRO_CB(skb)->frag0_len = 0;
3639 3660
3640 if (skb->mac_header == skb->tail && 3661 if (skb->mac_header == skb->tail &&
3641 !PageHighMem(skb_frag_page(&skb_shinfo(skb)->frags[0]))) { 3662 pinfo->nr_frags &&
3642 NAPI_GRO_CB(skb)->frag0 = 3663 !PageHighMem(skb_frag_page(frag0))) {
3643 skb_frag_address(&skb_shinfo(skb)->frags[0]); 3664 NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
3644 NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(&skb_shinfo(skb)->frags[0]); 3665 NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
3645 } 3666 }
3646} 3667}
3647EXPORT_SYMBOL(skb_gro_reset_offset);
3648 3668
3649gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) 3669gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
3650{ 3670{
@@ -3876,7 +3896,7 @@ void napi_complete(struct napi_struct *n)
3876 if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state))) 3896 if (unlikely(test_bit(NAPI_STATE_NPSVC, &n->state)))
3877 return; 3897 return;
3878 3898
3879 napi_gro_flush(n); 3899 napi_gro_flush(n, false);
3880 local_irq_save(flags); 3900 local_irq_save(flags);
3881 __napi_complete(n); 3901 __napi_complete(n);
3882 local_irq_restore(flags); 3902 local_irq_restore(flags);
@@ -3981,8 +4001,17 @@ static void net_rx_action(struct softirq_action *h)
3981 local_irq_enable(); 4001 local_irq_enable();
3982 napi_complete(n); 4002 napi_complete(n);
3983 local_irq_disable(); 4003 local_irq_disable();
3984 } else 4004 } else {
4005 if (n->gro_list) {
4006 /* flush too old packets
4007 * If HZ < 1000, flush all packets.
4008 */
4009 local_irq_enable();
4010 napi_gro_flush(n, HZ >= 1000);
4011 local_irq_disable();
4012 }
3985 list_move_tail(&n->poll_list, &sd->poll_list); 4013 list_move_tail(&n->poll_list, &sd->poll_list);
4014 }
3986 } 4015 }
3987 4016
3988 netpoll_poll_unlock(have); 4017 netpoll_poll_unlock(have);