datapath: backport: tunnel: introduce ipv6_tun_rx_dst()
authorPravin B Shelar <pshelar@ovn.org>
Fri, 8 Jul 2016 04:49:02 +0000 (21:49 -0700)
committerPravin B Shelar <pshelar@ovn.org>
Sat, 9 Jul 2016 02:27:49 +0000 (19:27 -0700)
Update ovs_udp_tun_rx_dst() to handle ipv6 tunnels.

This commit partially backports c29a70d2c ("tunnel: introduce udp_tun_rx_dst()")

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
datapath/linux/compat/include/net/dst_metadata.h
datapath/linux/compat/include/net/udp_tunnel.h

index f15bb03..90230c4 100644 (file)
@@ -5,8 +5,11 @@
 #include_next <net/dst_metadata.h>
 #else
 #include <linux/skbuff.h>
-#include <net/ip_tunnels.h>
+
+#include <net/dsfield.h>
 #include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/ip_tunnels.h>
 
 struct metadata_dst {
        unsigned long dst;
@@ -15,6 +18,23 @@ struct metadata_dst {
        } u;
 };
 
+static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen)
+{
+       unsigned long *dst;
+
+       dst = &md_dst->dst;
+       *dst = 0;
+#if 0
+       dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE,
+                       DST_METADATA | DST_NOCACHE | DST_NOCOUNT);
+
+       dst->input = dst_md_discard;
+       dst->output = dst_md_discard_out;
+#endif
+
+       memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
+}
+
 static inline struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags)
 {
        struct metadata_dst *md_dst;
@@ -23,20 +43,60 @@ static inline struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags)
        if (!md_dst)
                return NULL;
 
+       __metadata_dst_init(md_dst, optslen);
        return md_dst;
 }
+
 #define skb_tunnel_info ovs_skb_tunnel_info
 #endif
+
+static inline void ovs_tun_rx_dst(struct ip_tunnel_info *info, int md_size)
+{
+       /* No need to allocate for OVS backport case. */
+#if 0
+       struct metadata_dst *tun_dst;
+       struct ip_tunnel_info *info;
+
+       tun_dst = metadata_dst_alloc(md_size, GFP_ATOMIC);
+       if (!tun_dst)
+               return NULL;
+#endif
+       info->mode = 0;
+       info->options_len = 0;
+}
+
 static inline void ovs_ip_tun_rx_dst(struct ip_tunnel_info *tun_info,
                                 struct sk_buff *skb, __be16 flags,
                                 __be64 tunnel_id, int md_size)
 {
        const struct iphdr *iph = ip_hdr(skb);
 
+       ovs_tun_rx_dst(tun_info, md_size);
        ip_tunnel_key_init(&tun_info->key,
                           iph->saddr, iph->daddr, iph->tos, iph->ttl,
                           0, 0, tunnel_id, flags);
-       tun_info->mode = 0;
+}
+
+static inline void ovs_ipv6_tun_rx_dst(struct ip_tunnel_info *info,
+                                      struct sk_buff *skb,
+                                      __be16 flags,
+                                      __be64 tunnel_id,
+                                      int md_size)
+{
+       const struct ipv6hdr *ip6h = ipv6_hdr(skb);
+
+       ovs_tun_rx_dst(info, md_size);
+       info->mode = IP_TUNNEL_INFO_IPV6;
+       info->key.tun_flags = flags;
+       info->key.tun_id = tunnel_id;
+       info->key.tp_src = 0;
+       info->key.tp_dst = 0;
+
+       info->key.u.ipv6.src = ip6h->saddr;
+       info->key.u.ipv6.dst = ip6h->daddr;
+
+       info->key.tos = ipv6_get_dsfield(ip6h);
+       info->key.ttl = ip6h->hop_limit;
 }
 
 void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
index 23e66f1..e027508 100644 (file)
@@ -7,7 +7,7 @@
 #include <net/dst_metadata.h>
 #include <linux/netdev_features.h>
 
-#ifdef HAVE_UDP_TUNNEL_IPV6
+#ifdef HAVE_METADATA_DST
 #include_next <net/udp_tunnel.h>
 
 #else
@@ -141,6 +141,7 @@ static inline int rpl_udp_tunnel_handle_offloads(struct sk_buff *skb,
 #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,
@@ -148,6 +149,8 @@ static inline void ovs_udp_tun_rx_dst(struct ip_tunnel_info *info,
 {
        if (family == AF_INET)
                ovs_ip_tun_rx_dst(info, skb, flags, tunnel_id, md_size);
+       else
+               ovs_ipv6_tun_rx_dst(info, skb, flags, tunnel_id, md_size);
 
        info->key.tp_src = udp_hdr(skb)->source;
        info->key.tp_dst = udp_hdr(skb)->dest;