From 8abaa53cac82dad5e7f8dba9ef30d785b0a46140 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 20 Oct 2014 16:13:04 -0700 Subject: [PATCH] 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 --- acinclude.m4 | 1 + datapath/actions.c | 2 +- datapath/linux/compat/exthdrs_core.c | 18 ++++++++++-------- datapath/linux/compat/include/net/ipv6.h | 19 ++++++++++++------- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index f0617df1d..3d0eef118 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -364,6 +364,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 00c1fd4b7..a42ad1e10 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -482,7 +482,7 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *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) -- 2.20.1