diff options
author | Jarno Rajahalme <jrajahalme@nicira.com> | 2014-05-05 12:54:49 -0400 |
---|---|---|
committer | Pravin B Shelar <pshelar@nicira.com> | 2014-05-22 19:27:34 -0400 |
commit | 1139e241ec436b9e9610c7a33ac5c6657f87fda1 (patch) | |
tree | 55695454aef14f07009148a6919b52c04308152a /net/openvswitch | |
parent | 091b64868b43ed84334c6623ea6a08497529d4ff (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.c | 44 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 29 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 112 |
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) | |||
64 | void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) | 64 | void 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 | ||
52 | static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key, | 52 | static 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 | ||
1264 | static int validate_tp_port(const struct sw_flow_key *flow_key) | 1219 | static 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 | } |