LCOV - code coverage report
Current view: top level - net/core - gro_cells.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 10 55 18.2 %
Date: 2022-03-28 13:20:08 Functions: 1 4 25.0 %
Branches: 3 30 10.0 %

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

Generated by: LCOV version 1.14