net: Convert GRO SKB handling to list_head.
authorDavid Miller <davem@davemloft.net>
Sun, 24 Jun 2018 05:13:49 +0000 (14:13 +0900)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Jun 2018 02:33:04 +0000 (11:33 +0900)
Manage pending per-NAPI GRO packets via list_head.

Return an SKB pointer from the GRO receive handlers.  When GRO receive
handlers return non-NULL, it means that this SKB needs to be completed
at this time and removed from the NAPI queue.

Several operations are greatly simplified by this transformation,
especially timing out the oldest SKB in the list when gro_count
exceeds MAX_GRO_SKBS, and napi_gro_flush() which walks the queue
in reverse order.

Signed-off-by: David S. Miller <davem@davemloft.net>
24 files changed:
drivers/net/geneve.c
drivers/net/vxlan.c
include/linux/etherdevice.h
include/linux/netdevice.h
include/linux/skbuff.h
include/linux/udp.h
include/net/inet_common.h
include/net/tcp.h
include/net/udp.h
include/net/udp_tunnel.h
net/8021q/vlan.c
net/core/dev.c
net/core/skbuff.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/esp4_offload.c
net/ipv4/fou.c
net/ipv4/gre_offload.c
net/ipv4/tcp_offload.c
net/ipv4/udp_offload.c
net/ipv6/esp6_offload.c
net/ipv6/ip6_offload.c
net/ipv6/tcpv6_offload.c
net/ipv6/udp_offload.c

index 750eaa53bf0ce59429d524ba0658ad6f488a4ba0..3e94375b9b01cb90494e62bc9883dc84dc76c0f5 100644 (file)
@@ -418,11 +418,12 @@ static int geneve_hlen(struct genevehdr *gh)
        return sizeof(*gh) + gh->opt_len * 4;
 }
 
-static struct sk_buff **geneve_gro_receive(struct sock *sk,
-                                          struct sk_buff **head,
-                                          struct sk_buff *skb)
+static struct sk_buff *geneve_gro_receive(struct sock *sk,
+                                         struct list_head *head,
+                                         struct sk_buff *skb)
 {
-       struct sk_buff *p, **pp = NULL;
+       struct sk_buff *pp = NULL;
+       struct sk_buff *p;
        struct genevehdr *gh, *gh2;
        unsigned int hlen, gh_len, off_gnv;
        const struct packet_offload *ptype;
@@ -449,7 +450,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
                        goto out;
        }
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
index aee0e60471f10d59c39ad39f8170eedea722455d..cc14e0cd56470a3e2b92ef3e7b473e567a9272ae 100644 (file)
@@ -568,11 +568,12 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
        return vh;
 }
 
-static struct sk_buff **vxlan_gro_receive(struct sock *sk,
-                                         struct sk_buff **head,
-                                         struct sk_buff *skb)
+static struct sk_buff *vxlan_gro_receive(struct sock *sk,
+                                        struct list_head *head,
+                                        struct sk_buff *skb)
 {
-       struct sk_buff *p, **pp = NULL;
+       struct sk_buff *pp = NULL;
+       struct sk_buff *p;
        struct vxlanhdr *vh, *vh2;
        unsigned int hlen, off_vx;
        int flush = 1;
@@ -607,7 +608,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk,
 
        skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
index 79563840c295cfcd40d17287eebcf793ee010020..572e11bb869672cbc9b6da8a375760b192f9eaf9 100644 (file)
@@ -59,8 +59,7 @@ struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv,
                                           unsigned int rxqs);
 #define devm_alloc_etherdev(dev, sizeof_priv) devm_alloc_etherdev_mqs(dev, sizeof_priv, 1, 1)
 
-struct sk_buff **eth_gro_receive(struct sk_buff **head,
-                                struct sk_buff *skb);
+struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb);
 int eth_gro_complete(struct sk_buff *skb, int nhoff);
 
 /* Reserved Ethernet Addresses per IEEE 802.1Q */
