[ovs-dev] [PATCH 5/6] datapath: Update IPv6 parsing code for kernel style.

Jesse Gross jesse at nicira.com
Thu Mar 3 03:20:34 UTC 2011


Fixes a number of minor elements in the IPv6 extraction and
parsing code to better conform to kernel style.  Examples include
using kernel types/functions, adding line breaks, and using
unlikely() macros.  There is no functional change.

Signed-off-by: Jesse Gross <jesse at nicira.com>
---
 datapath/flow.c |   86 ++++++++++++++++++++++++++++--------------------------
 datapath/flow.h |    7 ++--
 2 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/datapath/flow.c b/datapath/flow.c
index 9cba723..468172f 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -116,15 +116,15 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 	nexthdr = nh->nexthdr;
 	payload_ofs = (u8 *)(nh + 1) - skb->data;
 
-	memcpy(key->ipv6_src, nh->saddr.in6_u.u6_addr8, sizeof(key->ipv6_src));
-	memcpy(key->ipv6_dst, nh->daddr.in6_u.u6_addr8, sizeof(key->ipv6_dst));
+	ipv6_addr_copy(&key->ipv6_src, &nh->saddr);
+	ipv6_addr_copy(&key->ipv6_dst, &nh->daddr);
 	key->nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
 	key->nw_proto = NEXTHDR_NONE;
 
 	payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr);
-	if (payload_ofs < 0) {
+	if (unlikely(payload_ofs < 0))
 		return -EINVAL;
-	}
+
 	nh_len = payload_ofs - nh_ofs;
 
 	/* Pull enough header bytes to account for the IP header plus the
@@ -304,31 +304,33 @@ static __be16 parse_ethertype(struct sk_buff *skb)
 }
 
 static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
-		int nh_len)
+			int nh_len)
 {
 	struct icmp6hdr *icmp = icmp6_hdr(skb);
 
 	/* The ICMPv6 type and code fields use the 16-bit transport port
-	 * fields, so we need to store them in 16-bit network byte order. */
+	 * fields, so we need to store them in 16-bit network byte order.
+	 */
 	key->tp_src = htons(icmp->icmp6_type);
 	key->tp_dst = htons(icmp->icmp6_code);
 
