Skip to content

Commit

Permalink
datapath: Use upstream ipv6_find_hdr().
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pravin B Shelar committed Oct 24, 2014
1 parent af465b6 commit 8abaa53
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 16 deletions.
1 change: 1 addition & 0 deletions acinclude.m4
Expand Up @@ -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])
Expand Down
2 changes: 1 addition & 1 deletion datapath/actions.c
Expand Up @@ -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))
Expand Down
18 changes: 10 additions & 8 deletions datapath/linux/compat/exthdrs_core.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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),
Expand All @@ -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
Expand All @@ -169,3 +169,5 @@ int rpl_ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
*offset = start;
return nexthdr;
}

#endif
19 changes: 12 additions & 7 deletions datapath/linux/compat/include/net/ipv6.h
Expand Up @@ -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)
Expand Down

0 comments on commit 8abaa53

Please sign in to comment.