index 3ec9850c7936f01c0f7564dbe519e95ce0849639..f176d9873910e007bd8c194b72546ac9a1f85afc 100644 (file)
@@ -322,7 +322,7 @@ struct napi_struct {
        int                     poll_owner;
 #endif
        struct net_device       *dev;
-       struct sk_buff          *gro_list;
+       struct list_head        gro_list;
        struct sk_buff          *skb;
        struct hrtimer          timer;
        struct list_head        dev_list;
@@ -2255,10 +2255,10 @@ static inline int gro_recursion_inc_test(struct sk_buff *skb)
        return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT;
 }
 
-typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *);
-static inline struct sk_buff **call_gro_receive(gro_receive_t cb,
-                                               struct sk_buff **head,
-                                               struct sk_buff *skb)
+typedef struct sk_buff *(*gro_receive_t)(struct list_head *, struct sk_buff *);
+static inline struct sk_buff *call_gro_receive(gro_receive_t cb,
+                                              struct list_head *head,
+                                              struct sk_buff *skb)
 {
        if (unlikely(gro_recursion_inc_test(skb))) {
                NAPI_GRO_CB(skb)->flush |= 1;
@@ -2268,12 +2268,12 @@ static inline struct sk_buff **call_gro_receive(gro_receive_t cb,
        return cb(head, skb);
 }
 
-typedef struct sk_buff **(*gro_receive_sk_t)(struct sock *, struct sk_buff **,
-                                            struct sk_buff *);
-static inline struct sk_buff **call_gro_receive_sk(gro_receive_sk_t cb,
-                                                  struct sock *sk,
-                                                  struct sk_buff **head,
-                                                  struct sk_buff *skb)
+typedef struct sk_buff *(*gro_receive_sk_t)(struct sock *, struct list_head *,
+                                           struct sk_buff *);
+static inline struct sk_buff *call_gro_receive_sk(gro_receive_sk_t cb,
+                                                 struct sock *sk,
+                                                 struct list_head *head,
+                                                 struct sk_buff *skb)
 {
        if (unlikely(gro_recursion_inc_test(skb))) {
                NAPI_GRO_CB(skb)->flush |= 1;
@@ -2299,8 +2299,8 @@ struct packet_type {
 struct offload_callbacks {
        struct sk_buff          *(*gso_segment)(struct sk_buff *skb,
                                                netdev_features_t features);
-       struct sk_buff          **(*gro_receive)(struct sk_buff **head,
-                                                struct sk_buff *skb);
+       struct sk_buff          *(*gro_receive)(struct list_head *head,
+                                               struct sk_buff *skb);
        int                     (*gro_complete)(struct sk_buff *skb, int nhoff);
 };
 
@@ -2568,7 +2568,7 @@ struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex);
 struct net_device *dev_get_by_napi_id(unsigned int napi_id);
 int netdev_get_name(struct net *net, char *name, int ifindex);
 int dev_restart(struct net_device *dev);
-int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb);
+int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb);
 
 static inline unsigned int skb_gro_offset(const struct sk_buff *skb)
 {
@@ -2784,13 +2784,13 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
 }
 
 #ifdef CONFIG_XFRM_OFFLOAD
-static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush)
+static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff *pp, int flush)
 {
        if (PTR_ERR(pp) != -EINPROGRESS)
                NAPI_GRO_CB(skb)->flush |= flush;
 }
 #else
-static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush)
+static inline void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff *pp, int flush)
 {
        NAPI_GRO_CB(skb)->flush |= flush;
 }
index c8688595499421d9f051366d4a85e5553751768e..7ccc601b55d9ba231c62dba6c92a08f117d69302 100644 (file)
@@ -677,7 +677,8 @@ struct sk_buff {
                                int                     ip_defrag_offset;
                        };
                };
-               struct rb_node  rbnode; /* used in netem & tcp stack */
+               struct rb_node          rbnode; /* used in netem & tcp stack */
+               struct list_head        list;
        };
        struct sock             *sk;
 
