From: Pravin B Shelar Date: Mon, 20 Oct 2014 23:13:04 +0000 (-0700) Subject: datapath: Use upstream ipv6_find_hdr(). X-Git-Tag: v2.3.1~14 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=7f9d9f27e787943d7d419d6bea184e4c112f0b26 datapath: Use upstream ipv6_find_hdr(). 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 Signed-off-by: Pravin B Shelar Acked-by: Andy Zhou --- diff --git a/acinclude.m4 b/acinclude.m4 index 96b28c06a..8d10360ca 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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]) diff --git a/datapath/actions.c b/datapath/actions.c index ddacbc6a7..a688f1983 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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)) diff --git a/datapath/linux/compat/exthdrs_core.c b/datapath/linux/compat/exthdrs_core.c index e2b4a03cb..29e4e056d 100644 --- a/datapath/linux/compat/exthdrs_core.c +++ b/datapath/linux/compat/exthdrs_core.c @@ -2,6 +2,7 @@ #include #include +#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 diff --git a/datapath/linux/compat/include/net/ipv6.h b/datapath/linux/compat/include/net/ipv6.h index eebb1fe46..1762a4d45 100644 --- a/datapath/linux/compat/include/net/ipv6.h +++ b/datapath/linux/compat/include/net/ipv6.h @@ -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)