[ovs-dev] [PATCH 1/2] datapath: Rearrange struct sw_flow_key to put IPv4/IPv6-specific details last.

Andrew Evans aevans at nicira.com
Sat Mar 5 03:37:46 UTC 2011


IPv4/IPv6-specific fields are currently scattered about struct
sw_flow_table. Group them together in a union at the end to make it possible to
hash fewer bytes for IPv4 flows.

Suggested-by: Jesse Gross <jesse at nicira.com>
Signed-off-by: Andrew Evans <aevans at nicira.com>
---
 datapath/flow.c |  170 +++++++++++++++++++++++++++++++------------------------
 datapath/flow.h |   52 +++++++++++------
 2 files changed, 130 insertions(+), 92 deletions(-)

diff --git a/datapath/flow.c b/datapath/flow.c
index fe05df3..e3a1a6d 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -118,8 +118,8 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 	payload_ofs = (u8 *)(nh + 1) - skb->data;
 	payload_len = ntohs(nh->payload_len);
 
-	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));
+	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));
 	key->nw_tos = ipv6_get_dsfield(nh) & ~INET_ECN_MASK;
 	key->nw_proto = NEXTHDR_NONE;
 
@@ -326,8 +326,8 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 
 	/* 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. */
-	key->tp_src = htons(icmp->icmp6_type);
-	key->tp_dst = htons(icmp->icmp6_code);
+	key->ipv6.tp.src = htons(icmp->icmp6_type);
+	key->ipv6.tp.dst = htons(icmp->icmp6_code);
 
 	if (!icmp->icmp6_code
 			&& ((icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
@@ -343,7 +343,7 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 			return -ENOMEM;
 
 		nd = (struct nd_msg *)skb_transport_header(skb);
-		memcpy(key->nd_target, &nd->target, sizeof(key->nd_target));
+		memcpy(key->ipv6.nd_target, &nd->target, sizeof(key->ipv6.nd_target));
 
 		icmp_len -= sizeof(*nd);
 		offset = 0;
@@ -359,15 +359,15 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 			 * 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))
+				if (!is_zero_ether_addr(key->ipv6.nd_sha))
 					goto invalid;
-				memcpy(key->arp_sha,
+				memcpy(key->ipv6.nd_sha,
 						&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))
+				if (!is_zero_ether_addr(key->ipv6.nd_tha))
 					goto invalid;
-				memcpy(key->arp_tha,
+				memcpy(key->ipv6.nd_tha,
 						&nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
 			}
 
@@ -379,9 +379,9 @@ 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->arp_sha, 0, sizeof(key->arp_sha));
-	memset(key->arp_tha, 0, sizeof(key->arp_tha));
+	memset(key->ipv6.nd_target, 0, sizeof(key->ipv6.nd_target));
+	memset(key->ipv6.nd_sha, 0, sizeof(key->ipv6.nd_sha));
+	memset(key->ipv6.nd_tha, 0, sizeof(key->ipv6.nd_tha));
 
 	return 0;
 }
@@ -476,8 +476,8 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 		}
 
 		nh = ip_hdr(skb);
-		key->ipv4_src = nh->saddr;
-		key->ipv4_dst = nh->daddr;
+		key->ipv4.src = nh->saddr;
+		key->ipv4.dst = nh->daddr;
 		key->nw_tos = nh->tos & ~INET_ECN_MASK;
 		key->nw_proto = nh->protocol;
 