index ca840345571bf6cf9253647c11112252fa7b6241..320d49d85484d4ac2d0fdbbe365ad339bf949c0b 100644 (file)
@@ -74,8 +74,8 @@ struct udp_sock {
        void (*encap_destroy)(struct sock *sk);
 
        /* GRO functions for UDP socket */
-       struct sk_buff **       (*gro_receive)(struct sock *sk,
-                                              struct sk_buff **head,
+       struct sk_buff *        (*gro_receive)(struct sock *sk,
+                                              struct list_head *head,
                                               struct sk_buff *skb);
        int                     (*gro_complete)(struct sock *sk,
                                                struct sk_buff *skb,
index 384b90c62c0bce9b60d74383a2c68287a3f30d95..3ca969cbd16117fe15b1521333c5d7a28c8709f7 100644 (file)
@@ -43,7 +43,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
                    int *addr_len);
 
-struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb);
+struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb);
 int inet_gro_complete(struct sk_buff *skb, int nhoff);
 struct sk_buff *inet_gso_segment(struct sk_buff *skb,
                                 netdev_features_t features);
index 822ee49ed0f962f0531e2cab786899ca6f16536a..402a88b0e8a86373afb36e9c6fc7427c62fa85cd 100644 (file)
@@ -1788,7 +1788,7 @@ void tcp_v4_destroy_sock(struct sock *sk);
 
 struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
                                netdev_features_t features);
-struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb);
+struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb);
 int tcp_gro_complete(struct sk_buff *skb);
 
 void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr);
index b1ea8b0f5e6a8ce82602e593acd583170b4a6e73..5723c6128ae492610d48cd1ee9abe45e8ec9ecf6 100644 (file)
@@ -170,8 +170,8 @@ static inline void udp_csum_pull_header(struct sk_buff *skb)
 typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport,
                                     __be16 dport);
 
-struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
-                                struct udphdr *uh, udp_lookup_t lookup);
+struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
+                               struct udphdr *uh, udp_lookup_t lookup);
 int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
 
 struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
index b95a6927c7185eae2481d21235fa106e8a7ddb94..fe680ab6b15a18aba378d161d57461176b75d8cb 100644 (file)
@@ -65,9 +65,9 @@ static inline int udp_sock_create(struct net *net,
 
 typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb);
 typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk);
-typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk,
-                                                    struct sk_buff **head,
-                                                    struct sk_buff *skb);
+typedef struct sk_buff *(*udp_tunnel_gro_receive_t)(struct sock *sk,
+                                                   struct list_head *head,
+                                                   struct sk_buff *skb);
 typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb,
                                         int nhoff);
 
index 73a65789271ba9346902dd721b0accd8ce747adc..99141986efa02c6b17ae60abb7c84d18bf313bf0 100644 (file)
@@ -647,13 +647,14 @@ out:
        return err;
 }
 
-static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *vlan_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
-       struct sk_buff *p, **pp = NULL;
-       struct vlan_hdr *vhdr;
-       unsigned int hlen, off_vlan;
        const struct packet_offload *ptype;
+       unsigned int hlen, off_vlan;
+       struct sk_buff *pp = NULL;
+       struct vlan_hdr *vhdr;
+       struct sk_buff *p;
        __be16 type;
        int flush = 1;
 
@@ -675,7 +676,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
 
        flush = 0;
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                struct vlan_hdr *vhdr2;
 
                if (!NAPI_GRO_CB(p)->same_flow)
