diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/openvswitch/flow.c | 2 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 2 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 31 |
3 files changed, 33 insertions, 2 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index b73c7680a3d2..b409f5279601 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -428,6 +428,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) | |||
428 | struct tcphdr *tcp = tcp_hdr(skb); | 428 | struct tcphdr *tcp = tcp_hdr(skb); |
429 | key->ipv4.tp.src = tcp->source; | 429 | key->ipv4.tp.src = tcp->source; |
430 | key->ipv4.tp.dst = tcp->dest; | 430 | key->ipv4.tp.dst = tcp->dest; |
431 | key->ipv4.tp.flags = TCP_FLAGS_BE16(tcp); | ||
431 | } | 432 | } |
432 | } else if (key->ip.proto == IPPROTO_UDP) { | 433 | } else if (key->ip.proto == IPPROTO_UDP) { |
433 | if (udphdr_ok(skb)) { | 434 | if (udphdr_ok(skb)) { |
@@ -496,6 +497,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key) | |||
496 | struct tcphdr *tcp = tcp_hdr(skb); | 497 | struct tcphdr *tcp = tcp_hdr(skb); |
497 | key->ipv6.tp.src = tcp->source; | 498 | key->ipv6.tp.src = tcp->source; |
498 | key->ipv6.tp.dst = tcp->dest; | 499 | key->ipv6.tp.dst = tcp->dest; |
500 | key->ipv6.tp.flags = TCP_FLAGS_BE16(tcp); | ||
499 | } | 501 | } |
500 | } else if (key->ip.proto == NEXTHDR_UDP) { | 502 | } else if (key->ip.proto == NEXTHDR_UDP) { |
501 | if (udphdr_ok(skb)) { | 503 | if (udphdr_ok(skb)) { |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 204e0ccd116d..1510f51dbf74 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -93,6 +93,7 @@ struct sw_flow_key { | |||
93 | struct { | 93 | struct { |
94 | __be16 src; /* TCP/UDP/SCTP source port. */ | 94 | __be16 src; /* TCP/UDP/SCTP source port. */ |
95 | __be16 dst; /* TCP/UDP/SCTP destination port. */ | 95 | __be16 dst; /* TCP/UDP/SCTP destination port. */ |
96 | __be16 flags; /* TCP flags. */ | ||
96 | } tp; | 97 | } tp; |
97 | struct { | 98 | struct { |
98 | u8 sha[ETH_ALEN]; /* ARP source hardware address. */ | 99 | u8 sha[ETH_ALEN]; /* ARP source hardware address. */ |
@@ -109,6 +110,7 @@ struct sw_flow_key { | |||
109 | struct { | 110 | struct { |
110 | __be16 src; /* TCP/UDP/SCTP source port. */ | 111 | __be16 src; /* TCP/UDP/SCTP source port. */ |
111 | __be16 dst; /* TCP/UDP/SCTP destination port. */ | 112 | __be16 dst; /* TCP/UDP/SCTP destination port. */ |
113 | __be16 flags; /* TCP flags. */ | ||
112 | } tp; | 114 | } tp; |
113 | struct { | 115 | struct { |
114 | struct in6_addr target; /* ND target address. */ | 116 | struct in6_addr target; /* ND target address. */ |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index e04649c56a96..2bc1bc1aca3b 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -114,6 +114,7 @@ static bool match_validate(const struct sw_flow_match *match, | |||
114 | mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4) | 114 | mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4) |
115 | | (1 << OVS_KEY_ATTR_IPV6) | 115 | | (1 << OVS_KEY_ATTR_IPV6) |
116 | | (1 << OVS_KEY_ATTR_TCP) | 116 | | (1 << OVS_KEY_ATTR_TCP) |
117 | | (1 << OVS_KEY_ATTR_TCP_FLAGS) | ||
117 | | (1 << OVS_KEY_ATTR_UDP) | 118 | | (1 << OVS_KEY_ATTR_UDP) |
118 | | (1 << OVS_KEY_ATTR_SCTP) | 119 | | (1 << OVS_KEY_ATTR_SCTP) |
119 | | (1 << OVS_KEY_ATTR_ICMP) | 120 | | (1 << OVS_KEY_ATTR_ICMP) |
@@ -154,8 +155,11 @@ static bool match_validate(const struct sw_flow_match *match, | |||
154 | 155 | ||
155 | if (match->key->ip.proto == IPPROTO_TCP) { | 156 | if (match->key->ip.proto == IPPROTO_TCP) { |
156 | key_expected |= 1 << OVS_KEY_ATTR_TCP; | 157 | key_expected |= 1 << OVS_KEY_ATTR_TCP; |
157 | if (match->mask && (match->mask->key.ip.proto == 0xff)) | 158 | key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS; |
159 | if (match->mask && (match->mask->key.ip.proto == 0xff)) { | ||
158 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP; | 160 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP; |
161 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS; | ||
162 | } | ||
159 | } | 163 | } |
160 | 164 | ||
161 | if (match->key->ip.proto == IPPROTO_ICMP) { | 165 | if (match->key->ip.proto == IPPROTO_ICMP) { |
@@ -186,8 +190,11 @@ static bool match_validate(const struct sw_flow_match *match, | |||
186 | 190 | ||
187 | if (match->key->ip.proto == IPPROTO_TCP) { | 191 | if (match->key->ip.proto == IPPROTO_TCP) { |
188 | key_expected |= 1 << OVS_KEY_ATTR_TCP; | 192 | key_expected |= 1 << OVS_KEY_ATTR_TCP; |
189 | if (match->mask && (match->mask->key.ip.proto == 0xff)) | 193 | key_expected |= 1 << OVS_KEY_ATTR_TCP_FLAGS; |
194 | if (match->mask && (match->mask->key.ip.proto == 0xff)) { | ||
190 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP; | 195 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP; |
196 | mask_allowed |= 1 << OVS_KEY_ATTR_TCP_FLAGS; | ||
197 | } | ||
191 | } | 198 | } |
192 | 199 | ||
193 | if (match->key->ip.proto == IPPROTO_ICMPV6) { | 200 | if (match->key->ip.proto == IPPROTO_ICMPV6) { |
@@ -235,6 +242,7 @@ static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { | |||
235 | [OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4), | 242 | [OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4), |
236 | [OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6), | 243 | [OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6), |
237 | [OVS_KEY_ATTR_TCP] = sizeof(struct ovs_key_tcp), | 244 | [OVS_KEY_ATTR_TCP] = sizeof(struct ovs_key_tcp), |
245 | [OVS_KEY_ATTR_TCP_FLAGS] = sizeof(__be16), | ||
238 | [OVS_KEY_ATTR_UDP] = sizeof(struct ovs_key_udp), | 246 | [OVS_KEY_ATTR_UDP] = sizeof(struct ovs_key_udp), |
239 | [OVS_KEY_ATTR_SCTP] = sizeof(struct ovs_key_sctp), | 247 | [OVS_KEY_ATTR_SCTP] = sizeof(struct ovs_key_sctp), |
240 | [OVS_KEY_ATTR_ICMP] = sizeof(struct ovs_key_icmp), | 248 | [OVS_KEY_ATTR_ICMP] = sizeof(struct ovs_key_icmp), |
@@ -634,6 +642,19 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, | |||
634 | attrs &= ~(1 << OVS_KEY_ATTR_TCP); | 642 | attrs &= ~(1 << OVS_KEY_ATTR_TCP); |
635 | } | 643 | } |
636 | 644 | ||
645 | if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) { | ||
646 | if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) { | ||
647 | SW_FLOW_KEY_PUT(match, ipv4.tp.flags, | ||
648 | nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), | ||
649 | is_mask); | ||
650 | } else { | ||
651 | SW_FLOW_KEY_PUT(match, ipv6.tp.flags, | ||
652 | nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]), | ||
653 | is_mask); | ||
654 | } | ||
655 | attrs &= ~(1 << OVS_KEY_ATTR_TCP_FLAGS); | ||
656 | } | ||
657 | |||
637 | if (attrs & (1 << OVS_KEY_ATTR_UDP)) { | 658 | if (attrs & (1 << OVS_KEY_ATTR_UDP)) { |
638 | const struct ovs_key_udp *udp_key; | 659 | const struct ovs_key_udp *udp_key; |
639 | 660 | ||
@@ -1004,9 +1025,15 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey, | |||
1004 | if (swkey->eth.type == htons(ETH_P_IP)) { | 1025 | if (swkey->eth.type == htons(ETH_P_IP)) { |
1005 | tcp_key->tcp_src = output->ipv4.tp.src; | 1026 | tcp_key->tcp_src = output->ipv4.tp.src; |
1006 | tcp_key->tcp_dst = output->ipv4.tp.dst; | 1027 | tcp_key->tcp_dst = output->ipv4.tp.dst; |
1028 | if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS, | ||
1029 | output->ipv4.tp.flags)) | ||
1030 | goto nla_put_failure; | ||
1007 | } else if (swkey->eth.type == htons(ETH_P_IPV6)) { | 1031 | } else if (swkey->eth.type == htons(ETH_P_IPV6)) { |
1008 | tcp_key->tcp_src = output->ipv6.tp.src; | 1032 | tcp_key->tcp_src = output->ipv6.tp.src; |
1009 | tcp_key->tcp_dst = output->ipv6.tp.dst; | 1033 | tcp_key->tcp_dst = output->ipv6.tp.dst; |
1034 | if (nla_put_be16(skb, OVS_KEY_ATTR_TCP_FLAGS, | ||
1035 | output->ipv6.tp.flags)) | ||
1036 | goto nla_put_failure; | ||
1010 | } | 1037 | } |
1011 | } else if (swkey->ip.proto == IPPROTO_UDP) { | 1038 | } else if (swkey->ip.proto == IPPROTO_UDP) { |
1012 | struct ovs_key_udp *udp_key; | 1039 | struct ovs_key_udp *udp_key; |