@@ -487,14 +487,14 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 			if (key->nw_proto == IPPROTO_TCP) {
 				if (tcphdr_ok(skb)) {
 					struct tcphdr *tcp = tcp_hdr(skb);
-					key->tp_src = tcp->source;
-					key->tp_dst = tcp->dest;
+					key->ipv4.tp.src = tcp->source;
+					key->ipv4.tp.dst = tcp->dest;
 				}
 			} else if (key->nw_proto == IPPROTO_UDP) {
 				if (udphdr_ok(skb)) {
 					struct udphdr *udp = udp_hdr(skb);
-					key->tp_src = udp->source;
-					key->tp_dst = udp->dest;
+					key->ipv4.tp.src = udp->source;
+					key->ipv4.tp.dst = udp->dest;
 				}
 			} else if (key->nw_proto == IPPROTO_ICMP) {
 				if (icmphdr_ok(skb)) {
@@ -502,8 +502,8 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 					/* The ICMP type and code fields use the 16-bit
 					 * transport port fields, so we need to store them
 					 * in 16-bit network byte order. */
-					key->tp_src = htons(icmp->type);
-					key->tp_dst = htons(icmp->code);
+					key->ipv4.tp.src = htons(icmp->type);
+					key->ipv4.tp.dst = htons(icmp->code);
 				}
 			}
 		} else
@@ -525,10 +525,10 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 
 			if (key->nw_proto == ARPOP_REQUEST
 					|| key->nw_proto == ARPOP_REPLY) {
-				memcpy(&key->ipv4_src, arp->ar_sip, sizeof(key->ipv4_src));
-				memcpy(&key->ipv4_dst, arp->ar_tip, sizeof(key->ipv4_dst));
-				memcpy(key->arp_sha, arp->ar_sha, ETH_ALEN);
-				memcpy(key->arp_tha, arp->ar_tha, ETH_ALEN);
+				memcpy(&key->ipv4.src, arp->ar_sip, sizeof(key->ipv4.src));
+				memcpy(&key->ipv4.dst, arp->ar_tip, sizeof(key->ipv4.dst));
+				memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+				memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
 			}
 		}
 	} else if (key->dl_type == htons(ETH_P_IPV6)) {
@@ -547,14 +547,14 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 		if (key->nw_proto == NEXTHDR_TCP) {
 			if (tcphdr_ok(skb)) {
 				struct tcphdr *tcp = tcp_hdr(skb);
-				key->tp_src = tcp->source;
-				key->tp_dst = tcp->dest;
+				key->ipv6.tp.src = tcp->source;
+				key->ipv6.tp.dst = tcp->dest;
 			}
 		} else if (key->nw_proto == NEXTHDR_UDP) {
 			if (udphdr_ok(skb)) {
 				struct udphdr *udp = udp_hdr(skb);
-				key->tp_src = udp->source;
-				key->tp_dst = udp->dest;
+				key->ipv6.tp.src = udp->source;
+				key->ipv6.tp.dst = udp->dest;
 			}
 		} else if (key->nw_proto == NEXTHDR_ICMP) {
 			if (icmp6hdr_ok(skb)) {
@@ -675,8 +675,8 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
 			if (swkey->dl_type != htons(ETH_P_IP))
 				return -EINVAL;
 			ipv4_key = nla_data(nla);
-			swkey->ipv4_src = ipv4_key->ipv4_src;
-			swkey->ipv4_dst = ipv4_key->ipv4_dst;
+			swkey->ipv4.src = ipv4_key->ipv4_src;
+			swkey->ipv4.dst = ipv4_key->ipv4_dst;
 			swkey->nw_proto = ipv4_key->ipv4_proto;
 			swkey->nw_tos = ipv4_key->ipv4_tos;
 			if (swkey->nw_tos & INET_ECN_MASK)
@@ -687,10 +687,10 @@ 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,
-					sizeof(swkey->ipv6_src));
-			memcpy(swkey->ipv6_dst, ipv6_key->ipv6_dst,
-					sizeof(swkey->ipv6_dst));
+			memcpy(swkey->ipv6.src, ipv6_key->ipv6_src,
+					sizeof(swkey->ipv6.src));
+			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;
 			if (swkey->nw_tos & INET_ECN_MASK)
@@ -698,61 +698,75 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
 			break;
 
 		case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP):
+			if (swkey->nw_proto != IPPROTO_TCP)
+				return -EINVAL;
+			tcp_key = nla_data(nla);
+			swkey->ipv4.tp.src = tcp_key->tcp_src;
+			swkey->ipv4.tp.dst = tcp_key->tcp_dst;
+			break;
+
 		case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_TCP):
 			if (swkey->nw_proto != IPPROTO_TCP)
 				return -EINVAL;
 			tcp_key = nla_data(nla);