index a5aa1c7444e688e66263fc112a4211409840a749..aa61b9344b46dca53ffeebf325738bf5b0f1e328 100644 (file)
@@ -4881,36 +4881,25 @@ out:
  */
 void napi_gro_flush(struct napi_struct *napi, bool flush_old)
 {
-       struct sk_buff *skb, *prev = NULL;
-
-       /* scan list and build reverse chain */
-       for (skb = napi->gro_list; skb != NULL; skb = skb->next) {
-               skb->prev = prev;
-               prev = skb;
-       }
-
-       for (skb = prev; skb; skb = prev) {
-               skb->next = NULL;
+       struct sk_buff *skb, *p;
 
+       list_for_each_entry_safe_reverse(skb, p, &napi->gro_list, list) {
                if (flush_old && NAPI_GRO_CB(skb)->age == jiffies)
                        return;
-
-               prev = skb->prev;
+               list_del_init(&skb->list);
                napi_gro_complete(skb);
                napi->gro_count--;
        }
-
-       napi->gro_list = NULL;
 }
 EXPORT_SYMBOL(napi_gro_flush);
 
 static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
 {
-       struct sk_buff *p;
        unsigned int maclen = skb->dev->hard_header_len;
        u32 hash = skb_get_hash_raw(skb);
+       struct sk_buff *p;
 
-       for (p = napi->gro_list; p; p = p->next) {
+       list_for_each_entry(p, &napi->gro_list, list) {
                unsigned long diffs;
 
                NAPI_GRO_CB(p)->flush = 0;
@@ -4977,12 +4966,12 @@ static void gro_pull_from_frag0(struct sk_buff *skb, int grow)
 
 static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
-       struct sk_buff **pp = NULL;
+       struct list_head *head = &offload_base;
        struct packet_offload *ptype;
        __be16 type = skb->protocol;
-       struct list_head *head = &offload_base;
-       int same_flow;
+       struct sk_buff *pp = NULL;
        enum gro_result ret;
+       int same_flow;
        int grow;
 
        if (netif_elide_gro(skb->dev))
@@ -5039,11 +5028,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        ret = NAPI_GRO_CB(skb)->free ? GRO_MERGED_FREE : GRO_MERGED;
 
        if (pp) {
-               struct sk_buff *nskb = *pp;
-
-               *pp = nskb->next;
-               nskb->next = NULL;
-               napi_gro_complete(nskb);
+               list_del_init(&pp->list);
+               napi_gro_complete(pp);
                napi->gro_count--;
        }
 
@@ -5054,15 +5040,10 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
                goto normal;
 
        if (unlikely(napi->gro_count >= MAX_GRO_SKBS)) {
-               struct sk_buff *nskb = napi->gro_list;
+               struct sk_buff *nskb;
 
-               /* locate the end of the list to select the 'oldest' flow */
-               while (nskb->next) {
-                       pp = &nskb->next;
-                       nskb = *pp;
-               }
-               *pp = NULL;
-               nskb->next = NULL;
+               nskb = list_last_entry(&napi->gro_list, struct sk_buff, list);
+               list_del(&nskb->list);
                napi_gro_complete(nskb);
        } else {
                napi->gro_count++;
@@ -5071,8 +5052,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        NAPI_GRO_CB(skb)->age = jiffies;
        NAPI_GRO_CB(skb)->last = skb;
        skb_shinfo(skb)->gso_size = skb_gro_len(skb);
-       skb->next = napi->gro_list;
-       napi->gro_list = skb;
+       list_add(&skb->list, &napi->gro_list);
        ret = GRO_HELD;
 
 pull:
@@ -5478,7 +5458,7 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
                                 NAPIF_STATE_IN_BUSY_POLL)))
                return false;
 
-       if (n->gro_list) {
+       if (!list_empty(&n->gro_list)) {
                unsigned long timeout = 0;
 
                if (work_done)
@@ -5687,7 +5667,7 @@ static enum hrtimer_restart napi_watchdog(struct hrtimer *timer)
        /* Note : we use a relaxed variant of napi_schedule_prep() not setting
         * NAPI_STATE_MISSED, since we do not react to a device IRQ.
         */
-       if (napi->gro_list && !napi_disable_pending(napi) &&
+       if (!list_empty(&napi->gro_list) && !napi_disable_pending(napi) &&
            !test_and_set_bit(NAPI_STATE_SCHED, &napi->state))
                __napi_schedule_irqoff(napi);
 
@@ -5701,7 +5681,7 @@ void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
        hrtimer_init(&napi->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
        napi->timer.function = napi_watchdog;
        napi->gro_count = 0;
-       napi->gro_list = NULL;
+       INIT_LIST_HEAD(&napi->gro_list);
        napi->skb = NULL;
        napi->poll = poll;
        if (weight > NAPI_POLL_WEIGHT)
@@ -5734,6 +5714,14 @@ void napi_disable(struct napi_struct *n)
 }
 EXPORT_SYMBOL(napi_disable);
 
+static void gro_list_free(struct list_head *head)
+{
+       struct sk_buff *skb, *p;
+
+       list_for_each_entry_safe(skb, p, head, list)
+               kfree_skb(skb);
+}
+
 /* Must be called in process context */
 void netif_napi_del(struct napi_struct *napi)
 {
@@ -5743,8 +5731,8 @@ void netif_napi_del(struct napi_struct *napi)
        list_del_init(&napi->dev_list);
        napi_free_frags(napi);
 
-       kfree_skb_list(napi->gro_list);
-       napi->gro_list = NULL;
+       gro_list_free(&napi->gro_list);
+       INIT_LIST_HEAD(&napi->gro_list);
        napi->gro_count = 0;
 }
 EXPORT_SYMBOL(netif_napi_del);
@@ -5787,7 +5775,7 @@ static int napi_poll(struct napi_struct *n, struct list_head *repoll)
                goto out_unlock;
        }
 
-       if (n->gro_list) {
+       if (!list_empty(&n->gro_list)) {
                /* flush too old packets
                 * If HZ < 1000, flush all packets.
                 */
index c642304f178ce0a4e1358d59e45032a39f76fb3f..b1f274f22d85175dbf163b8d9526deee46577949 100644 (file)
@@ -3815,14 +3815,14 @@ err:
 }
 EXPORT_SYMBOL_GPL(skb_segment);
 
-int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
 {
        struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
        unsigned int offset = skb_gro_offset(skb);
        unsigned int headlen = skb_headlen(skb);
        unsigned int len = skb_gro_len(skb);
-       struct sk_buff *lp, *p = *head;
        unsigned int delta_truesize;
+       struct sk_buff *lp;
 
        if (unlikely(p->len + len >= 65536))
                return -E2BIG;
index ee28440f57c58f4eec29e67641a49efcbd36c8cd..fd8faa0dfa6193a186e562dae33008b4a0dc2182 100644 (file)
@@ -427,13 +427,13 @@ ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len)
 }
 EXPORT_SYMBOL(sysfs_format_mac);
 
-struct sk_buff **eth_gro_receive(struct sk_buff **head,
-                                struct sk_buff *skb)
+struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
-       struct sk_buff *p, **pp = NULL;
-       struct ethhdr *eh, *eh2;
-       unsigned int hlen, off_eth;
        const struct packet_offload *ptype;
+       unsigned int hlen, off_eth;
+       struct sk_buff *pp = NULL;
+       struct ethhdr *eh, *eh2;
+       struct sk_buff *p;
        __be16 type;
        int flush = 1;
 
@@ -448,7 +448,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head,
 
        flush = 0;
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
index 15e125558c76e5fa2fe466ab0d64be1d3183ebed..06b218a2870fb797b30b0f0a34c62333645e7aa5 100644 (file)
@@ -1384,12 +1384,12 @@ out:
 }
 EXPORT_SYMBOL(inet_gso_segment);
 
-struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
        const struct net_offload *ops;
-       struct sk_buff **pp = NULL;
-       struct sk_buff *p;
+       struct sk_buff *pp = NULL;
        const struct iphdr *iph;
+       struct sk_buff *p;
        unsigned int hlen;
        unsigned int off;
        unsigned int id;
@@ -1425,7 +1425,7 @@ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
        id >>= 16;
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                struct iphdr *iph2;
                u16 flush_id;
 
@@ -1505,8 +1505,8 @@ out:
 }
 EXPORT_SYMBOL(inet_gro_receive);
 
-static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *ipip_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        if (NAPI_GRO_CB(skb)->encap_mark) {
                NAPI_GRO_CB(skb)->flush = 1;
index 7cf755ef9efba3c13fcee22e1a24a320f4d9a503..bbeecd13e53477ce21c4c77f876f6e84966e1cb0 100644 (file)
@@ -28,8 +28,8 @@
 #include <linux/spinlock.h>
 #include <net/udp.h>
 
-static struct sk_buff **esp4_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *esp4_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        int offset = skb_gro_offset(skb);
        struct xfrm_offload *xo;
index 1540db65241a6fd4d96b00546f13a3e3d3cd1815..efdc9e1f741e4cc15f4e4e6be93e73a025f504ab 100644 (file)
@@ -224,14 +224,14 @@ drop:
        return 0;
 }
 
-static struct sk_buff **fou_gro_receive(struct sock *sk,
-                                       struct sk_buff **head,
-                                       struct sk_buff *skb)
+static struct sk_buff *fou_gro_receive(struct sock *sk,
+                                      struct list_head *head,
+                                      struct sk_buff *skb)
 {
-       const struct net_offload *ops;
-       struct sk_buff **pp = NULL;
        u8 proto = fou_from_sock(sk)->protocol;
        const struct net_offload **offloads;
+       const struct net_offload *ops;
+       struct sk_buff *pp = NULL;
 
        /* We can clear the encap_mark for FOU as we are essentially doing
         * one of two possible things.  We are either adding an L4 tunnel
@@ -305,13 +305,13 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
        return guehdr;
 }
 
-static struct sk_buff **gue_gro_receive(struct sock *sk,
-                                       struct sk_buff **head,
-                                       struct sk_buff *skb)
+static struct sk_buff *gue_gro_receive(struct sock *sk,
+                                      struct list_head *head,
+                                      struct sk_buff *skb)
 {
        const struct net_offload **offloads;
        const struct net_offload *ops;
-       struct sk_buff **pp = NULL;
+       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        struct guehdr *guehdr;
        size_t len, optlen, hdrlen, off;
@@ -397,7 +397,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk,
 
        skb_gro_pull(skb, hdrlen);
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                const struct guehdr *guehdr2;
 
                if (!NAPI_GRO_CB(p)->same_flow)
index 1859c473b21a862b383edebbcf2c1656f9c58b3b..b9673c21be452f0cf1f1824187252a38f83bbaf0 100644 (file)
@@ -108,10 +108,10 @@ out:
        return segs;
 }
 
-static struct sk_buff **gre_gro_receive(struct sk_buff **head,
-                                       struct sk_buff *skb)
+static struct sk_buff *gre_gro_receive(struct list_head *head,
+                                      struct sk_buff *skb)
 {
-       struct sk_buff **pp = NULL;
+       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        const struct gre_base_hdr *greh;
        unsigned int hlen, grehlen;
@@ -182,7 +182,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
                                             null_compute_pseudo);
        }
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                const struct gre_base_hdr *greh2;
 
                if (!NAPI_GRO_CB(p)->same_flow)
index 8cc7c348733052a8ef4bc06d09149171d8277006..f5aee641f825be8af56fd8ee9b0998f56605c0a7 100644 (file)
@@ -180,9 +180,9 @@ out:
        return segs;
 }
 
-struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
-       struct sk_buff **pp = NULL;
+       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        struct tcphdr *th;
        struct tcphdr *th2;
@@ -220,7 +220,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        len = skb_gro_len(skb);
        flags = tcp_flag_word(th);
 
-       for (; (p = *head); head = &p->next) {
+       list_for_each_entry(p, head, list) {
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
@@ -233,7 +233,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 
                goto found;
        }
-
+       p = NULL;
        goto out_check_final;
 
 found:
@@ -263,7 +263,7 @@ found:
        flush |= (len - 1) >= mss;
        flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq);
 
-       if (flush || skb_gro_receive(head, skb)) {
+       if (flush || skb_gro_receive(p, skb)) {
                mss = 1;
                goto out_check_final;
        }
@@ -277,7 +277,7 @@ out_check_final:
                                        TCP_FLAG_FIN));
 
        if (p && (!NAPI_GRO_CB(skb)->same_flow || flush))
-               pp = head;
+               pp = p;
 
 out:
        NAPI_GRO_CB(skb)->flush |= (flush != 0);
@@ -302,7 +302,7 @@ int tcp_gro_complete(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(tcp_gro_complete);
 
-static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+static struct sk_buff *tcp4_gro_receive(struct list_head *head, struct sk_buff *skb)
 {
        /* Don't bother verifying checksum if we're going to flush anyway. */
        if (!NAPI_GRO_CB(skb)->flush &&
index 92dc9e5a7ff3d0a7509bfa2a66e9189c8341a5fa..ac46c1c55c99f6dde0896ed4f3ba58b34ba7e50c 100644 (file)
@@ -343,10 +343,11 @@ out:
        return segs;
 }
 
-struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
-                                struct udphdr *uh, udp_lookup_t lookup)
+struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
+                               struct udphdr *uh, udp_lookup_t lookup)
 {
-       struct sk_buff *p, **pp = NULL;
+       struct sk_buff *pp = NULL;
+       struct sk_buff *p;
        struct udphdr *uh2;
        unsigned int off = skb_gro_offset(skb);
        int flush = 1;
@@ -371,7 +372,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
 unflush:
        flush = 0;
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                if (!NAPI_GRO_CB(p)->same_flow)
                        continue;
 
@@ -399,8 +400,8 @@ out:
 }
 EXPORT_SYMBOL(udp_gro_receive);
 
-static struct sk_buff **udp4_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *udp4_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        struct udphdr *uh = udp_gro_udphdr(skb);
 
index 27f59b61f70f59f6b4a4502727a161b5f1b91ef1..ddfa533a84e501dfb5b888b0d558dd59af43ec49 100644 (file)
@@ -49,8 +49,8 @@ static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
        return 0;
 }
 
