1 #include <linux/skbuff.h> 2 #include <linux/slab.h> 3 #include <linux/netdevice.h> 4 #include <net/gro_cells.h> 5 6 struct gro_cell { 7 struct sk_buff_head napi_skbs; 8 struct napi_struct napi; 9 }; 10 11 int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) 12 { 13 struct net_device *dev = skb->dev; 14 struct gro_cell *cell; 15 16 if (!gcells->cells || skb_cloned(skb) || netif_elide_gro(dev)) 17 return netif_rx(skb); 18 19 cell = this_cpu_ptr(gcells->cells); 20 21 if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) { 22 atomic_long_inc(&dev->rx_dropped); 23 kfree_skb(skb); 24 return NET_RX_DROP; 25 } 26 27 __skb_queue_tail(&cell->napi_skbs, skb); 28 if (skb_queue_len(&cell->napi_skbs) == 1) 29 napi_schedule(&cell->napi); 30 return NET_RX_SUCCESS; 31 } 32 EXPORT_SYMBOL(gro_cells_receive); 33 34 /* called under BH context */ 35 static int gro_cell_poll(struct napi_struct *napi, int budget) 36 { 37 struct gro_cell *cell = container_of(napi, struct gro_cell, napi); 38 struct sk_buff *skb; 39 int work_done = 0; 40 41 while (work_done < budget) { 42 skb = __skb_dequeue(&cell->napi_skbs); 43 if (!skb) 44 break; 45 napi_gro_receive(napi, skb); 46 work_done++; 47 } 48 49 if (work_done < budget) 50 napi_complete_done(napi, work_done); 51 return work_done; 52 } 53 54 int gro_cells_init(struct gro_cells *gcells, struct net_device *dev) 55 { 56 int i; 57 58 gcells->cells = alloc_percpu(struct gro_cell); 59 if (!gcells->cells) 60 return -ENOMEM; 61 62 for_each_possible_cpu(i) { 63 struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 64 65 __skb_queue_head_init(&cell->napi_skbs); 66 67 set_bit(NAPI_STATE_NO_BUSY_POLL, &cell->napi.state); 68 69 netif_napi_add(dev, &cell->napi, gro_cell_poll, 70 NAPI_POLL_WEIGHT); 71 napi_enable(&cell->napi); 72 } 73 return 0; 74 } 75 EXPORT_SYMBOL(gro_cells_init); 76 77 void gro_cells_destroy(struct gro_cells *gcells) 78 { 79 int i; 80 81 if (!gcells->cells) 82 return; 83 for_each_possible_cpu(i) { 84 struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 85 86 netif_napi_del(&cell->napi); 87 __skb_queue_purge(&cell->napi_skbs); 88 } 89 free_percpu(gcells->cells); 90 gcells->cells = NULL; 91 } 92 EXPORT_SYMBOL(gro_cells_destroy); 93