-	if (!icmp->icmp6_code
-			&& ((icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
-			  || (icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT))) {
+	if (icmp->icmp6_code == 0 &&
+	    ((icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) ||
+	     (icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT))) {
 		int icmp_len = skb->len - skb_transport_offset(skb);
 		struct nd_msg *nd;
 		int offset;
 
 		/* In order to process neighbor discovery options, we need the
-		 * entire packet. */
-		if (icmp_len < sizeof(*nd))
-			goto invalid;
-		if (unlikely(!pskb_may_pull(skb, skb->len)))
+		 * entire packet.
+		 */
+		if (unlikely(icmp_len < sizeof(*nd)))
+			return 0;
+		if (unlikely(skb_linearize(skb)))
 			return -ENOMEM;
 
 		nd = (struct nd_msg *)skb_transport_header(skb);
-		memcpy(key->nd_target, &nd->target, sizeof(key->nd_target));
+		ipv6_addr_copy(&key->nd_target, &nd->target);
 
 		icmp_len -= sizeof(*nd);
 		offset = 0;
@@ -336,24 +338,25 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 			struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd->opt + offset);
 			int opt_len = nd_opt->nd_opt_len * 8;
 
-			if (!opt_len || (opt_len > icmp_len))
+			if (unlikely(!opt_len || (opt_len > icmp_len)))
 				goto invalid;
 
-			/* Store the link layer address if the appropriate option is
-			 * provided.  It is considered an error if the same link
-			 * layer option is specified twice. */
+			/* Store the link layer address if the appropriate
+			 * option is provided.  It is considered an error if
+			 * the same link layer option is specified twice.
+			 */
 			if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR
-					&& opt_len == 8) {
-				if (!is_zero_ether_addr(key->arp_sha))
+			    && opt_len == 8) {
+				if (unlikely(!is_zero_ether_addr(key->arp_sha)))
 					goto invalid;
 				memcpy(key->arp_sha,
-						&nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
+				    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
 			} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR
-					&& opt_len == 8) {
-				if (!is_zero_ether_addr(key->arp_tha))
+				   && opt_len == 8) {
+				if (unlikely(!is_zero_ether_addr(key->arp_tha)))
 					goto invalid;
 				memcpy(key->arp_tha,
-						&nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
+				    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
 			}
 
 			icmp_len -= opt_len;
@@ -364,7 +367,7 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 	return 0;
 
 invalid:
-	memset(key->nd_target, 0, sizeof(key->nd_target));
+	memset(&key->nd_target, 0, sizeof(key->nd_target));
 	memset(key->arp_sha, 0, sizeof(key->arp_sha));
 	memset(key->arp_tha, 0, sizeof(key->arp_tha));
 
@@ -672,9 +675,9 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
 			if (swkey->dl_type != htons(ETH_P_IPV6))
 				return -EINVAL;
 			ipv6_key = nla_data(nla);
-			memcpy(swkey->ipv6_src, ipv6_key->ipv6_src,
+			memcpy(&swkey->ipv6_src, ipv6_key->ipv6_src,
 					sizeof(swkey->ipv6_src));
-			memcpy(swkey->ipv6_dst, ipv6_key->ipv6_dst,
+			memcpy(&swkey->ipv6_dst, ipv6_key->ipv6_dst,
 					sizeof(swkey->ipv6_dst));
 			swkey->nw_proto = ipv6_key->ipv6_proto;
 			swkey->nw_tos = ipv6_key->ipv6_tos;
@@ -731,10 +734,10 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
 
 		case TRANSITION(ODP_KEY_ATTR_ICMPV6, ODP_KEY_ATTR_ND):
 			if (swkey->tp_src != htons(NDISC_NEIGHBOUR_SOLICITATION)
-					&& swkey->tp_src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+			    && swkey->tp_src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
 				return -EINVAL;
 			nd_key = nla_data(nla);
-			memcpy(swkey->nd_target, nd_key->nd_target,
+			memcpy(&swkey->nd_target, nd_key->nd_target,
 					sizeof(swkey->nd_target));
 			memcpy(swkey->arp_sha, nd_key->nd_sll, ETH_ALEN);
 			memcpy(swkey->arp_tha, nd_key->nd_tll, ETH_ALEN);
@@ -854,9 +857,9 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			goto nla_put_failure;
 		ipv6_key = nla_data(nla);
 		memset(ipv6_key, 0, sizeof(struct odp_key_ipv6));
-		memcpy(ipv6_key->ipv6_src, swkey->ipv6_src,
+		memcpy(ipv6_key->ipv6_src, &swkey->ipv6_src,
 				sizeof(ipv6_key->ipv6_src));
-		memcpy(ipv6_key->ipv6_dst, swkey->ipv6_dst,
+		memcpy(ipv6_key->ipv6_dst, &swkey->ipv6_dst,
 				sizeof(ipv6_key->ipv6_dst));
 		ipv6_key->ipv6_proto = swkey->nw_proto;
 		ipv6_key->ipv6_tos = swkey->nw_tos;
@@ -875,8 +878,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 		memcpy(arp_key->arp_tha, swkey->arp_tha, ETH_ALEN);
 	}
 
-	if (swkey->dl_type == htons(ETH_P_IP)
-			|| swkey->dl_type == htons(ETH_P_IPV6)) {
+	if (swkey->dl_type == htons(ETH_P_IP) ||
+	    swkey->dl_type == htons(ETH_P_IPV6)) {
 
 		if (swkey->nw_proto == IPPROTO_TCP) {
 			struct odp_key_tcp *tcp_key;
@@ -896,8 +899,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			udp_key = nla_data(nla);
 			udp_key->udp_src = swkey->tp_src;
 			udp_key->udp_dst = swkey->tp_dst;
-		} else if (swkey->dl_type == htons(ETH_P_IP)
-				&& swkey->nw_proto == IPPROTO_ICMP) {
+		} else if (swkey->dl_type == htons(ETH_P_IP) &&
+			   swkey->nw_proto == IPPROTO_ICMP) {
 			struct odp_key_icmp *icmp_key;
 
 			nla = nla_reserve(skb, ODP_KEY_ATTR_ICMP, sizeof(*icmp_key));
@@ -906,26 +909,27 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			icmp_key = nla_data(nla);
 			icmp_key->icmp_type = ntohs(swkey->tp_src);
 			icmp_key->icmp_code = ntohs(swkey->tp_dst);
-		} else if (swkey->dl_type == htons(ETH_P_IPV6)
-				&& swkey->nw_proto == IPPROTO_ICMPV6) {
+		} else if (swkey->dl_type == htons(ETH_P_IPV6) &&
+			   swkey->nw_proto == IPPROTO_ICMPV6) {
 			struct odp_key_icmpv6 *icmpv6_key;
 
-			nla = nla_reserve(skb, ODP_KEY_ATTR_ICMPV6, sizeof(*icmpv6_key));
+			nla = nla_reserve(skb, ODP_KEY_ATTR_ICMPV6,
+						sizeof(*icmpv6_key));
 			if (!nla)
 				goto nla_put_failure;
 			icmpv6_key = nla_data(nla);
 			icmpv6_key->icmpv6_type = ntohs(swkey->tp_src);
 			icmpv6_key->icmpv6_code = ntohs(swkey->tp_dst);
 
-			if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION
-					|| icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
+			if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
+			    icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
 				struct odp_key_nd *nd_key;
 
 				nla = nla_reserve(skb, ODP_KEY_ATTR_ND, sizeof(*nd_key));
 				if (!nla)
 					goto nla_put_failure;
 				nd_key = nla_data(nla);
-				memcpy(nd_key->nd_target, swkey->nd_target,
+				memcpy(nd_key->nd_target, &swkey->nd_target,
 							sizeof(nd_key->nd_target));
 				memcpy(nd_key->nd_sll, swkey->arp_sha, ETH_ALEN);
 				memcpy(nd_key->nd_tll, swkey->arp_tha, ETH_ALEN);
diff --git a/datapath/flow.h b/datapath/flow.h
index a40073a..5c23279 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/rcupdate.h>
 #include <linux/if_ether.h>
+#include <linux/in6.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
 
@@ -37,11 +38,11 @@ struct sw_flow_key {
 			__be32	ipv4_dst;	 /* IPv4 destination address. */
 		};
 		struct {
-			__be32	ipv6_src[4]; /* IPv6 source address. */
-			__be32	ipv6_dst[4]; /* IPv6 source address. */
+			struct in6_addr	ipv6_src; /* IPv6 source address. */
+			struct in6_addr ipv6_dst; /* IPv6 source address. */
 		};
 	};
-	__be32	nd_target[4]; /* IPv6 ND target address. */
+	struct in6_addr	nd_target; /* IPv6 ND target address. */
 	u16	in_port;    /* Input switch port. */
 	__be16	dl_tci;	    /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
 	__be16	dl_type;    /* Ethernet frame type. */
-- 
1.7.1





More information about the dev mailing list