openvswitch: Add support for checksums on UDP tunnels.
authorJesse Gross <jesse@nicira.com>
Thu, 29 Jan 2015 00:32:46 +0000 (16:32 -0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 29 Jan 2015 07:04:15 +0000 (23:04 -0800)
Currently, it isn't possible to request checksums on the outer UDP
header of tunnels - the TUNNEL_CSUM flag is ignored. This adds
support for requesting that UDP checksums be computed on transmit
and properly reported if they are present on receive.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/geneve.h
net/ipv4/geneve.c
net/openvswitch/vport-geneve.c
net/openvswitch/vport-vxlan.c

index 03aa2ad..14fb8d3 100644 (file)
@@ -90,7 +90,7 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
                    struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos,
                    __u8 ttl, __be16 df, __be16 src_port, __be16 dst_port,
                    __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
-                   bool xnet);
+                   bool csum, bool xnet);
 #endif /*ifdef CONFIG_INET */
 
 #endif /*ifdef__NET_GENEVE_H */
index 93e5119..5a4828b 100644 (file)
@@ -107,13 +107,13 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
                    struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos,
                    __u8 ttl, __be16 df, __be16 src_port, __be16 dst_port,
                    __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt,
-                   bool xnet)
+                   bool csum, bool xnet)
 {
        struct genevehdr *gnvh;
        int min_headroom;
        int err;
 
-       skb = udp_tunnel_handle_offloads(skb, !gs->sock->sk->sk_no_check_tx);
+       skb = udp_tunnel_handle_offloads(skb, csum);
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
@@ -138,7 +138,7 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
 
        return udp_tunnel_xmit_skb(rt, skb, src, dst,
                                   tos, ttl, df, src_port, dst_port, xnet,
-                                  gs->sock->sk->sk_no_check_tx);
+                                  !csum);
 }
 EXPORT_SYMBOL_GPL(geneve_xmit_skb);
 
index 7ca3d45..bf02fd5 100644 (file)
@@ -212,7 +212,7 @@ static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb)
                              tun_key->ipv4_dst, tun_key->ipv4_tos,
                              tun_key->ipv4_ttl, df, sport, dport,
                              tun_key->tun_flags, vni, opts_len, opts,
-                             false);
+                             !!(tun_key->tun_flags & TUNNEL_CSUM), false);
        if (err < 0)
                ip_rt_put(rt);
        return err;
index 3cc983b..ff07d40 100644 (file)
@@ -74,7 +74,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,
        __be64 key;
        __be16 flags;
 
-       flags = TUNNEL_KEY;
+       flags = TUNNEL_KEY | (udp_hdr(skb)->check != 0 ? TUNNEL_CSUM : 0);
        vxlan_port = vxlan_vport(vport);
        if (vxlan_port->exts & VXLAN_F_GBP)
                flags |= TUNNEL_VXLAN_OPT;
@@ -230,6 +230,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
        __be16 src_port;
        __be16 df;
        int err;
+       u32 vxflags;
 
        if (unlikely(!OVS_CB(skb)->egress_tun_info)) {
                err = -EINVAL;
@@ -251,11 +252,13 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
        src_port = udp_flow_src_port(net, skb, 0, 0, true);
        md.vni = htonl(be64_to_cpu(tun_key->tun_id) << 8);
        md.gbp = vxlan_ext_gbp(skb);
+       vxflags = vxlan_port->exts |
+                     (tun_key->tun_flags & TUNNEL_CSUM ? VXLAN_F_UDP_CSUM : 0);
 
        err = vxlan_xmit_skb(rt, skb, fl.saddr, tun_key->ipv4_dst,
                             tun_key->ipv4_tos, tun_key->ipv4_ttl, df,
                             src_port, dst_port,
-                            &md, false, vxlan_port->exts);
+                            &md, false, vxflags);
        if (err < 0)
                ip_rt_put(rt);
        return err;