-			swkey->tp_src = tcp_key->tcp_src;
-			swkey->tp_dst = tcp_key->tcp_dst;
+			swkey->ipv6.tp.src = tcp_key->tcp_src;
+			swkey->ipv6.tp.dst = tcp_key->tcp_dst;
 			break;
 
 		case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP):
+			if (swkey->nw_proto != IPPROTO_UDP)
+				return -EINVAL;
+			udp_key = nla_data(nla);
+			swkey->ipv4.tp.src = udp_key->udp_src;
+			swkey->ipv4.tp.dst = udp_key->udp_dst;
+			break;
+
 		case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_UDP):
 			if (swkey->nw_proto != IPPROTO_UDP)
 				return -EINVAL;
 			udp_key = nla_data(nla);
-			swkey->tp_src = udp_key->udp_src;
-			swkey->tp_dst = udp_key->udp_dst;
+			swkey->ipv6.tp.src = udp_key->udp_src;
+			swkey->ipv6.tp.dst = udp_key->udp_dst;
 			break;
 
 		case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP):
 			if (swkey->nw_proto != IPPROTO_ICMP)
 				return -EINVAL;
 			icmp_key = nla_data(nla);
-			swkey->tp_src = htons(icmp_key->icmp_type);
-			swkey->tp_dst = htons(icmp_key->icmp_code);
+			swkey->ipv4.tp.src = htons(icmp_key->icmp_type);
+			swkey->ipv4.tp.dst = htons(icmp_key->icmp_code);
 			break;
 
 		case TRANSITION(ODP_KEY_ATTR_IPV6, ODP_KEY_ATTR_ICMPV6):
 			if (swkey->nw_proto != IPPROTO_ICMPV6)
 				return -EINVAL;
 			icmpv6_key = nla_data(nla);
-			swkey->tp_src = htons(icmpv6_key->icmpv6_type);
-			swkey->tp_dst = htons(icmpv6_key->icmpv6_code);
+			swkey->ipv6.tp.src = htons(icmpv6_key->icmpv6_type);
+			swkey->ipv6.tp.dst = htons(icmpv6_key->icmpv6_code);
 			break;
 
 		case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP):
 			if (swkey->dl_type != htons(ETH_P_ARP))
 				return -EINVAL;
 			arp_key = nla_data(nla);
-			swkey->ipv4_src = arp_key->arp_sip;
-			swkey->ipv4_dst = arp_key->arp_tip;
+			swkey->ipv4.src = arp_key->arp_sip;
+			swkey->ipv4.dst = arp_key->arp_tip;
 			if (arp_key->arp_op & htons(0xff00))
 				return -EINVAL;
 			swkey->nw_proto = ntohs(arp_key->arp_op);
-			memcpy(swkey->arp_sha, arp_key->arp_sha, ETH_ALEN);
-			memcpy(swkey->arp_tha, arp_key->arp_tha, ETH_ALEN);
+			memcpy(swkey->ipv4.arp.sha, arp_key->arp_sha, ETH_ALEN);
+			memcpy(swkey->ipv4.arp.tha, arp_key->arp_tha, ETH_ALEN);
 			break;
 
 		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))
+			if (swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_SOLICITATION)
+					&& swkey->ipv6.tp.src != htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
 				return -EINVAL;
 			nd_key = nla_data(nla);
-			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);
+			memcpy(swkey->ipv6.nd_target, nd_key->nd_target,
+					sizeof(swkey->ipv6.nd_target));
+			memcpy(swkey->ipv6.nd_sha, nd_key->nd_sll, ETH_ALEN);
+			memcpy(swkey->ipv6.nd_tha, nd_key->nd_tll, ETH_ALEN);
 			break;
 
 		default:
@@ -797,8 +811,8 @@ int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr)
 		return 0;
 
 	case ODP_KEY_ATTR_ICMPV6:
-		if (swkey->tp_src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
-		    swkey->tp_src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
+		if (swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_SOLICITATION) ||
+		    swkey->ipv6.tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT))
 			return -EINVAL;
 		return 0;
 
@@ -857,8 +871,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			goto nla_put_failure;
 		ipv4_key = nla_data(nla);
 		memset(ipv4_key, 0, sizeof(struct odp_key_ipv4));
-		ipv4_key->ipv4_src = swkey->ipv4_src;
-		ipv4_key->ipv4_dst = swkey->ipv4_dst;
+		ipv4_key->ipv4_src = swkey->ipv4.src;
+		ipv4_key->ipv4_dst = swkey->ipv4.dst;
 		ipv4_key->ipv4_proto = swkey->nw_proto;
 		ipv4_key->ipv4_tos = swkey->nw_tos;
 	} else if (swkey->dl_type == htons(ETH_P_IPV6)) {
@@ -869,9 +883,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;
@@ -883,11 +897,11 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			goto nla_put_failure;
 		arp_key = nla_data(nla);
 		memset(arp_key, 0, sizeof(struct odp_key_arp));
-		arp_key->arp_sip = swkey->ipv4_src;
-		arp_key->arp_tip = swkey->ipv4_dst;
+		arp_key->arp_sip = swkey->ipv4.src;
+		arp_key->arp_tip = swkey->ipv4.dst;
 		arp_key->arp_op = htons(swkey->nw_proto);
-		memcpy(arp_key->arp_sha, swkey->arp_sha, ETH_ALEN);
-		memcpy(arp_key->arp_tha, swkey->arp_tha, ETH_ALEN);
+		memcpy(arp_key->arp_sha, swkey->ipv4.arp.sha, ETH_ALEN);
+		memcpy(arp_key->arp_tha, swkey->ipv4.arp.tha, ETH_ALEN);
 	}
 
 	if (swkey->dl_type == htons(ETH_P_IP)
@@ -900,8 +914,13 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			if (!nla)
 				goto nla_put_failure;
 			tcp_key = nla_data(nla);
-			tcp_key->tcp_src = swkey->tp_src;
-			tcp_key->tcp_dst = swkey->tp_dst;
+			if (swkey->dl_type == htons(ETH_P_IP)) {
+				tcp_key->tcp_src = swkey->ipv4.tp.src;
+				tcp_key->tcp_dst = swkey->ipv4.tp.dst;
+			} else if (swkey->dl_type == htons(ETH_P_IPV6)) {
+				tcp_key->tcp_src = swkey->ipv6.tp.src;
+				tcp_key->tcp_dst = swkey->ipv6.tp.dst;
+			}
 		} else if (swkey->nw_proto == IPPROTO_UDP) {
 			struct odp_key_udp *udp_key;
 
@@ -909,8 +928,13 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			if (!nla)
 				goto nla_put_failure;
 			udp_key = nla_data(nla);
-			udp_key->udp_src = swkey->tp_src;
-			udp_key->udp_dst = swkey->tp_dst;
+			if (swkey->dl_type == htons(ETH_P_IP)) {
+				udp_key->udp_src = swkey->ipv4.tp.src;
+				udp_key->udp_dst = swkey->ipv4.tp.dst;
+			} else if (swkey->dl_type == htons(ETH_P_IPV6)) {
+				udp_key->udp_src = swkey->ipv6.tp.src;
+				udp_key->udp_dst = swkey->ipv6.tp.dst;
+			}
 		} else if (swkey->dl_type == htons(ETH_P_IP)
 				&& swkey->nw_proto == IPPROTO_ICMP) {
 			struct odp_key_icmp *icmp_key;
@@ -919,8 +943,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			if (!nla)
 				goto nla_put_failure;
 			icmp_key = nla_data(nla);
-			icmp_key->icmp_type = ntohs(swkey->tp_src);
-			icmp_key->icmp_code = ntohs(swkey->tp_dst);
+			icmp_key->icmp_type = ntohs(swkey->ipv4.tp.src);
+			icmp_key->icmp_code = ntohs(swkey->ipv4.tp.dst);
 		} else if (swkey->dl_type == htons(ETH_P_IPV6)
 				&& swkey->nw_proto == IPPROTO_ICMPV6) {
 			struct odp_key_icmpv6 *icmpv6_key;
@@ -929,8 +953,8 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 			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);
+			icmpv6_key->icmpv6_type = ntohs(swkey->ipv6.tp.src);
+			icmpv6_key->icmpv6_code = ntohs(swkey->ipv6.tp.dst);
 
 			if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION
 					|| icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
