datapath: Use upstream ipv6_find_hdr().
authorPravin B Shelar <pshelar@nicira.com>
Mon, 20 Oct 2014 23:13:04 +0000 (16:13 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Fri, 24 Oct 2014 02:12:29 +0000 (19:12 -0700)
ipv6_find_hdr() already fixed in newer upstram kernel by Ansis, we
can start using this API safely.
This patch also backports fix (ipv6: ipv6_find_hdr restore prev
functionality) to compat ipv6_find_hdr().

CC: Ansis Atteka <aatteka@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
acinclude.m4
datapath/actions.c
datapath/linux/compat/exthdrs_core.c
datapath/linux/compat/include/net/ipv6.h

index 96b28c0..8d10360 100644 (file)
@@ -320,6 +320,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/net/gre.h], [gre_handle_offloads])
   OVS_GREP_IFELSE([$KSRC/include/net/ip_tunnels.h], [iptunnel_xmit.*net],
                   [OVS_DEFINE([HAVE_IPTUNNEL_XMIT_NET])])
+  OVS_GREP_IFELSE([$KSRC/include/net/ipv6.h], [IP6_FH_F_SKIP_RH])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be16])
   OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be32])
index ddacbc6..a688f19 100644 (file)
@@ -276,7 +276,7 @@ static int set_ipv6(struct sk_buff *skb, const struct ovs_key_ipv6 *ipv6_key)
 
        if (memcmp(ipv6_key->ipv6_dst, daddr, sizeof(ipv6_key->ipv6_dst))) {
                unsigned int offset = 0;
-               int flags = OVS_IP6T_FH_F_SKIP_RH;
+               int flags = IP6_FH_F_SKIP_RH;
                bool recalc_csum = true;
 
                if (ipv6_ext_hdr(nh->nexthdr))
index e2b4a03..29e4e05 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/version.h>
 #include <net/ipv6.h>
 
+#ifndef HAVE_IP6_FH_F_SKIP_RH
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
 int rpl_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
                         u8 *nexthdrp, __be16 *frag_offp)
@@ -68,9 +69,9 @@ int rpl_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
  * isn't NULL.
  *
  * if flags is not NULL and it's a fragment, then the frag flag
- * OVS_IP6T_FH_F_FRAG will be set. If it's an AH header, the
- * OVS_IP6T_FH_F_AUTH flag is set and target < 0, then this function will
- * stop at the AH header. If OVS_IP6T_FH_F_SKIP_RH flag was passed, then this
+ * IP6_FH_F_FRAG will be set. If it's an AH header, the
+ * IP6_FH_F_AUTH flag is set and target < 0, then this function will
+ * stop at the AH header. If IP6_FH_F_SKIP_RH flag was passed, then this
  * function will skip all those routing headers, where segements_left was 0.
  */
 int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
@@ -103,7 +104,7 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                found = (nexthdr == target);
 
                if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
-                       if (target < 0)
+                       if (target < 0 || found)
                                break;
                        return -ENOENT;
                }
@@ -120,7 +121,7 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                        if (rh == NULL)
                                return -EBADMSG;
 
-                       if (flags && (*flags & OVS_IP6T_FH_F_SKIP_RH) &&
+                       if (flags && (*flags & IP6_FH_F_SKIP_RH) &&
                            rh->segments_left == 0)
                                found = false;
                }
@@ -130,7 +131,7 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                        __be16 *fp;
 
                        if (flags)      /* Indicate that this is a fragment */
-                               *flags |= OVS_IP6T_FH_F_FRAG;
+                               *flags |= IP6_FH_F_FRAG;
                        fp = skb_header_pointer(skb,
                                                start+offsetof(struct frag_hdr,
                                                               frag_off),
@@ -152,8 +153,7 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                        }
                        hdrlen = 8;
                } else if (nexthdr == NEXTHDR_AUTH) {
-                       if (flags && (*flags & OVS_IP6T_FH_F_AUTH) &&
-                           (target < 0))
+                       if (flags && (*flags & IP6_FH_F_AUTH) && (target < 0))
                                break;
                        hdrlen = (hp->hdrlen + 2) << 2;
                } else
@@ -169,3 +169,5 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
        *offset = start;
        return nexthdr;
 }
+
+#endif
index eebb1fe..1762a4d 100644 (file)
@@ -9,23 +9,28 @@
 #define NEXTHDR_SCTP    132 /* Stream Control Transport Protocol */
 #endif
 
+#ifndef HAVE_IP6_FH_F_SKIP_RH
+
+enum {
+       IP6_FH_F_FRAG           = (1 << 0),
+       IP6_FH_F_AUTH           = (1 << 1),
+       IP6_FH_F_SKIP_RH        = (1 << 2),
+};
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
 #define ipv6_skip_exthdr rpl_ipv6_skip_exthdr
 extern int ipv6_skip_exthdr(const struct sk_buff *skb, int start,
                            u8 *nexthdrp, __be16 *frag_offp);
 #endif
 
-enum {
-       OVS_IP6T_FH_F_FRAG      = (1 << 0),
-       OVS_IP6T_FH_F_AUTH      = (1 << 1),
-       OVS_IP6T_FH_F_SKIP_RH   = (1 << 2),
-};
-
 /* This function is upstream, but not the version which skips routing
- * headers with 0 segments_left. We plan to propose the extended version. */
+ * headers with 0 segments_left. We fixed it when we introduced
+ * IP6_FH_F_SKIP_RH.
+ */
 #define ipv6_find_hdr rpl_ipv6_find_hdr
 extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                         int target, unsigned short *fragoff, int *fragflg);
+#endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
 static inline u32 ipv6_addr_hash(const struct in6_addr *a)