-static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *esp6_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        int offset = skb_gro_offset(skb);
        struct xfrm_offload *xo;
index 5b3f2f89ef41c3276ef4b478683bd9ab04a1d3da..37ff4805b20c73fd3c404a0904985bae68f21f23 100644 (file)
@@ -163,11 +163,11 @@ static int ipv6_exthdrs_len(struct ipv6hdr *iph,
        return len;
 }
 
-static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *ipv6_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        const struct net_offload *ops;
-       struct sk_buff **pp = NULL;
+       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        struct ipv6hdr *iph;
        unsigned int nlen;
@@ -214,7 +214,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
        flush--;
        nlen = skb_network_header_len(skb);
 
-       for (p = *head; p; p = p->next) {
+       list_for_each_entry(p, head, list) {
                const struct ipv6hdr *iph2;
                __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
 
@@ -263,8 +263,8 @@ out:
        return pp;
 }
 
-static struct sk_buff **sit_ip6ip6_gro_receive(struct sk_buff **head,
-                                              struct sk_buff *skb)
+static struct sk_buff *sit_ip6ip6_gro_receive(struct list_head *head,
+                                             struct sk_buff *skb)
 {
        /* Common GRO receive for SIT and IP6IP6 */
 
@@ -278,8 +278,8 @@ static struct sk_buff **sit_ip6ip6_gro_receive(struct sk_buff **head,
        return ipv6_gro_receive(head, skb);
 }
 
-static struct sk_buff **ip4ip6_gro_receive(struct sk_buff **head,
-                                          struct sk_buff *skb)
+static struct sk_buff *ip4ip6_gro_receive(struct list_head *head,
+                                         struct sk_buff *skb)
 {
        /* Common GRO receive for SIT and IP6IP6 */
 
index 278e49cd67d4e2c7b0ab9138fabe84753d628b5a..e72947c99454e54fefee30efa8aeea9bc13908b5 100644 (file)
@@ -15,8 +15,8 @@
 #include <net/ip6_checksum.h>
 #include "ip6_offload.h"
 
-static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *tcp6_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        /* Don't bother verifying checksum if we're going to flush anyway. */
        if (!NAPI_GRO_CB(skb)->flush &&
index 03a2ff3fe1e697e752e2aa9f13703b6feaff0453..95dee9ca8d22186486b09ef7514ec69e0985ff3a 100644 (file)
@@ -114,8 +114,8 @@ out:
        return segs;
 }
 
-static struct sk_buff **udp6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
+static struct sk_buff *udp6_gro_receive(struct list_head *head,
+                                       struct sk_buff *skb)
 {
        struct udphdr *uh = udp_gro_udphdr(skb);