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 <[email protected]>
Signed-off-by: Andrew Evans <[email protected]>
---
 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

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to