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
