[ovs-dev] [PATCH 1/2] datapath: compat: introduce ovs_iptunnel_handle_offloads()
Pravin B Shelar
pshelar at nicira.com
Sat Dec 20 00:24:57 UTC 2014
handle offload code is replicated for different tunneling protocols
define compat function to simplify the code.
Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
datapath/linux/compat/gre.c | 32 +++-----------
datapath/linux/compat/include/net/ip_tunnels.h | 3 +
datapath/linux/compat/ip_tunnels_core.c | 52 ++++++++++++++++++++++++
datapath/linux/compat/vxlan.c | 19 ++------
datapath/vport-geneve.c | 25 +++++-------
datapath/vport-lisp.c | 26 +++++-------
6 files changed, 87 insertions(+), 70 deletions(-)
diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
index 1cd885b..30ee34c 100644
--- a/datapath/linux/compat/gre.c
+++ b/datapath/linux/compat/gre.c
@@ -287,33 +287,15 @@ static void gre_csum_fix(struct sk_buff *skb)
struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
{
- int err;
-
- skb_reset_inner_headers(skb);
+ void (*fix_segment)(struct sk_buff *);
- if (skb_is_gso(skb)) {
- if (skb_is_encapsulated(skb)) {
- err = -ENOSYS;
- goto error;
- }
+ if (gre_csum)
+ fix_segment = gre_csum_fix;
+ else
+ fix_segment = NULL;
- if (gre_csum)
- OVS_GSO_CB(skb)->fix_segment = gre_csum_fix;
- else
- OVS_GSO_CB(skb)->fix_segment = NULL;
- } else {
- if (skb->ip_summed == CHECKSUM_PARTIAL && gre_csum) {
- err = skb_checksum_help(skb);
- if (err)
- goto error;
-
- } else if (skb->ip_summed != CHECKSUM_PARTIAL)
- skb->ip_summed = CHECKSUM_NONE;
- }
- return skb;
-error:
- kfree_skb(skb);
- return ERR_PTR(err);
+ skb_reset_inner_headers(skb);
+ return ovs_iptunnel_handle_offloads(skb, gre_csum, fix_segment);
}
static bool is_gre_gso(struct sk_buff *skb)
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 8fb9527..cd5a9e4 100644
--- a/datapath/linux/compat/include/net/ip_tunnels.h
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
@@ -76,5 +76,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
#define TUNNEL_OPTIONS_PRESENT __cpu_to_be16(0x0800)
bool skb_is_encapsulated(struct sk_buff *skb);
+struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help,
+ void (*fix_segment)(struct sk_buff *));
#endif /* __NET_IP_TUNNELS_H */
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index e71ba4e..7606ad6 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -126,3 +126,55 @@ bool skb_is_encapsulated(struct sk_buff *skb)
/* XXX: set inner protocol for all tunnel in OVS. */
return ovs_skb_get_inner_protocol(skb) || skb_encapsulation(skb);
}
+
+struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+ bool csum_help,
+ void (*fix_segment)(struct sk_buff *))
+{
+ int err;
+
+ if (skb_is_encapsulated(skb)) {
+ err = -ENOSYS;
+ goto error;
+ }
+
+ /* XXX: synchronize inner header for compat and non compat code so that
+ * we can do it here.
+ */
+
+ /* skb_reset_inner_headers(skb); */
+
+ /* OVS compat code does not maintain encapsulation bit.
+ * skb->encapsulation = 1; */
+
+ if (skb_is_gso(skb)) {
+ err = skb_unclone(skb, GFP_ATOMIC);
+ if (unlikely(err))
+ goto error;
+
+ OVS_GSO_CB(skb)->fix_segment = fix_segment;
+ return skb;
+ }
+
+ /* If packet is not gso and we are resolving any partial checksum,
+ * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL
+ * on the outer header without confusing devices that implement
+ * NETIF_F_IP_CSUM with encapsulation.
+ */
+ /*
+ if (csum_help)
+ skb->encapsulation = 0;
+ */
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) {
+ err = skb_checksum_help(skb);
+ if (unlikely(err))
+ goto error;
+ } else if (skb->ip_summed != CHECKSUM_PARTIAL)
+ skb->ip_summed = CHECKSUM_NONE;
+
+ return skb;
+error:
+ kfree_skb(skb);
+ return ERR_PTR(err);
+}
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index ff040ac..76ae552 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -166,18 +166,9 @@ static void vxlan_gso(struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
}
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
- if (skb_is_gso(skb)) {
- if (skb_is_encapsulated(skb))
- return -ENOSYS;
-
- OVS_GSO_CB(skb)->fix_segment = vxlan_gso;
- } else {
- if (skb->ip_summed != CHECKSUM_PARTIAL)
- skb->ip_summed = CHECKSUM_NONE;
- }
- return 0;
+ return ovs_iptunnel_handle_offloads(skb, false, vxlan_gso);
}
int vxlan_xmit_skb(struct vxlan_sock *vs,
@@ -226,9 +217,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
vxlan_set_owner(vs->sock->sk, skb);
- err = handle_offloads(skb);
- if (err)
- return err;
+ skb = handle_offloads(skb);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP,
tos, ttl, df, false);
diff --git a/datapath/vport-geneve.c b/datapath/vport-geneve.c
index 200cc14..6fcf1cc 100644
--- a/datapath/vport-geneve.c
+++ b/datapath/vport-geneve.c
@@ -324,36 +324,29 @@ static void geneve_fix_segment(struct sk_buff *skb)
udph->len = htons(skb->len - skb_transport_offset(skb));
}
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
- if (skb_is_gso(skb)) {
- if (skb_is_encapsulated(skb))
- return -ENOSYS;
- OVS_GSO_CB(skb)->fix_segment = geneve_fix_segment;
- } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
- skb->ip_summed = CHECKSUM_NONE;
- }
- return 0;
+ return ovs_iptunnel_handle_offloads(skb, false, geneve_fix_segment);
}
#else
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
if (skb_is_gso(skb)) {
int err;
if (skb_is_encapsulated(skb))
- return -ENOSYS;
+ return ERR_PTR(-ENOSYS);
err = skb_unclone(skb, GFP_ATOMIC);
if (unlikely(err))
- return err;
+ return ERR_PTR(err);
skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
} else if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_NONE;
skb->encapsulation = 1;
- return 0;
+ return skb;
}
#endif
@@ -420,9 +413,11 @@ static int geneve_send(struct vport *vport, struct sk_buff *skb)
geneve_build_header(vport, skb);
/* Offloading */
- err = handle_offloads(skb);
- if (err)
+ skb = handle_offloads(skb);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
goto err_free_rt;
+ }
df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index a067e05..ce30f69 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -406,37 +406,29 @@ static void lisp_fix_segment(struct sk_buff *skb)
udph->len = htons(skb->len - skb_transport_offset(skb));
}
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
- if (skb_is_gso(skb)) {
- if (skb_is_encapsulated(skb))
- return -ENOSYS;
-
- OVS_GSO_CB(skb)->fix_segment = lisp_fix_segment;
- } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
- skb->ip_summed = CHECKSUM_NONE;
- }
- return 0;
+ return ovs_iptunnel_handle_offloads(skb, false, lisp_fix_segment);
}
#else
-static int handle_offloads(struct sk_buff *skb)
+static struct sk_buff *handle_offloads(struct sk_buff *skb)
{
if (skb_is_gso(skb)) {
int err;
if (skb_is_encapsulated(skb))
- return -ENOSYS;
+ return ERR_PTR(-ENOSYS);
err = skb_unclone(skb, GFP_ATOMIC);
if (unlikely(err))
- return err;
+ return ERR_PTR(err);
skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
} else if (skb->ip_summed != CHECKSUM_PARTIAL)
skb->ip_summed = CHECKSUM_NONE;
skb->encapsulation = 1;
- return 0;
+ return skb;
}
#endif
@@ -500,9 +492,11 @@ static int lisp_send(struct vport *vport, struct sk_buff *skb)
lisp_build_header(vport, skb);
/* Offloading */
- err = handle_offloads(skb);
- if (err)
+ skb = handle_offloads(skb);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
goto err_free_rt;
+ }
skb->ignore_df = 1;
--
1.7.1
More information about the dev
mailing list