summaryrefslogtreecommitdiff
path: root/datapath
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@ovn.org>2016-07-07 21:48:57 -0700
committerPravin B Shelar <pshelar@ovn.org>2016-07-08 19:27:49 -0700
commitcf5789aa4e30d60c6d46c19d9329145d5f795783 (patch)
tree6090344ef26a0e3d881e47f8a7bd8bef515b4c97 /datapath
parentd281b6a9a5e79533042e6647114940ef4ef7d838 (diff)
downloadopenvswitch-cf5789aa4e30d60c6d46c19d9329145d5f795783.tar.gz
datapath: backport: ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb
There is return type change in upstream handle-offload functions. Following patch brings these changes in. This is backport of aed069df ("ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb") I have also removed duplicate definitions of tunnel_handle_offloads() from ip-tunnel header. Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Jesse Gross <jesse@kernel.org>
Diffstat (limited to 'datapath')
-rw-r--r--datapath/linux/compat/geneve.c16
-rw-r--r--datapath/linux/compat/include/net/ip_tunnels.h35
-rw-r--r--datapath/linux/compat/include/net/udp_tunnel.h83
-rw-r--r--datapath/linux/compat/ip_gre.c20
-rw-r--r--datapath/linux/compat/ip_tunnels_core.c19
-rw-r--r--datapath/linux/compat/lisp.c7
-rw-r--r--datapath/linux/compat/vxlan.c21
7 files changed, 106 insertions, 95 deletions
diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 8d25f7a2e..45597002f 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -547,10 +547,8 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
+ GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr)
+ (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
err = skb_cow_head(skb, min_headroom);
- if (unlikely(err)) {
- kfree_skb(skb);
+ if (unlikely(err))
goto free_rt;
- }
skb = vlan_hwaccel_push_inside(skb);
if (!skb) {
@@ -558,11 +556,9 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb,
goto free_rt;
}
- skb = udp_tunnel_handle_offloads(skb, csum, 0, false);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
+ err = udp_tunnel_handle_offloads(skb, csum, false);
+ if (err)
goto free_rt;
- }
gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
gnvh->ver = GENEVE_VER;
gnvh->opt_len = opt_len / 4;
@@ -688,7 +684,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
err = geneve_build_skb(rt, skb, key->tun_flags, vni,
info->options_len, opts, udp_csum);
if (unlikely(err))
- goto err;
+ goto tx_error;
tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
ttl = key->ttl;
@@ -698,7 +694,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
err = geneve_build_skb(rt, skb, 0, geneve->vni,
0, NULL, udp_csum);
if (unlikely(err))
- goto err;
+ goto tx_error;
tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
ttl = geneve->ttl;
@@ -717,7 +713,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
tx_error:
dev_kfree_skb(skb);
-err:
+
if (err == -ELOOP)
dev->stats.collisions++;
else if (err == -ENETUNREACH)
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 26c9041f0..cea75a11c 100644
--- a/datapath/linux/compat/include/net/ip_tunnels.h
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
@@ -31,11 +31,27 @@ static inline int rpl_iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
}
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
-struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
- bool csum_help, int gso_type_mask,
- void (*fix_segment)(struct sk_buff *));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+int ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help, int gso_type_mask,
+ void (*fix_segment)(struct sk_buff *));
+
+/* This is is required to compile upstream gre.h. gre_handle_offloads()
+ * is defined in gre.h and needs iptunnel_handle_offloads(). This provides
+ * default signature for this function.
+ * rpl prefix is to make OVS build happy.
+ */
+#define iptunnel_handle_offloads rpl_iptunnel_handle_offloads
+struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help,
+ int gso_type_mask);
+#else
+
+#define ovs_iptunnel_handle_offloads(skb, csum_help, gso_type_mask, fix_segment) \
+ iptunnel_handle_offloads(skb, gso_type_mask)
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
#define iptunnel_xmit rpl_iptunnel_xmit
int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl,
@@ -43,9 +59,6 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
#else
-#define ovs_iptunnel_handle_offloads(skb, csum_help, gso_type_mask, fix_segment) \
- iptunnel_handle_offloads(skb, csum_help, gso_type_mask)
-
#define rpl_iptunnel_xmit iptunnel_xmit
int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl,
@@ -53,14 +66,6 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
#endif /* 3.18 */
-/* This is not required for OVS on kernel older than 3.18, but gre.h
- * header file needs this declaration for function gre_handle_offloads().
- * So it is defined for all kernel version.
- */
-#define rpl_iptunnel_handle_offloads iptunnel_handle_offloads
-struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
- int gso_type_mask);
-
#ifndef TUNNEL_CSUM
#define TUNNEL_CSUM __cpu_to_be16(0x01)
#define TUNNEL_ROUTING __cpu_to_be16(0x02)
diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h
index 85aed9809..23e66f148 100644
--- a/datapath/linux/compat/include/net/udp_tunnel.h
+++ b/datapath/linux/compat/include/net/udp_tunnel.h
@@ -6,21 +6,10 @@
#include <net/dst_metadata.h>
#include <linux/netdev_features.h>
+
#ifdef HAVE_UDP_TUNNEL_IPV6
#include_next <net/udp_tunnel.h>
-static inline struct sk_buff *
-rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum,
- int type, bool is_vxlan)
-{
- if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
- kfree_skb(skb);
- return ERR_PTR(-ENOSYS);
- }
- return udp_tunnel_handle_offloads(skb, udp_csum);
-}
-#define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads
-
#else
#include <net/ip_tunnels.h>
@@ -84,20 +73,56 @@ int rpl_udp_tunnel_xmit_skb(struct rtable *rt,
#define udp_tunnel_sock_release rpl_udp_tunnel_sock_release
void rpl_udp_tunnel_sock_release(struct socket *sock);
+#define udp_tunnel_encap_enable(sock) udp_encap_enable()
+
+#if IS_ENABLED(CONFIG_IPV6)
+#define udp_tunnel6_xmit_skb rpl_udp_tunnel6_xmit_skb
+int rpl_udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
+ struct sk_buff *skb,
+ struct net_device *dev, struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u8 prio, __u8 ttl, __be16 src_port,
+ __be16 dst_port, bool nocheck);
+#endif
+
+static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff)
+{
+ struct udphdr *uh;
+
+ uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr));
+ skb_shinfo(skb)->gso_type |= uh->check ?
+ SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
+/* this is to handle the return type change in handle-offload
+ * functions.
+ */
+static inline int
+rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum,
+ bool is_vxlan)
+{
+ if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
+ return -ENOSYS;
+ }
+ return udp_tunnel_handle_offloads(skb, udp_csum);
+}
+
+#else
void ovs_udp_gso(struct sk_buff *skb);
void ovs_udp_csum_gso(struct sk_buff *skb);
-#define udp_tunnel_encap_enable(sock) udp_encap_enable()
-static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb,
- bool udp_csum,
- int type,
- bool is_vxlan)
+static inline int rpl_udp_tunnel_handle_offloads(struct sk_buff *skb,
+ bool udp_csum,
+ bool is_vxlan)
{
+ int type = 0;
+
void (*fix_segment)(struct sk_buff *);
if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
- kfree_skb(skb);
- return ERR_PTR(-ENOSYS);
+ return -ENOSYS;
}
type |= udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
@@ -113,27 +138,9 @@ static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb,
return ovs_iptunnel_handle_offloads(skb, udp_csum, type, fix_segment);
}
-
-#if IS_ENABLED(CONFIG_IPV6)
-#define udp_tunnel6_xmit_skb rpl_udp_tunnel6_xmit_skb
-int rpl_udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
- struct sk_buff *skb,
- struct net_device *dev, struct in6_addr *saddr,
- struct in6_addr *daddr,
- __u8 prio, __u8 ttl, __be16 src_port,
- __be16 dst_port, bool nocheck);
-#endif
-
-static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff)
-{
- struct udphdr *uh;
-
- uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr));
- skb_shinfo(skb)->gso_type |= uh->check ?
- SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
-}
#endif
+#define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads
static inline void ovs_udp_tun_rx_dst(struct ip_tunnel_info *info,
struct sk_buff *skb,
unsigned short family,
diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c
index 67db9af73..995f5daad 100644
--- a/datapath/linux/compat/ip_gre.c
+++ b/datapath/linux/compat/ip_gre.c
@@ -171,7 +171,8 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
return 0;
}
-#ifndef HAVE_GRE_HANDLE_OFFLOADS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+/* gre_handle_offloads() has different return type on older kernsl. */
static void gre_nop_fix(struct sk_buff *skb) { }
static void gre_csum_fix(struct sk_buff *skb)
@@ -193,7 +194,7 @@ static bool is_gre_gso(struct sk_buff *skb)
return skb_is_gso(skb);
}
-static struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
+static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
{
int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE;
gso_fix_segment_t fix_segment;
@@ -213,12 +214,11 @@ static bool is_gre_gso(struct sk_buff *skb)
(SKB_GSO_GRE | SKB_GSO_GRE_CSUM);
}
-static struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
+static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
{
- if (skb_is_gso(skb) && skb_is_encapsulated(skb)) {
- kfree_skb(skb);
- return ERR_PTR(-ENOSYS);
- }
+ if (skb_is_gso(skb) && skb_is_encapsulated(skb))
+ return -ENOSYS;
+
#undef gre_handle_offloads
return gre_handle_offloads(skb, gre_csum);
}
@@ -318,11 +318,9 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb)
}
/* Push Tunnel header. */
- skb = rpl_gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM));
- if (IS_ERR(skb)) {
- skb = NULL;
+ err = rpl_gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM));
+ if (err)
goto err_free_rt;
- }
flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB),
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index ee4fadcb5..cb0223ee2 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -86,10 +86,12 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
return pkt_len;
}
EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit);
+#endif
-struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
- bool csum_help, int gso_type_mask,
- void (*fix_segment)(struct sk_buff *))
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
+int ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help, int gso_type_mask,
+ void (*fix_segment)(struct sk_buff *))
{
int err;
@@ -103,17 +105,19 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
goto error;
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
if (gso_type_mask)
fix_segment = NULL;
OVS_GSO_CB(skb)->fix_segment = fix_segment;
+#endif
if (skb_is_gso(skb)) {
err = skb_unclone(skb, GFP_ATOMIC);
if (unlikely(err))
goto error;
skb_shinfo(skb)->gso_type |= gso_type_mask;
- return skb;
+ return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
@@ -133,15 +137,12 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
} else if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_NONE;
- return skb;
+ return 0;
error:
- kfree_skb(skb);
- return ERR_PTR(err);
+ return err;
}
EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads);
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
__be16 inner_proto, bool raw_proto, bool xnet)
{
diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c
index c7260126d..7c1aa3151 100644
--- a/datapath/linux/compat/lisp.c
+++ b/datapath/linux/compat/lisp.c
@@ -344,12 +344,9 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
skb_reset_mac_header(skb);
skb->vlan_tci = 0;
- skb = udp_tunnel_handle_offloads(skb, false, 0, false);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- skb = NULL;
+ err = udp_tunnel_handle_offloads(skb, false, false);
+ if (err)
goto err_free_rt;
- }
src_port = htons(get_src_port(net, skb));
dst_port = lisp_dev->dst_port;
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 4374a3a6b..4e65b4341 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -1030,6 +1030,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
__be16 src_port, __be16 dst_port, __be32 vni,
struct vxlan_metadata *md, bool xnet, u32 vxflags)
{
+ void (*fix_segment)(struct sk_buff *);
struct vxlanhdr *vxh;
int min_headroom;
int err;
@@ -1074,9 +1075,11 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
goto err;
}
- skb = udp_tunnel_handle_offloads(skb, udp_sum, type, true);
- if (IS_ERR(skb)) {
- err = -EINVAL;
+ type |= udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+ fix_segment = udp_sum ? ovs_udp_gso : ovs_udp_csum_gso;
+ err = ovs_iptunnel_handle_offloads(skb, udp_sum, type, fix_segment);
+ if (err) {
+ kfree_skb(skb);
goto err;
}
@@ -1123,6 +1126,7 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
__be16 src_port, __be16 dst_port, __be32 vni,
struct vxlan_metadata *md, bool xnet, u32 vxflags)
{
+ void (*fix_segment)(struct sk_buff *);
struct vxlanhdr *vxh;
int min_headroom;
int err;
@@ -1162,10 +1166,13 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
if (WARN_ON(!skb))
return -ENOMEM;
- skb = udp_tunnel_handle_offloads(skb, udp_sum, type, true);
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
+ type |= udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+ fix_segment = udp_sum ? ovs_udp_gso : ovs_udp_csum_gso;
+ err = ovs_iptunnel_handle_offloads(skb, udp_sum, type, fix_segment);
+ if (err) {
+ kfree_skb(skb);
+ return err;
+ }
vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
vxh->vx_flags = htonl(VXLAN_HF_VNI);
vxh->vx_vni = vni;