net: relax expensive skb_unclone() in iptunnel_handle_offloads()
[cascardo/linux.git] / net / ipv4 / ip_tunnel_core.c
index 6165f30..9118b0e 100644 (file)
@@ -86,15 +86,15 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(iptunnel_xmit);
 
-int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto,
-                        bool xnet)
+int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
+                          __be16 inner_proto, bool raw_proto, bool xnet)
 {
        if (unlikely(!pskb_may_pull(skb, hdr_len)))
                return -ENOMEM;
 
        skb_pull_rcsum(skb, hdr_len);
 
-       if (inner_proto == htons(ETH_P_TEB)) {
+       if (!raw_proto && inner_proto == htons(ETH_P_TEB)) {
                struct ethhdr *eh;
 
                if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
@@ -117,7 +117,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto,
 
        return iptunnel_pull_offloads(skb);
 }
-EXPORT_SYMBOL_GPL(iptunnel_pull_header);
+EXPORT_SYMBOL_GPL(__iptunnel_pull_header);
 
 struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
                                             gfp_t flags)
@@ -146,8 +146,8 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
 }
 EXPORT_SYMBOL_GPL(iptunnel_metadata_reply);
 
-struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb,
-                                        int gso_type_mask)
+int iptunnel_handle_offloads(struct sk_buff *skb,
+                            int gso_type_mask)
 {
        int err;
 
@@ -157,11 +157,11 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb,
        }
 
        if (skb_is_gso(skb)) {
-               err = skb_unclone(skb, GFP_ATOMIC);
+               err = skb_header_unclone(skb, GFP_ATOMIC);
                if (unlikely(err))
-                       goto error;
+                       return err;
                skb_shinfo(skb)->gso_type |= gso_type_mask;
-               return skb;
+               return 0;
        }
 
        if (skb->ip_summed != CHECKSUM_PARTIAL) {
@@ -174,10 +174,7 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb,
                skb->encapsulation = 0;
        }
 
-       return skb;
-error:
-       kfree_skb(skb);
-       return ERR_PTR(err);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
 
@@ -247,10 +244,10 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
                tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]);
 
        if (tb[LWTUNNEL_IP_DST])
-               tun_info->key.u.ipv4.dst = nla_get_be32(tb[LWTUNNEL_IP_DST]);
+               tun_info->key.u.ipv4.dst = nla_get_in_addr(tb[LWTUNNEL_IP_DST]);
 
        if (tb[LWTUNNEL_IP_SRC])
-               tun_info->key.u.ipv4.src = nla_get_be32(tb[LWTUNNEL_IP_SRC]);
+               tun_info->key.u.ipv4.src = nla_get_in_addr(tb[LWTUNNEL_IP_SRC]);
 
        if (tb[LWTUNNEL_IP_TTL])
                tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP_TTL]);
@@ -274,9 +271,10 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,
 {
        struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate);
 
-       if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) ||
-           nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) ||
-           nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) ||
+       if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id,
+                        LWTUNNEL_IP_PAD) ||
+           nla_put_in_addr(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) ||
+           nla_put_in_addr(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) ||
            nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) ||
            nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) ||
            nla_put_be16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags))
@@ -287,7 +285,7 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,
 
 static int ip_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
 {
-       return nla_total_size(8)        /* LWTUNNEL_IP_ID */
+       return nla_total_size_64bit(8)  /* LWTUNNEL_IP_ID */
                + nla_total_size(4)     /* LWTUNNEL_IP_DST */
                + nla_total_size(4)     /* LWTUNNEL_IP_SRC */
                + nla_total_size(1)     /* LWTUNNEL_IP_TOS */
@@ -369,7 +367,8 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb,
 {
        struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate);
 
-       if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) ||
+       if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id,
+                        LWTUNNEL_IP6_PAD) ||
            nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) ||
            nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) ||
            nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.tos) ||
@@ -382,7 +381,7 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb,
 
 static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
 {
-       return nla_total_size(8)        /* LWTUNNEL_IP6_ID */
+       return nla_total_size_64bit(8)  /* LWTUNNEL_IP6_ID */
                + nla_total_size(16)    /* LWTUNNEL_IP6_DST */
                + nla_total_size(16)    /* LWTUNNEL_IP6_SRC */
                + nla_total_size(1)     /* LWTUNNEL_IP6_HOPLIMIT */