@@ -940,10 +964,10 @@ int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
 				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->ipv6.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);
+				memcpy(nd_key->nd_sll, swkey->ipv6.nd_sha, ETH_ALEN);
+				memcpy(nd_key->nd_tll, swkey->ipv6.nd_tha, ETH_ALEN);
 			}
 		}
 	}
diff --git a/datapath/flow.h b/datapath/flow.h
index a40073a..4b304d4 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -30,29 +30,43 @@ struct sw_flow_actions {
 };
 
 struct sw_flow_key {
-	__be64	tun_id;     /* Encapsulating tunnel ID. */
+	__be64 tun_id;			/* Encapsulating tunnel ID. */
+	u16    in_port;			/* Input switch port. */
+	__be16 dl_tci;			/* 0 if no VLAN, VLAN_TAG_PRESENT set
+					 * otherwise. */
+	u8     dl_src[ETH_ALEN];	/* Ethernet source address. */
+	u8     dl_dst[ETH_ALEN];	/* Ethernet destination address. */
+	__be16 dl_type;			/* Ethernet frame type. */
+	u8     nw_proto;		/* IP protocol or lower 8 bits of
+					 * ARP opcode. */
+	u8     nw_tos;			/* IP ToS (DSCP field, 6 bits). */
 	union {
 		struct {
-			__be32	ipv4_src;	 /* IPv4 source address. */
-			__be32	ipv4_dst;	 /* IPv4 destination address. */
-		};
+			__be32 src;	/* IP source address. */
+			__be32 dst;	/* IP destination address. */
+			union {
+				struct {
+					__be16 src;	/* TCP/UDP source port. */
+					__be16 dst;	/* TCP/UDP destination port. */
+				} tp;
+				struct {
+					u8 sha[ETH_ALEN];	/* ARP source hardware address. */
+					u8 tha[ETH_ALEN];	/* ARP target hardware address. */
+				} arp;
+			};
+		} ipv4;
 		struct {
-			__be32	ipv6_src[4]; /* IPv6 source address. */
-			__be32	ipv6_dst[4]; /* IPv6 source address. */
-		};
+			__be32 src[4];			/* IPv6 source address. */
+			__be32 dst[4];			/* IPv6 destination address. */
+			struct {
+				__be16 src;		/* TCP/UDP source port. */
+				__be16 dst;		/* TCP/UDP destination port. */
+			} tp;
+			__be32 nd_target[4];		/* ND target address. */
+			u8     nd_sha[ETH_ALEN];	/* ND source hardware address. */
+			u8     nd_tha[ETH_ALEN];	/* ND target hardware address. */
+		} ipv6;
 	};
-	__be32	nd_target[4]; /* 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. */
-	__be16	tp_src;	    /* TCP/UDP source port. */
-	__be16	tp_dst;	    /* TCP/UDP destination port. */
-	u8	dl_src[ETH_ALEN]; /* Ethernet source address. */
-	u8	dl_dst[ETH_ALEN]; /* Ethernet destination address. */
-	u8	nw_proto;   /* IP protocol or lower 8 bits of ARP opcode. */
-	u8	nw_tos;	    /* IP ToS (DSCP field, 6 bits). */
-	u8	arp_sha[ETH_ALEN]; /* ARP/ND source hardware address. */
-	u8	arp_tha[ETH_ALEN]; /* ARP/ND target hardware address. */
 };
 
 struct sw_flow {
-- 
1.7.2.3




More information about the dev mailing list