aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-05-05 12:54:49 -0400
committerPravin B Shelar <pshelar@nicira.com>2014-05-22 19:27:34 -0400
commit1139e241ec436b9e9610c7a33ac5c6657f87fda1 (patch)
tree55695454aef14f07009148a6919b52c04308152a /net/openvswitch
parent091b64868b43ed84334c6623ea6a08497529d4ff (diff)
openvswitch: Compact sw_flow_key.
Minimize padding in sw_flow_key and move 'tp' top the main struct. These changes simplify code when accessing the transport port numbers and the tcp flags, and makes the sw_flow_key 8 bytes smaller on 64-bit systems (128->120 bytes). These changes also make the keys for IPv4 packets to fit in one cache line. There is a valid concern for safety of packing the struct ovs_key_ipv4_tunnel, as it would be possible to take the address of the tun_id member as a __be64 * which could result in unaligned access in some systems. However: - sw_flow_key itself is 64-bit aligned, so the tun_id within is always 64-bit aligned. - We never make arrays of ovs_key_ipv4_tunnel (which would force every second tun_key to be misaligned). - We never take the address of the tun_id in to a __be64 *. - Whereever we use struct ovs_key_ipv4_tunnel outside the sw_flow_key, it is in stack (on tunnel input functions), where compiler has full control of the alignment. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/flow.c44
-rw-r--r--net/openvswitch/flow.h29
-rw-r--r--net/openvswitch/flow_netlink.c112
3 files changed, 62 insertions, 123 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index e0fc12bbeeb1..6d8d2da0a8ec 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -64,17 +64,11 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
64void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) 64void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
65{ 65{
66 struct flow_stats *stats; 66 struct flow_stats *stats;
67 __be16 tcp_flags = 0; 67 __be16 tcp_flags = flow->key.tp.flags;
68 int node = numa_node_id(); 68 int node = numa_node_id();
69 69
70 stats = rcu_dereference(flow->stats[node]); 70 stats = rcu_dereference(flow->stats[node]);
71 71
72 if (likely(flow->key.ip.proto == IPPROTO_TCP)) {
73 if (likely(flow->key.eth.type == htons(ETH_P_IP)))
74 tcp_flags = flow->key.ipv4.tp.flags;
75 else if (likely(flow->key.eth.type == htons(ETH_P_IPV6)))
76 tcp_flags = flow->key.ipv6.tp.flags;
77 }
78 /* Check if already have node-specific stats. */ 72 /* Check if already have node-specific stats. */
79 if (likely(stats)) { 73 if (likely(stats)) {
80 spin_lock(&stats->lock); 74 spin_lock(&stats->lock);
@@ -357,8 +351,8 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
357 /* The ICMPv6 type and code fields use the 16-bit transport port 351 /* The ICMPv6 type and code fields use the 16-bit transport port
358 * fields, so we need to store them in 16-bit network byte order. 352 * fields, so we need to store them in 16-bit network byte order.
359 */ 353 */
360 key->ipv6.tp.src = htons(icmp->icmp6_type); 354 key->tp.src = htons(icmp->icmp6_type);
361 key->ipv6.tp.dst = htons(icmp->icmp6_code); 355 key->tp.dst = htons(icmp->icmp6_code);
362 356
363 if (icmp->icmp6_code == 0 && 357 if (icmp->icmp6_code == 0 &&
364 (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION || 358 (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
@@ -520,21 +514,21 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
520 if (key->ip.proto == IPPROTO_TCP) { 514 if (key->ip.proto == IPPROTO_TCP) {
521 if (tcphdr_ok(skb)) { 515 if (tcphdr_ok(skb)) {
522 struct tcphdr *tcp = tcp_hdr(skb); 516 struct tcphdr *tcp = tcp_hdr(skb);
523 key->ipv4.tp.src = tcp->source; 517 key->tp.src = tcp->source;
524 key->ipv4.tp.dst = tcp->dest; 518 key->tp.dst = tcp->dest;
525 key->ipv4.tp.flags = TCP_FLAGS_BE16(tcp); 519 key->tp.flags = TCP_FLAGS_BE16(tcp);
526 } 520 }
527 } else if (key->ip.proto == IPPROTO_UDP) { 521 } else if (key->ip.proto == IPPROTO_UDP) {
528 if (udphdr_ok(skb)) { 522 if (udphdr_ok(skb)) {
529 struct udphdr *udp = udp_hdr(skb); 523 struct udphdr *udp = udp_hdr(skb);
530 key->ipv4.tp.src = udp->source; 524 key->tp.src = udp->source;
531 key->ipv4.tp.dst = udp->dest; 525 key->tp.dst = udp->dest;
532 } 526 }
533 } else if (key->ip.proto == IPPROTO_SCTP) { 527 } else if (key->ip.proto == IPPROTO_SCTP) {
534 if (sctphdr_ok(skb)) { 528 if (sctphdr_ok(skb)) {
535 struct sctphdr *sctp = sctp_hdr(skb); 529 struct sctphdr *sctp = sctp_hdr(skb);
536 key->ipv4.tp.src = sctp->source; 530 key->tp.src = sctp->source;
537 key->ipv4.tp.dst = sctp->dest; 531 key->tp.dst = sctp->dest;
538 } 532 }
539 } else if (key->ip.proto == IPPROTO_ICMP) { 533 } else if (key->ip.proto == IPPROTO_ICMP) {
540 if (icmphdr_ok(skb)) { 534 if (icmphdr_ok(skb)) {
@@ -542,8 +536,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
542 /* The ICMP type and code fields use the 16-bit 536 /* The ICMP type and code fields use the 16-bit
543 * transport port fields, so we need to store 537 * transport port fields, so we need to store
544 * them in 16-bit network byte order. */ 538 * them in 16-bit network byte order. */
545 key->ipv4.tp.src = htons(icmp->type); 539 key->tp.src = htons(icmp->type);
546 key->ipv4.tp.dst = htons(icmp->code); 540 key->tp.dst = htons(icmp->code);
547 } 541 }
548 } 542 }
549 543
@@ -589,21 +583,21 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
589 if (key->ip.proto == NEXTHDR_TCP) { 583 if (key->ip.proto == NEXTHDR_TCP) {
590 if (tcphdr_ok(skb)) { 584 if (tcphdr_ok(skb)) {
591 struct tcphdr *tcp = tcp_hdr(skb); 585 struct tcphdr *tcp = tcp_hdr(skb);
592 key->ipv6.tp.src = tcp->source; 586 key->tp.src = tcp->source;
593 key->ipv6.tp.dst = tcp->dest; 587 key->tp.dst = tcp->dest;
594 key->ipv6.tp.flags = TCP_FLAGS_BE16(tcp); 588 key->tp.flags = TCP_FLAGS_BE16(tcp);
595 } 589 }
596 } else if (key->ip.proto == NEXTHDR_UDP) { 590 } else if (key->ip.proto == NEXTHDR_UDP) {
597 if (udphdr_ok(skb)) { 591 if (udphdr_ok(skb)) {
598 struct udphdr *udp = udp_hdr(skb); 592 struct udphdr *udp = udp_hdr(skb);
599 key->ipv6.tp.src = udp->source; 593 key->tp.src = udp->source;
600 key->ipv6.tp.dst = udp->dest; 594 key->tp.dst = udp->dest;
601 } 595 }
602 } else if (key->ip.proto == NEXTHDR_SCTP) { 596 } else if (key->ip.proto == NEXTHDR_SCTP) {
603 if (sctphdr_ok(skb)) { 597 if (sctphdr_ok(skb)) {
604 struct sctphdr *sctp = sctp_hdr(skb); 598 struct sctphdr *sctp = sctp_hdr(skb);
605 key->ipv6.tp.src = sctp->source; 599 key->tp.src = sctp->source;
606 key->ipv6.tp.dst = sctp->dest; 600 key->tp.dst = sctp->dest;
607 } 601 }
608 } else if (key->ip.proto == NEXTHDR_ICMP) { 602 } else if (key->ip.proto == NEXTHDR_ICMP) {
609 if (icmp6hdr_ok(skb)) { 603 if (icmp6hdr_ok(skb)) {
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index ddcebc53224f..a292bf8ad75c 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -47,7 +47,7 @@ struct ovs_key_ipv4_tunnel {
47 __be16 tun_flags; 47 __be16 tun_flags;
48 u8 ipv4_tos; 48 u8 ipv4_tos;
49 u8 ipv4_ttl; 49 u8 ipv4_ttl;
50}; 50} __packed __aligned(4); /* Minimize padding. */
51 51
52static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key, 52static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key,
53 const struct iphdr *iph, __be64 tun_id, 53 const struct iphdr *iph, __be64 tun_id,
@@ -71,7 +71,7 @@ struct sw_flow_key {
71 u32 priority; /* Packet QoS priority. */ 71 u32 priority; /* Packet QoS priority. */
72 u32 skb_mark; /* SKB mark. */ 72 u32 skb_mark; /* SKB mark. */
73 u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ 73 u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
74 } phy; 74 } __packed phy; /* Safe when right after 'tun_key'. */
75 struct { 75 struct {
76 u8 src[ETH_ALEN]; /* Ethernet source address. */ 76 u8 src[ETH_ALEN]; /* Ethernet source address. */
77 u8 dst[ETH_ALEN]; /* Ethernet destination address. */ 77 u8 dst[ETH_ALEN]; /* Ethernet destination address. */
@@ -84,23 +84,21 @@ struct sw_flow_key {
84 u8 ttl; /* IP TTL/hop limit. */ 84 u8 ttl; /* IP TTL/hop limit. */
85 u8 frag; /* One of OVS_FRAG_TYPE_*. */ 85 u8 frag; /* One of OVS_FRAG_TYPE_*. */
86 } ip; 86 } ip;
87 struct {
88 __be16 src; /* TCP/UDP/SCTP source port. */
89 __be16 dst; /* TCP/UDP/SCTP destination port. */
90 __be16 flags; /* TCP flags. */
91 } tp;
87 union { 92 union {
88 struct { 93 struct {
89 struct { 94 struct {
90 __be32 src; /* IP source address. */ 95 __be32 src; /* IP source address. */
91 __be32 dst; /* IP destination address. */ 96 __be32 dst; /* IP destination address. */
92 } addr; 97 } addr;
93 union { 98 struct {
94 struct { 99 u8 sha[ETH_ALEN]; /* ARP source hardware address. */
95 __be16 src; /* TCP/UDP/SCTP source port. */ 100 u8 tha[ETH_ALEN]; /* ARP target hardware address. */
96 __be16 dst; /* TCP/UDP/SCTP destination port. */ 101 } arp;
97 __be16 flags; /* TCP flags. */
98 } tp;
99 struct {
100 u8 sha[ETH_ALEN]; /* ARP source hardware address. */
101 u8 tha[ETH_ALEN]; /* ARP target hardware address. */
102 } arp;
103 };
104 } ipv4; 102 } ipv4;
105 struct { 103 struct {
106 struct { 104 struct {
@@ -109,11 +107,6 @@ struct sw_flow_key {
109 } addr; 107 } addr;
110 __be32 label; /* IPv6 flow label. */ 108 __be32 label; /* IPv6 flow label. */
111 struct { 109 struct {
112 __be16 src; /* TCP/UDP/SCTP source port. */
113 __be16 dst; /* TCP/UDP/SCTP destination port. */
114 __be16 flags; /* TCP flags. */
115 } tp;
116 struct {
117 struct in6_addr target; /* ND target address. */ 110 struct in6_addr target; /* ND target address. */
118 u8 sll[ETH_ALEN]; /* ND source link layer address. */ 111 u8 sll[ETH_ALEN]; /* ND source link layer address. */
119 u8 tll[ETH_ALEN]; /* ND target link layer address. */ 112 u8 tll[ETH_ALEN]; /* ND target link layer address. */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 32a725cfeb0e..d757848da89c 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -204,11 +204,11 @@ static bool match_validate(const struct sw_flow_match *match,
204 if (match->mask && (match->mask->key.ip.proto == 0xff)) 204 if (match->mask && (match->mask->key.ip.proto == 0xff))
205 mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6; 205 mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6;
206 206
207 if (match->key->ipv6.tp.src == 207 if (match->key->tp.src ==
208 htons(NDISC_NEIGHBOUR_SOLICITATION) || 208 htons(NDISC_NEIGHBOUR_SOLICITATION) ||
209 match->key->ipv6.tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) { 209 match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
210 key_expected |= 1 << OVS_KEY_ATTR_ND; 210 key_expected |= 1 << OVS_KEY_ATTR_ND;
211 if (match->mask && (match->mask->key.ipv6.tp.src == htons(0xffff))) 211 if (match->mask && (match->mask->key.tp.src == htons(0xffff)))
212 mask_allowed |= 1 << OVS_KEY_ATTR_ND; 212 mask_allowed |= 1 << OVS_KEY_ATTR_ND;
213 } 213 }
214 } 214 }
@@ -630,27 +630,18 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
630 const struct ovs_key_tcp *tcp_key; 630 const struct ovs_key_tcp *tcp_key;
631 631
632 tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]); 632 tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]);
633 if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) { 633 SW_FLOW_KEY_PUT(match, tp.src, tcp_key->tcp_src, is_mask);
634 SW_FLOW_KEY_PUT(match, ipv4.tp.src, 634 SW_FLOW_KEY_PUT(match, tp.dst, tcp_key->tcp_dst, is_mask);
635 tcp_key->tcp_src, is_mask);
636 SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
637 tcp_key->tcp_dst, is_mask);
638 } else {
639 SW_FLOW_KEY_PUT(match, ipv6.tp.src,
640 tcp_key->tcp_src, is_mask);
641 SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
642 tcp_key->tcp_dst, is_mask);
643 }
644 attrs &= ~(1 << OVS_KEY_ATTR_TCP); 635 attrs &= ~(1 << OVS_KEY_ATTR_TCP);
645 } 636 }
646 637
647 if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) { 638 if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
648 if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) { 639 if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) {
649 SW_FLOW_KEY_PUT(match, ipv4.tp.flags, 640 SW_FLOW_KEY_PUT(match, tp.flags,
650 nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), 641 nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
651 is_mask); 642 is_mask);
652 } else { 643 } else {
653 SW_FLOW_KEY_PUT(match, ipv6.tp.flags, 644 SW_FLOW_KEY_PUT(match, tp.flags,
654 nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), 645 nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
655 is_mask); 646 is_mask);
656 } 647 }
@@ -661,17 +652,8 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
661 const struct ovs_key_udp *udp_key; 652 const struct ovs_key_udp *udp_key;
662 653
663 udp_key = nla_data(a[OVS_KEY_ATTR_UDP]); 654 udp_key = nla_data(a[OVS_KEY_ATTR_UDP]);
664 if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) { 655 SW_FLOW_KEY_PUT(match, tp.src, udp_key->udp_src, is_mask);
665 SW_FLOW_KEY_PUT(match, ipv4.tp.src, 656 SW_FLOW_KEY_PUT(match, tp.dst, udp_key->udp_dst, is_mask);
666 udp_key->udp_src, is_mask);
667 SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
668 udp_key->udp_dst, is_mask);
669 } else {
670 SW_FLOW_KEY_PUT(match, ipv6.tp.src,
671 udp_key->udp_src, is_mask);
672 SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
673 udp_key->udp_dst, is_mask);
674 }
675 attrs &= ~(1 << OVS_KEY_ATTR_UDP); 657 attrs &= ~(1 << OVS_KEY_ATTR_UDP);
676 } 658 }
677 659
@@ -679,17 +661,8 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
679 const struct ovs_key_sctp *sctp_key; 661 const struct ovs_key_sctp *sctp_key;
680 662
681 sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]); 663 sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]);
682 if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) { 664 SW_FLOW_KEY_PUT(match, tp.src, sctp_key->sctp_src, is_mask);
683 SW_FLOW_KEY_PUT(match, ipv4.tp.src, 665 SW_FLOW_KEY_PUT(match, tp.dst, sctp_key->sctp_dst, is_mask);
684 sctp_key->sctp_src, is_mask);
685 SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
686 sctp_key->sctp_dst, is_mask);
687 } else {
688 SW_FLOW_KEY_PUT(match, ipv6.tp.src,
689 sctp_key->sctp_src, is_mask);
690 SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
691 sctp_key->sctp_dst, is_mask);
692 }
693 attrs &= ~(1 << OVS_KEY_ATTR_SCTP); 666 attrs &= ~(1 << OVS_KEY_ATTR_SCTP);
694 } 667 }
695 668
@@ -697,9 +670,9 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
697 const struct ovs_key_icmp *icmp_key; 670 const struct ovs_key_icmp *icmp_key;
698 671
699 icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]); 672 icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]);
700 SW_FLOW_KEY_PUT(match, ipv4.tp.src, 673 SW_FLOW_KEY_PUT(match, tp.src,
701 htons(icmp_key->icmp_type), is_mask); 674 htons(icmp_key->icmp_type), is_mask);
702 SW_FLOW_KEY_PUT(match, ipv4.tp.dst, 675 SW_FLOW_KEY_PUT(match, tp.dst,
703 htons(icmp_key->icmp_code), is_mask); 676 htons(icmp_key->icmp_code), is_mask);
704 attrs &= ~(1 << OVS_KEY_ATTR_ICMP); 677 attrs &= ~(1 << OVS_KEY_ATTR_ICMP);
705 } 678 }
@@ -708,9 +681,9 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
708 const struct ovs_key_icmpv6 *icmpv6_key; 681 const struct ovs_key_icmpv6 *icmpv6_key;
709 682
710 icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]); 683 icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]);
711 SW_FLOW_KEY_PUT(match, ipv6.tp.src, 684 SW_FLOW_KEY_PUT(match, tp.src,
712 htons(icmpv6_key->icmpv6_type), is_mask); 685 htons(icmpv6_key->icmpv6_type), is_mask);
713 SW_FLOW_KEY_PUT(match, ipv6.tp.dst, 686 SW_FLOW_KEY_PUT(match, tp.dst,
714 htons(icmpv6_key->icmpv6_code), is_mask); 687 htons(icmpv6_key->icmpv6_code), is_mask);
715 attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6); 688 attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6);
716 } 689 }
@@ -1024,19 +997,11 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
1024 if (!nla) 997 if (!nla)
1025 goto nla_put_failure; 998 goto nla_put_failure;
1026 tcp_key = nla_data(nla); 999 tcp_key = nla_data(nla);
1027 if (swkey->eth.type == htons(ETH_P_IP)) { 1000 tcp_key->tcp_src = output->tp.src;
1028 tcp_key->tcp_src = output->ipv4.tp.src; 1001 tcp_key->tcp_dst = output->tp.dst;
1029 tcp_key->tcp_dst = output->ipv4.tp.dst; 1002 if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS,
1030 if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS, 1003 output->tp.flags))
1031 output->ipv4.tp.flags)) 1004 goto nla_put_failure;
1032 goto nla_put_failure;
1033 } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
1034 tcp_key->tcp_src = output->ipv6.tp.src;
1035 tcp_key->tcp_dst = output->ipv6.tp.dst;
1036 if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS,
1037 output->ipv6.tp.flags))
1038 goto nla_put_failure;
1039 }
1040 } else if (swkey->ip.proto == IPPROTO_UDP) { 1005 } else if (swkey->ip.proto == IPPROTO_UDP) {
1041 struct ovs_key_udp *udp_key; 1006 struct ovs_key_udp *udp_key;
1042 1007
@@ -1044,13 +1009,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
1044 if (!nla) 1009 if (!nla)
1045 goto nla_put_failure; 1010 goto nla_put_failure;
1046 udp_key = nla_data(nla); 1011 udp_key = nla_data(nla);
1047 if (swkey->eth.type == htons(ETH_P_IP)) { 1012 udp_key->udp_src = output->tp.src;
1048 udp_key->udp_src = output->ipv4.tp.src; 1013 udp_key->udp_dst = output->tp.dst;
1049 udp_key->udp_dst = output->ipv4.tp.dst;
1050 } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
1051 udp_key->udp_src = output->ipv6.tp.src;
1052 udp_key->udp_dst = output->ipv6.tp.dst;
1053 }
1054 } else if (swkey->ip.proto == IPPROTO_SCTP) { 1014 } else if (swkey->ip.proto == IPPROTO_SCTP) {
1055 struct ovs_key_sctp *sctp_key; 1015 struct ovs_key_sctp *sctp_key;
1056 1016
@@ -1058,13 +1018,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
1058 if (!nla) 1018 if (!nla)
1059 goto nla_put_failure; 1019 goto nla_put_failure;
1060 sctp_key = nla_data(nla); 1020 sctp_key = nla_data(nla);
1061 if (swkey->eth.type == htons(ETH_P_IP)) { 1021 sctp_key->sctp_src = output->tp.src;
1062 sctp_key->sctp_src = output->ipv4.tp.src; 1022 sctp_key->sctp_dst = output->tp.dst;
1063 sctp_key->sctp_dst = output->ipv4.tp.dst;
1064 } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
1065 sctp_key->sctp_src = output->ipv6.tp.src;
1066 sctp_key->sctp_dst = output->ipv6.tp.dst;
1067 }
1068 } else if (swkey->eth.type == htons(ETH_P_IP) && 1023 } else if (swkey->eth.type == htons(ETH_P_IP) &&
1069 swkey->ip.proto == IPPROTO_ICMP) { 1024 swkey->ip.proto == IPPROTO_ICMP) {
1070 struct ovs_key_icmp *icmp_key; 1025 struct ovs_key_icmp *icmp_key;
@@ -1073,8 +1028,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
1073 if (!nla) 1028 if (!nla)
1074 goto nla_put_failure; 1029 goto nla_put_failure;
1075 icmp_key = nla_data(nla); 1030 icmp_key = nla_data(nla);
1076 icmp_key->icmp_type = ntohs(output->ipv4.tp.src); 1031 icmp_key->icmp_type = ntohs(output->tp.src);
1077 icmp_key->icmp_code = ntohs(output->ipv4.tp.dst); 1032 icmp_key->icmp_code = ntohs(output->tp.dst);
1078 } else if (swkey->eth.type == htons(ETH_P_IPV6) && 1033 } else if (swkey->eth.type == htons(ETH_P_IPV6) &&
1079 swkey->ip.proto == IPPROTO_ICMPV6) { 1034 swkey->ip.proto == IPPROTO_ICMPV6) {
1080 struct ovs_key_icmpv6 *icmpv6_key; 1035 struct ovs_key_icmpv6 *icmpv6_key;
@@ -1084,8 +1039,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
1084 if (!nla) 1039 if (!nla)
1085 goto nla_put_failure; 1040 goto nla_put_failure;
1086 icmpv6_key = nla_data(nla); 1041 icmpv6_key = nla_data(nla);
1087 icmpv6_key->icmpv6_type = ntohs(output->ipv6.tp.src); 1042 icmpv6_key->icmpv6_type = ntohs(output->tp.src);
1088 icmpv6_key->icmpv6_code = ntohs(output->ipv6.tp.dst); 1043 icmpv6_key->icmpv6_code = ntohs(output->tp.dst);
1089 1044
1090 if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION || 1045 if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
1091 icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { 1046 icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
@@ -1263,13 +1218,10 @@ static int validate_and_copy_sample(const struct nlattr *attr,
1263 1218
1264static int validate_tp_port(const struct sw_flow_key *flow_key) 1219static int validate_tp_port(const struct sw_flow_key *flow_key)
1265{ 1220{
1266 if (flow_key->eth.type == htons(ETH_P_IP)) { 1221 if ((flow_key->eth.type == htons(ETH_P_IP) ||
1267 if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst) 1222 flow_key->eth.type == htons(ETH_P_IPV6)) &&
1268 return 0; 1223 (flow_key->tp.src || flow_key->tp.dst))
1269 } else if (flow_key->eth.type == htons(ETH_P_IPV6)) { 1224 return 0;
1270 if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst)
1271 return 0;
1272 }
1273 1225
1274 return -EINVAL; 1226 return -EINVAL;
1275} 1227}