These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / ipv4 / fou.c
index 34968cd..bd903fe 100644 (file)
@@ -24,6 +24,7 @@ struct fou {
        u16 type;
        struct udp_offload udp_offloads;
        struct list_head list;
+       struct rcu_head rcu;
 };
 
 #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
@@ -79,7 +80,11 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
        __be16 *pd = data;
        size_t start = ntohs(pd[0]);
        size_t offset = ntohs(pd[1]);
-       size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
+       size_t plen = sizeof(struct udphdr) + hdrlen +
+           max_t(size_t, offset + sizeof(u16), start);
+
+       if (skb->remcsum_offload)
+               return guehdr;
 
        if (!pskb_may_pull(skb, plen))
                return NULL;
@@ -221,29 +226,21 @@ out_unlock:
 
 static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
                                      struct guehdr *guehdr, void *data,
-                                     size_t hdrlen, u8 ipproto,
-                                     struct gro_remcsum *grc, bool nopartial)
+                                     size_t hdrlen, struct gro_remcsum *grc,
+                                     bool nopartial)
 {
        __be16 *pd = data;
        size_t start = ntohs(pd[0]);
        size_t offset = ntohs(pd[1]);
-       size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
 
        if (skb->remcsum_offload)
-               return NULL;
+               return guehdr;
 
        if (!NAPI_GRO_CB(skb)->csum_valid)
                return NULL;
 
-       /* Pull checksum that will be written */
-       if (skb_gro_header_hard(skb, off + plen)) {
-               guehdr = skb_gro_header_slow(skb, off + plen, off);
-               if (!guehdr)
-                       return NULL;
-       }
-
-       skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen,
-                               start, offset, grc, nopartial);
+       guehdr = skb_gro_remcsum_process(skb, (void *)guehdr, off, hdrlen,
+                                        start, offset, grc, nopartial);
 
        skb->remcsum_offload = 1;
 
@@ -307,10 +304,10 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
 
                if (flags & GUE_PFLAG_REMCSUM) {
                        guehdr = gue_gro_remcsum(skb, off, guehdr,
-                                                data + doffset, hdrlen,
-                                                guehdr->proto_ctype, &grc,
+                                                data + doffset, hdrlen, &grc,
                                                 !!(fou->flags &
                                                    FOU_F_REMCSUM_NOPARTIAL));
+
                        if (!guehdr)
                                goto out;
 
@@ -351,7 +348,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
        rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[guehdr->proto_ctype]);
-       if (WARN_ON(!ops || !ops->callbacks.gro_receive))
+       if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
                goto out_unlock;
 
        pp = ops->callbacks.gro_receive(head, skb);
@@ -421,7 +418,7 @@ static void fou_release(struct fou *fou)
        list_del(&fou->list);
        udp_tunnel_sock_release(sock);
 
-       kfree(fou);
+       kfree_rcu(fou, rcu);
 }
 
 static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
@@ -570,7 +567,7 @@ static int parse_nl_config(struct genl_info *info,
        if (info->attrs[FOU_ATTR_AF]) {
                u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]);
 
-               if (family != AF_INET && family != AF_INET6)
+               if (family != AF_INET)
                        return -EINVAL;
 
                cfg->udp_config.family = family;