]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
e0edde6f | 2 | * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | #include <config.h> | |
17 | #include <sys/types.h> | |
18 | #include "flow.h" | |
db7f8281 | 19 | #include <assert.h> |
d31f1109 | 20 | #include <errno.h> |
064af421 BP |
21 | #include <inttypes.h> |
22 | #include <netinet/in.h> | |
d31f1109 JP |
23 | #include <netinet/icmp6.h> |
24 | #include <netinet/ip6.h> | |
064af421 BP |
25 | #include <stdlib.h> |
26 | #include <string.h> | |
10a24935 | 27 | #include "byte-order.h" |
064af421 BP |
28 | #include "coverage.h" |
29 | #include "dynamic-string.h" | |
30 | #include "hash.h" | |
31 | #include "ofpbuf.h" | |
32 | #include "openflow/openflow.h" | |
064af421 | 33 | #include "packets.h" |
176aaa65 | 34 | #include "unaligned.h" |
5136ce49 | 35 | #include "vlog.h" |
064af421 | 36 | |
d98e6007 | 37 | VLOG_DEFINE_THIS_MODULE(flow); |
064af421 | 38 | |
d76f09ea BP |
39 | COVERAGE_DEFINE(flow_extract); |
40 | ||
a26ef517 JP |
41 | static struct arp_eth_header * |
42 | pull_arp(struct ofpbuf *packet) | |
43 | { | |
44 | return ofpbuf_try_pull(packet, ARP_ETH_HEADER_LEN); | |
45 | } | |
46 | ||
064af421 BP |
47 | static struct ip_header * |
48 | pull_ip(struct ofpbuf *packet) | |
49 | { | |
50 | if (packet->size >= IP_HEADER_LEN) { | |
51 | struct ip_header *ip = packet->data; | |
52 | int ip_len = IP_IHL(ip->ip_ihl_ver) * 4; | |
53 | if (ip_len >= IP_HEADER_LEN && packet->size >= ip_len) { | |
54 | return ofpbuf_pull(packet, ip_len); | |
55 | } | |
56 | } | |
57 | return NULL; | |
58 | } | |
59 | ||
60 | static struct tcp_header * | |
d295e8e9 | 61 | pull_tcp(struct ofpbuf *packet) |
064af421 BP |
62 | { |
63 | if (packet->size >= TCP_HEADER_LEN) { | |
64 | struct tcp_header *tcp = packet->data; | |
65 | int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; | |
66 | if (tcp_len >= TCP_HEADER_LEN && packet->size >= tcp_len) { | |
67 | return ofpbuf_pull(packet, tcp_len); | |
68 | } | |
69 | } | |
70 | return NULL; | |
71 | } | |
72 | ||
73 | static struct udp_header * | |
d295e8e9 | 74 | pull_udp(struct ofpbuf *packet) |
064af421 BP |
75 | { |
76 | return ofpbuf_try_pull(packet, UDP_HEADER_LEN); | |
77 | } | |
78 | ||
79 | static struct icmp_header * | |
d295e8e9 | 80 | pull_icmp(struct ofpbuf *packet) |
064af421 BP |
81 | { |
82 | return ofpbuf_try_pull(packet, ICMP_HEADER_LEN); | |
83 | } | |
84 | ||
d31f1109 JP |
85 | static struct icmp6_hdr * |
86 | pull_icmpv6(struct ofpbuf *packet) | |
87 | { | |
88 | return ofpbuf_try_pull(packet, sizeof(struct icmp6_hdr)); | |
89 | } | |
90 | ||
50f06e16 | 91 | static void |
ae412e7d | 92 | parse_vlan(struct ofpbuf *b, struct flow *flow) |
064af421 | 93 | { |
50f06e16 | 94 | struct qtag_prefix { |
0b3e77bb BP |
95 | ovs_be16 eth_type; /* ETH_TYPE_VLAN */ |
96 | ovs_be16 tci; | |
50f06e16 BP |
97 | }; |
98 | ||
0b3e77bb | 99 | if (b->size >= sizeof(struct qtag_prefix) + sizeof(ovs_be16)) { |
50f06e16 | 100 | struct qtag_prefix *qp = ofpbuf_pull(b, sizeof *qp); |
66642cb4 | 101 | flow->vlan_tci = qp->tci | htons(VLAN_CFI); |
50f06e16 | 102 | } |
064af421 BP |
103 | } |
104 | ||
0b3e77bb | 105 | static ovs_be16 |
50f06e16 | 106 | parse_ethertype(struct ofpbuf *b) |
064af421 | 107 | { |
50f06e16 | 108 | struct llc_snap_header *llc; |
0b3e77bb | 109 | ovs_be16 proto; |
50f06e16 | 110 | |
0b3e77bb | 111 | proto = *(ovs_be16 *) ofpbuf_pull(b, sizeof proto); |
36956a7d | 112 | if (ntohs(proto) >= ETH_TYPE_MIN) { |
50f06e16 BP |
113 | return proto; |
114 | } | |
115 | ||
116 | if (b->size < sizeof *llc) { | |
36956a7d | 117 | return htons(FLOW_DL_TYPE_NONE); |
50f06e16 BP |
118 | } |
119 | ||
120 | llc = b->data; | |
121 | if (llc->llc.llc_dsap != LLC_DSAP_SNAP | |
122 | || llc->llc.llc_ssap != LLC_SSAP_SNAP | |
123 | || llc->llc.llc_cntl != LLC_CNTL_SNAP | |
124 | || memcmp(llc->snap.snap_org, SNAP_ORG_ETHERNET, | |
125 | sizeof llc->snap.snap_org)) { | |
36956a7d | 126 | return htons(FLOW_DL_TYPE_NONE); |
50f06e16 BP |
127 | } |
128 | ||
129 | ofpbuf_pull(b, sizeof *llc); | |
130 | return llc->snap.snap_type; | |
064af421 BP |
131 | } |
132 | ||
d31f1109 JP |
133 | static int |
134 | parse_ipv6(struct ofpbuf *packet, struct flow *flow) | |
135 | { | |
88366484 | 136 | const struct ip6_hdr *nh; |
d31f1109 JP |
137 | ovs_be32 tc_flow; |
138 | int nexthdr; | |
139 | ||
88366484 JG |
140 | nh = ofpbuf_try_pull(packet, sizeof *nh); |
141 | if (!nh) { | |
142 | return EINVAL; | |
d31f1109 JP |
143 | } |
144 | ||
d31f1109 | 145 | nexthdr = nh->ip6_nxt; |
d31f1109 JP |
146 | |
147 | flow->ipv6_src = nh->ip6_src; | |
148 | flow->ipv6_dst = nh->ip6_dst; | |
149 | ||
150 | tc_flow = get_unaligned_be32(&nh->ip6_flow); | |
25cfd5ca | 151 | flow->nw_tos = ntohl(tc_flow) >> 20; |
fa8223b7 | 152 | flow->ipv6_label = tc_flow & htonl(IPV6_LABEL_MASK); |
a61680c6 | 153 | flow->nw_ttl = nh->ip6_hlim; |
d31f1109 JP |
154 | flow->nw_proto = IPPROTO_NONE; |
155 | ||
d31f1109 JP |
156 | while (1) { |
157 | if ((nexthdr != IPPROTO_HOPOPTS) | |
158 | && (nexthdr != IPPROTO_ROUTING) | |
159 | && (nexthdr != IPPROTO_DSTOPTS) | |
160 | && (nexthdr != IPPROTO_AH) | |
161 | && (nexthdr != IPPROTO_FRAGMENT)) { | |
162 | /* It's either a terminal header (e.g., TCP, UDP) or one we | |
163 | * don't understand. In either case, we're done with the | |
164 | * packet, so use it to fill in 'nw_proto'. */ | |
165 | break; | |
166 | } | |
167 | ||
168 | /* We only verify that at least 8 bytes of the next header are | |
169 | * available, but many of these headers are longer. Ensure that | |
170 | * accesses within the extension header are within those first 8 | |
88366484 | 171 | * bytes. All extension headers are required to be at least 8 |
d31f1109 | 172 | * bytes. */ |
88366484 JG |
173 | if (packet->size < 8) { |
174 | return EINVAL; | |
d31f1109 JP |
175 | } |
176 | ||
177 | if ((nexthdr == IPPROTO_HOPOPTS) | |
178 | || (nexthdr == IPPROTO_ROUTING) | |
179 | || (nexthdr == IPPROTO_DSTOPTS)) { | |
180 | /* These headers, while different, have the fields we care about | |
181 | * in the same location and with the same interpretation. */ | |
88366484 | 182 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data; |
d31f1109 | 183 | nexthdr = ext_hdr->ip6e_nxt; |
88366484 JG |
184 | if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 1) * 8)) { |
185 | return EINVAL; | |
186 | } | |
d31f1109 JP |
187 | } else if (nexthdr == IPPROTO_AH) { |
188 | /* A standard AH definition isn't available, but the fields | |
189 | * we care about are in the same location as the generic | |
190 | * option header--only the header length is calculated | |
191 | * differently. */ | |
88366484 | 192 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data; |
d31f1109 | 193 | nexthdr = ext_hdr->ip6e_nxt; |
88366484 JG |
194 | if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 2) * 4)) { |
195 | return EINVAL; | |
196 | } | |
d31f1109 | 197 | } else if (nexthdr == IPPROTO_FRAGMENT) { |
88366484 | 198 | const struct ip6_frag *frag_hdr = (struct ip6_frag *)packet->data; |
d31f1109 JP |
199 | |
200 | nexthdr = frag_hdr->ip6f_nxt; | |
88366484 JG |
201 | if (!ofpbuf_try_pull(packet, sizeof *frag_hdr)) { |
202 | return EINVAL; | |
203 | } | |
d31f1109 JP |
204 | |
205 | /* We only process the first fragment. */ | |
0fd0d083 JG |
206 | if (frag_hdr->ip6f_offlg != htons(0)) { |
207 | if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) == htons(0)) { | |
208 | flow->nw_frag = FLOW_NW_FRAG_ANY; | |
209 | } else { | |
210 | flow->nw_frag |= FLOW_NW_FRAG_LATER; | |
211 | nexthdr = IPPROTO_FRAGMENT; | |
212 | break; | |
213 | } | |
d31f1109 JP |
214 | } |
215 | } | |
216 | } | |
217 | ||
d31f1109 | 218 | flow->nw_proto = nexthdr; |
88366484 | 219 | return 0; |
d31f1109 JP |
220 | } |
221 | ||
88366484 JG |
222 | static void |
223 | parse_tcp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow) | |
224 | { | |
225 | const struct tcp_header *tcp = pull_tcp(b); | |
226 | if (tcp) { | |
227 | flow->tp_src = tcp->tcp_src; | |
228 | flow->tp_dst = tcp->tcp_dst; | |
229 | packet->l7 = b->data; | |
230 | } | |
231 | } | |
232 | ||
233 | static void | |
234 | parse_udp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow) | |
235 | { | |
236 | const struct udp_header *udp = pull_udp(b); | |
237 | if (udp) { | |
238 | flow->tp_src = udp->udp_src; | |
239 | flow->tp_dst = udp->udp_dst; | |
240 | packet->l7 = b->data; | |
241 | } | |
242 | } | |
685a51a5 JP |
243 | |
244 | static bool | |
88366484 | 245 | parse_icmpv6(struct ofpbuf *b, struct flow *flow) |
685a51a5 JP |
246 | { |
247 | const struct icmp6_hdr *icmp = pull_icmpv6(b); | |
248 | ||
249 | if (!icmp) { | |
250 | return false; | |
251 | } | |
252 | ||
253 | /* The ICMPv6 type and code fields use the 16-bit transport port | |
254 | * fields, so we need to store them in 16-bit network byte order. */ | |
3ee8a9f0 BP |
255 | flow->tp_src = htons(icmp->icmp6_type); |
256 | flow->tp_dst = htons(icmp->icmp6_code); | |
685a51a5 | 257 | |
88366484 JG |
258 | if (icmp->icmp6_code == 0 && |
259 | (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT || | |
260 | icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) { | |
261 | const struct in6_addr *nd_target; | |
685a51a5 | 262 | |
88366484 JG |
263 | nd_target = ofpbuf_try_pull(b, sizeof *nd_target); |
264 | if (!nd_target) { | |
685a51a5 JP |
265 | return false; |
266 | } | |
88366484 | 267 | flow->nd_target = *nd_target; |
685a51a5 | 268 | |
88366484 | 269 | while (b->size >= 8) { |
685a51a5 JP |
270 | /* The minimum size of an option is 8 bytes, which also is |
271 | * the size of Ethernet link-layer options. */ | |
88366484 JG |
272 | const struct nd_opt_hdr *nd_opt = b->data; |
273 | int opt_len = nd_opt->nd_opt_len * 8; | |
274 | ||
275 | if (!opt_len || opt_len > b->size) { | |
685a51a5 JP |
276 | goto invalid; |
277 | } | |
685a51a5 JP |
278 | |
279 | /* Store the link layer address if the appropriate option is | |
280 | * provided. It is considered an error if the same link | |
281 | * layer option is specified twice. */ | |
282 | if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR | |
283 | && opt_len == 8) { | |
284 | if (eth_addr_is_zero(flow->arp_sha)) { | |
88366484 | 285 | memcpy(flow->arp_sha, nd_opt + 1, ETH_ADDR_LEN); |
685a51a5 JP |
286 | } else { |
287 | goto invalid; | |
288 | } | |
289 | } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR | |
290 | && opt_len == 8) { | |
291 | if (eth_addr_is_zero(flow->arp_tha)) { | |
88366484 | 292 | memcpy(flow->arp_tha, nd_opt + 1, ETH_ADDR_LEN); |
685a51a5 JP |
293 | } else { |
294 | goto invalid; | |
295 | } | |
296 | } | |
297 | ||
88366484 | 298 | if (!ofpbuf_try_pull(b, opt_len)) { |
685a51a5 JP |
299 | goto invalid; |
300 | } | |
685a51a5 JP |
301 | } |
302 | } | |
303 | ||
304 | return true; | |
305 | ||
306 | invalid: | |
88366484 JG |
307 | memset(&flow->nd_target, 0, sizeof(flow->nd_target)); |
308 | memset(flow->arp_sha, 0, sizeof(flow->arp_sha)); | |
309 | memset(flow->arp_tha, 0, sizeof(flow->arp_tha)); | |
685a51a5 JP |
310 | |
311 | return false; | |
312 | ||
313 | } | |
314 | ||
deedf7e7 BP |
315 | /* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and |
316 | * 'ofp_in_port'. | |
317 | * | |
0b3e77bb | 318 | * Initializes 'packet' header pointers as follows: |
ca78c6b6 BP |
319 | * |
320 | * - packet->l2 to the start of the Ethernet header. | |
321 | * | |
322 | * - packet->l3 to just past the Ethernet header, or just past the | |
323 | * vlan_header if one is present, to the first byte of the payload of the | |
324 | * Ethernet frame. | |
325 | * | |
326 | * - packet->l4 to just past the IPv4 header, if one is present and has a | |
327 | * correct length, and otherwise NULL. | |
328 | * | |
329 | * - packet->l7 to just past the TCP or UDP or ICMP header, if one is | |
330 | * present and has a correct length, and otherwise NULL. | |
331 | */ | |
7257b535 | 332 | void |
deedf7e7 | 333 | flow_extract(struct ofpbuf *packet, uint32_t skb_priority, ovs_be64 tun_id, |
abff858b | 334 | uint16_t ofp_in_port, struct flow *flow) |
064af421 BP |
335 | { |
336 | struct ofpbuf b = *packet; | |
337 | struct eth_header *eth; | |
064af421 BP |
338 | |
339 | COVERAGE_INC(flow_extract); | |
340 | ||
341 | memset(flow, 0, sizeof *flow); | |
659586ef | 342 | flow->tun_id = tun_id; |
abe529af | 343 | flow->in_port = ofp_in_port; |
deedf7e7 | 344 | flow->skb_priority = skb_priority; |
064af421 BP |
345 | |
346 | packet->l2 = b.data; | |
347 | packet->l3 = NULL; | |
348 | packet->l4 = NULL; | |
349 | packet->l7 = NULL; | |
350 | ||
50f06e16 | 351 | if (b.size < sizeof *eth) { |
7257b535 | 352 | return; |
50f06e16 | 353 | } |
064af421 | 354 | |
50f06e16 BP |
355 | /* Link layer. */ |
356 | eth = b.data; | |
357 | memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN); | |
358 | memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN); | |
359 | ||
66642cb4 | 360 | /* dl_type, vlan_tci. */ |
50f06e16 BP |
361 | ofpbuf_pull(&b, ETH_ADDR_LEN * 2); |
362 | if (eth->eth_type == htons(ETH_TYPE_VLAN)) { | |
363 | parse_vlan(&b, flow); | |
364 | } | |
365 | flow->dl_type = parse_ethertype(&b); | |
366 | ||
367 | /* Network layer. */ | |
368 | packet->l3 = b.data; | |
369 | if (flow->dl_type == htons(ETH_TYPE_IP)) { | |
370 | const struct ip_header *nh = pull_ip(&b); | |
371 | if (nh) { | |
7257b535 BP |
372 | packet->l4 = b.data; |
373 | ||
9ea5d2d5 BP |
374 | flow->nw_src = get_unaligned_be32(&nh->ip_src); |
375 | flow->nw_dst = get_unaligned_be32(&nh->ip_dst); | |
50f06e16 | 376 | flow->nw_proto = nh->ip_proto; |
7257b535 | 377 | |
eadef313 | 378 | flow->nw_tos = nh->ip_tos; |
7257b535 | 379 | if (IP_IS_FRAGMENT(nh->ip_frag_off)) { |
eadef313 | 380 | flow->nw_frag = FLOW_NW_FRAG_ANY; |
7257b535 | 381 | if (nh->ip_frag_off & htons(IP_FRAG_OFF_MASK)) { |
eadef313 | 382 | flow->nw_frag |= FLOW_NW_FRAG_LATER; |
7257b535 BP |
383 | } |
384 | } | |
a61680c6 | 385 | flow->nw_ttl = nh->ip_ttl; |
7257b535 BP |
386 | |
387 | if (!(nh->ip_frag_off & htons(IP_FRAG_OFF_MASK))) { | |
6767a2cc | 388 | if (flow->nw_proto == IPPROTO_TCP) { |
88366484 | 389 | parse_tcp(packet, &b, flow); |
6767a2cc | 390 | } else if (flow->nw_proto == IPPROTO_UDP) { |
88366484 | 391 | parse_udp(packet, &b, flow); |
6767a2cc | 392 | } else if (flow->nw_proto == IPPROTO_ICMP) { |
50f06e16 BP |
393 | const struct icmp_header *icmp = pull_icmp(&b); |
394 | if (icmp) { | |
3ee8a9f0 BP |
395 | flow->tp_src = htons(icmp->icmp_type); |
396 | flow->tp_dst = htons(icmp->icmp_code); | |
50f06e16 | 397 | packet->l7 = b.data; |
064af421 | 398 | } |
064af421 | 399 | } |
50f06e16 BP |
400 | } |
401 | } | |
d31f1109 | 402 | } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { |
7257b535 BP |
403 | if (parse_ipv6(&b, flow)) { |
404 | return; | |
d31f1109 JP |
405 | } |
406 | ||
88366484 JG |
407 | packet->l4 = b.data; |
408 | if (flow->nw_proto == IPPROTO_TCP) { | |
409 | parse_tcp(packet, &b, flow); | |
410 | } else if (flow->nw_proto == IPPROTO_UDP) { | |
411 | parse_udp(packet, &b, flow); | |
412 | } else if (flow->nw_proto == IPPROTO_ICMPV6) { | |
413 | if (parse_icmpv6(&b, flow)) { | |
414 | packet->l7 = b.data; | |
d31f1109 JP |
415 | } |
416 | } | |
50f06e16 BP |
417 | } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { |
418 | const struct arp_eth_header *arp = pull_arp(&b); | |
419 | if (arp && arp->ar_hrd == htons(1) | |
d295e8e9 | 420 | && arp->ar_pro == htons(ETH_TYPE_IP) |
50f06e16 BP |
421 | && arp->ar_hln == ETH_ADDR_LEN |
422 | && arp->ar_pln == 4) { | |
423 | /* We only match on the lower 8 bits of the opcode. */ | |
424 | if (ntohs(arp->ar_op) <= 0xff) { | |
425 | flow->nw_proto = ntohs(arp->ar_op); | |
064af421 | 426 | } |
a26ef517 | 427 | |
d295e8e9 | 428 | if ((flow->nw_proto == ARP_OP_REQUEST) |
50f06e16 BP |
429 | || (flow->nw_proto == ARP_OP_REPLY)) { |
430 | flow->nw_src = arp->ar_spa; | |
431 | flow->nw_dst = arp->ar_tpa; | |
bad68a99 JP |
432 | memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN); |
433 | memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN); | |
a26ef517 | 434 | } |
064af421 BP |
435 | } |
436 | } | |
064af421 BP |
437 | } |
438 | ||
993410fb BP |
439 | /* For every bit of a field that is wildcarded in 'wildcards', sets the |
440 | * corresponding bit in 'flow' to zero. */ | |
441 | void | |
442 | flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards) | |
443 | { | |
444 | const flow_wildcards_t wc = wildcards->wildcards; | |
445 | int i; | |
446 | ||
e878338b | 447 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
993410fb BP |
448 | |
449 | for (i = 0; i < FLOW_N_REGS; i++) { | |
450 | flow->regs[i] &= wildcards->reg_masks[i]; | |
451 | } | |
452 | flow->tun_id &= wildcards->tun_id_mask; | |
969fc56c | 453 | flow->metadata &= wildcards->metadata_mask; |
993410fb BP |
454 | flow->nw_src &= wildcards->nw_src_mask; |
455 | flow->nw_dst &= wildcards->nw_dst_mask; | |
456 | if (wc & FWW_IN_PORT) { | |
457 | flow->in_port = 0; | |
458 | } | |
459 | flow->vlan_tci &= wildcards->vlan_tci_mask; | |
460 | if (wc & FWW_DL_TYPE) { | |
cb9457e2 | 461 | flow->dl_type = htons(0); |
993410fb | 462 | } |
73f33563 BP |
463 | flow->tp_src &= wildcards->tp_src_mask; |
464 | flow->tp_dst &= wildcards->tp_dst_mask; | |
73c0ce34 JS |
465 | eth_addr_bitand(flow->dl_src, wildcards->dl_src_mask, flow->dl_src); |
466 | eth_addr_bitand(flow->dl_dst, wildcards->dl_dst_mask, flow->dl_dst); | |
993410fb BP |
467 | if (wc & FWW_NW_PROTO) { |
468 | flow->nw_proto = 0; | |
469 | } | |
32455024 | 470 | flow->ipv6_label &= wildcards->ipv6_label_mask; |
2486e66a JP |
471 | if (wc & FWW_NW_DSCP) { |
472 | flow->nw_tos &= ~IP_DSCP_MASK; | |
473 | } | |
474 | if (wc & FWW_NW_ECN) { | |
475 | flow->nw_tos &= ~IP_ECN_MASK; | |
476 | } | |
a61680c6 JP |
477 | if (wc & FWW_NW_TTL) { |
478 | flow->nw_ttl = 0; | |
479 | } | |
eadef313 | 480 | flow->nw_frag &= wildcards->nw_frag_mask; |
e878338b SH |
481 | eth_addr_bitand(flow->arp_sha, wildcards->arp_sha_mask, flow->arp_sha); |
482 | eth_addr_bitand(flow->arp_tha, wildcards->arp_tha_mask, flow->arp_tha); | |
993410fb BP |
483 | flow->ipv6_src = ipv6_addr_bitand(&flow->ipv6_src, |
484 | &wildcards->ipv6_src_mask); | |
485 | flow->ipv6_dst = ipv6_addr_bitand(&flow->ipv6_dst, | |
486 | &wildcards->ipv6_dst_mask); | |
47284b1f AA |
487 | flow->nd_target = ipv6_addr_bitand(&flow->nd_target, |
488 | &wildcards->nd_target_mask); | |
deedf7e7 | 489 | flow->skb_priority = 0; |
993410fb BP |
490 | } |
491 | ||
5d6c3af0 EJ |
492 | /* Initializes 'fmd' with the metadata found in 'flow'. */ |
493 | void | |
494 | flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd) | |
495 | { | |
e878338b | 496 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
e9358af6 | 497 | |
5d6c3af0 EJ |
498 | fmd->tun_id = flow->tun_id; |
499 | fmd->tun_id_mask = htonll(UINT64_MAX); | |
500 | ||
969fc56c JS |
501 | fmd->metadata = flow->metadata; |
502 | fmd->metadata_mask = htonll(UINT64_MAX); | |
503 | ||
5d6c3af0 EJ |
504 | memcpy(fmd->regs, flow->regs, sizeof fmd->regs); |
505 | memset(fmd->reg_masks, 0xff, sizeof fmd->reg_masks); | |
506 | ||
507 | fmd->in_port = flow->in_port; | |
508 | } | |
509 | ||
064af421 | 510 | char * |
ae412e7d | 511 | flow_to_string(const struct flow *flow) |
064af421 BP |
512 | { |
513 | struct ds ds = DS_EMPTY_INITIALIZER; | |
514 | flow_format(&ds, flow); | |
515 | return ds_cstr(&ds); | |
516 | } | |
517 | ||
518 | void | |
ae412e7d | 519 | flow_format(struct ds *ds, const struct flow *flow) |
064af421 | 520 | { |
2bcf7df6 EJ |
521 | ds_put_format(ds, "priority:%"PRIu32 |
522 | ",tunnel:%#"PRIx64 | |
969fc56c | 523 | ",metadata:%#"PRIx64 |
2bcf7df6 | 524 | ",in_port:%04"PRIx16, |
deedf7e7 | 525 | flow->skb_priority, |
abff858b | 526 | ntohll(flow->tun_id), |
969fc56c | 527 | ntohll(flow->metadata), |
abff858b PS |
528 | flow->in_port); |
529 | ||
2bcf7df6 | 530 | ds_put_format(ds, ",tci("); |
66642cb4 | 531 | if (flow->vlan_tci) { |
2bcf7df6 | 532 | ds_put_format(ds, "vlan:%"PRIu16",pcp:%d", |
66642cb4 BP |
533 | vlan_tci_to_vid(flow->vlan_tci), |
534 | vlan_tci_to_pcp(flow->vlan_tci)); | |
535 | } else { | |
536 | ds_put_char(ds, '0'); | |
537 | } | |
2bcf7df6 EJ |
538 | ds_put_format(ds, ") mac("ETH_ADDR_FMT"->"ETH_ADDR_FMT |
539 | ") type:%04"PRIx16, | |
659586ef JG |
540 | ETH_ADDR_ARGS(flow->dl_src), |
541 | ETH_ADDR_ARGS(flow->dl_dst), | |
d31f1109 JP |
542 | ntohs(flow->dl_type)); |
543 | ||
544 | if (flow->dl_type == htons(ETH_TYPE_IPV6)) { | |
2bcf7df6 EJ |
545 | ds_put_format(ds, " label:%#"PRIx32" proto:%"PRIu8" tos:%#"PRIx8 |
546 | " ttl:%"PRIu8" ipv6(", | |
a61680c6 | 547 | ntohl(flow->ipv6_label), flow->nw_proto, |
eadef313 | 548 | flow->nw_tos, flow->nw_ttl); |
d31f1109 JP |
549 | print_ipv6_addr(ds, &flow->ipv6_src); |
550 | ds_put_cstr(ds, "->"); | |
551 | print_ipv6_addr(ds, &flow->ipv6_dst); | |
2bcf7df6 | 552 | ds_put_char(ds, ')'); |
d31f1109 | 553 | } else { |
2bcf7df6 EJ |
554 | ds_put_format(ds, " proto:%"PRIu8" tos:%#"PRIx8" ttl:%"PRIu8 |
555 | " ip("IP_FMT"->"IP_FMT")", | |
556 | flow->nw_proto, flow->nw_tos, flow->nw_ttl, | |
557 | IP_ARGS(&flow->nw_src), IP_ARGS(&flow->nw_dst)); | |
d31f1109 | 558 | } |
eadef313 | 559 | if (flow->nw_frag) { |
7257b535 | 560 | ds_put_format(ds, " frag(%s)", |
eadef313 JP |
561 | flow->nw_frag == FLOW_NW_FRAG_ANY ? "first" |
562 | : flow->nw_frag == (FLOW_NW_FRAG_ANY | FLOW_NW_FRAG_LATER) | |
9e44d715 | 563 | ? "later" : "<error>"); |
7257b535 | 564 | } |
bad68a99 | 565 | if (flow->tp_src || flow->tp_dst) { |
2bcf7df6 | 566 | ds_put_format(ds, " port(%"PRIu16"->%"PRIu16")", |
bad68a99 JP |
567 | ntohs(flow->tp_src), ntohs(flow->tp_dst)); |
568 | } | |
569 | if (!eth_addr_is_zero(flow->arp_sha) || !eth_addr_is_zero(flow->arp_tha)) { | |
2bcf7df6 | 570 | ds_put_format(ds, " arp_ha("ETH_ADDR_FMT"->"ETH_ADDR_FMT")", |
bad68a99 JP |
571 | ETH_ADDR_ARGS(flow->arp_sha), |
572 | ETH_ADDR_ARGS(flow->arp_tha)); | |
573 | } | |
064af421 BP |
574 | } |
575 | ||
576 | void | |
ae412e7d | 577 | flow_print(FILE *stream, const struct flow *flow) |
064af421 BP |
578 | { |
579 | char *s = flow_to_string(flow); | |
580 | fputs(s, stream); | |
581 | free(s); | |
582 | } | |
54363004 BP |
583 | \f |
584 | /* flow_wildcards functions. */ | |
585 | ||
d8ae4d67 | 586 | /* Initializes 'wc' as a set of wildcards that matches every packet. */ |
54363004 | 587 | void |
d8ae4d67 | 588 | flow_wildcards_init_catchall(struct flow_wildcards *wc) |
54363004 | 589 | { |
e878338b | 590 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
7257b535 | 591 | |
d8ae4d67 | 592 | wc->wildcards = FWW_ALL; |
8368c090 | 593 | wc->tun_id_mask = htonll(0); |
d8ae4d67 BP |
594 | wc->nw_src_mask = htonl(0); |
595 | wc->nw_dst_mask = htonl(0); | |
d31f1109 JP |
596 | wc->ipv6_src_mask = in6addr_any; |
597 | wc->ipv6_dst_mask = in6addr_any; | |
32455024 | 598 | wc->ipv6_label_mask = htonl(0); |
47284b1f | 599 | wc->nd_target_mask = in6addr_any; |
b6c9e612 | 600 | memset(wc->reg_masks, 0, sizeof wc->reg_masks); |
969fc56c | 601 | wc->metadata_mask = htonll(0); |
66642cb4 | 602 | wc->vlan_tci_mask = htons(0); |
eadef313 | 603 | wc->nw_frag_mask = 0; |
73f33563 BP |
604 | wc->tp_src_mask = htons(0); |
605 | wc->tp_dst_mask = htons(0); | |
73c0ce34 JS |
606 | memset(wc->dl_src_mask, 0, ETH_ADDR_LEN); |
607 | memset(wc->dl_dst_mask, 0, ETH_ADDR_LEN); | |
e878338b SH |
608 | memset(wc->arp_sha_mask, 0, ETH_ADDR_LEN); |
609 | memset(wc->arp_tha_mask, 0, ETH_ADDR_LEN); | |
dc56021d | 610 | memset(wc->zeros, 0, sizeof wc->zeros); |
54363004 BP |
611 | } |
612 | ||
494e43a5 BP |
613 | /* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not |
614 | * wildcard any bits or fields. */ | |
615 | void | |
616 | flow_wildcards_init_exact(struct flow_wildcards *wc) | |
617 | { | |
e878338b | 618 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
7257b535 | 619 | |
b6c9e612 | 620 | wc->wildcards = 0; |
8368c090 | 621 | wc->tun_id_mask = htonll(UINT64_MAX); |
b6c9e612 BP |
622 | wc->nw_src_mask = htonl(UINT32_MAX); |
623 | wc->nw_dst_mask = htonl(UINT32_MAX); | |
d31f1109 JP |
624 | wc->ipv6_src_mask = in6addr_exact; |
625 | wc->ipv6_dst_mask = in6addr_exact; | |
32455024 | 626 | wc->ipv6_label_mask = htonl(UINT32_MAX); |
47284b1f | 627 | wc->nd_target_mask = in6addr_exact; |
b6c9e612 | 628 | memset(wc->reg_masks, 0xff, sizeof wc->reg_masks); |
969fc56c | 629 | wc->metadata_mask = htonll(UINT64_MAX); |
66642cb4 | 630 | wc->vlan_tci_mask = htons(UINT16_MAX); |
eadef313 | 631 | wc->nw_frag_mask = UINT8_MAX; |
73f33563 BP |
632 | wc->tp_src_mask = htons(UINT16_MAX); |
633 | wc->tp_dst_mask = htons(UINT16_MAX); | |
73c0ce34 JS |
634 | memset(wc->dl_src_mask, 0xff, ETH_ADDR_LEN); |
635 | memset(wc->dl_dst_mask, 0xff, ETH_ADDR_LEN); | |
e878338b SH |
636 | memset(wc->arp_sha_mask, 0xff, ETH_ADDR_LEN); |
637 | memset(wc->arp_tha_mask, 0xff, ETH_ADDR_LEN); | |
dc56021d | 638 | memset(wc->zeros, 0, sizeof wc->zeros); |
494e43a5 BP |
639 | } |
640 | ||
00561f41 BP |
641 | /* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or |
642 | * fields. */ | |
643 | bool | |
644 | flow_wildcards_is_exact(const struct flow_wildcards *wc) | |
645 | { | |
d8ae4d67 | 646 | int i; |
00561f41 | 647 | |
e878338b | 648 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
ecf1e7ac | 649 | |
d8ae4d67 | 650 | if (wc->wildcards |
8368c090 | 651 | || wc->tun_id_mask != htonll(UINT64_MAX) |
d8ae4d67 | 652 | || wc->nw_src_mask != htonl(UINT32_MAX) |
66642cb4 | 653 | || wc->nw_dst_mask != htonl(UINT32_MAX) |
73f33563 BP |
654 | || wc->tp_src_mask != htons(UINT16_MAX) |
655 | || wc->tp_dst_mask != htons(UINT16_MAX) | |
d31f1109 | 656 | || wc->vlan_tci_mask != htons(UINT16_MAX) |
969fc56c | 657 | || wc->metadata_mask != htonll(UINT64_MAX) |
73c0ce34 JS |
658 | || !eth_mask_is_exact(wc->dl_src_mask) |
659 | || !eth_mask_is_exact(wc->dl_dst_mask) | |
e878338b SH |
660 | || !eth_mask_is_exact(wc->arp_sha_mask) |
661 | || !eth_mask_is_exact(wc->arp_tha_mask) | |
d31f1109 | 662 | || !ipv6_mask_is_exact(&wc->ipv6_src_mask) |
7257b535 | 663 | || !ipv6_mask_is_exact(&wc->ipv6_dst_mask) |
32455024 | 664 | || wc->ipv6_label_mask != htonl(UINT32_MAX) |
47284b1f | 665 | || !ipv6_mask_is_exact(&wc->nd_target_mask) |
eadef313 | 666 | || wc->nw_frag_mask != UINT8_MAX) { |
d8ae4d67 BP |
667 | return false; |
668 | } | |
669 | ||
670 | for (i = 0; i < FLOW_N_REGS; i++) { | |
d84d4b88 | 671 | if (wc->reg_masks[i] != UINT32_MAX) { |
d8ae4d67 BP |
672 | return false; |
673 | } | |
674 | } | |
675 | ||
676 | return true; | |
b5d97350 BP |
677 | } |
678 | ||
ecf1e7ac BP |
679 | /* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or |
680 | * fields. */ | |
681 | bool | |
682 | flow_wildcards_is_catchall(const struct flow_wildcards *wc) | |
683 | { | |
684 | int i; | |
685 | ||
e878338b | 686 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
ecf1e7ac BP |
687 | |
688 | if (wc->wildcards != FWW_ALL | |
689 | || wc->tun_id_mask != htonll(0) | |
690 | || wc->nw_src_mask != htonl(0) | |
691 | || wc->nw_dst_mask != htonl(0) | |
73f33563 BP |
692 | || wc->tp_src_mask != htons(0) |
693 | || wc->tp_dst_mask != htons(0) | |
ecf1e7ac | 694 | || wc->vlan_tci_mask != htons(0) |
969fc56c | 695 | || wc->metadata_mask != htonll(0) |
73c0ce34 JS |
696 | || !eth_addr_is_zero(wc->dl_src_mask) |
697 | || !eth_addr_is_zero(wc->dl_dst_mask) | |
e878338b SH |
698 | || !eth_addr_is_zero(wc->arp_sha_mask) |
699 | || !eth_addr_is_zero(wc->arp_tha_mask) | |
ecf1e7ac | 700 | || !ipv6_mask_is_any(&wc->ipv6_src_mask) |
7257b535 | 701 | || !ipv6_mask_is_any(&wc->ipv6_dst_mask) |
32455024 | 702 | || wc->ipv6_label_mask != htonl(0) |
47284b1f | 703 | || !ipv6_mask_is_any(&wc->nd_target_mask) |
eadef313 | 704 | || wc->nw_frag_mask != 0) { |
ecf1e7ac BP |
705 | return false; |
706 | } | |
707 | ||
708 | for (i = 0; i < FLOW_N_REGS; i++) { | |
709 | if (wc->reg_masks[i] != 0) { | |
710 | return false; | |
711 | } | |
712 | } | |
713 | ||
714 | return true; | |
715 | } | |
716 | ||
b5d97350 BP |
717 | /* Initializes 'dst' as the combination of wildcards in 'src1' and 'src2'. |
718 | * That is, a bit or a field is wildcarded in 'dst' if it is wildcarded in | |
719 | * 'src1' or 'src2' or both. */ | |
720 | void | |
721 | flow_wildcards_combine(struct flow_wildcards *dst, | |
722 | const struct flow_wildcards *src1, | |
723 | const struct flow_wildcards *src2) | |
724 | { | |
b6c9e612 | 725 | int i; |
b5d97350 | 726 | |
e878338b | 727 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
a79c50f3 | 728 | |
d8ae4d67 | 729 | dst->wildcards = src1->wildcards | src2->wildcards; |
8368c090 | 730 | dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask; |
b5d97350 BP |
731 | dst->nw_src_mask = src1->nw_src_mask & src2->nw_src_mask; |
732 | dst->nw_dst_mask = src1->nw_dst_mask & src2->nw_dst_mask; | |
d31f1109 JP |
733 | dst->ipv6_src_mask = ipv6_addr_bitand(&src1->ipv6_src_mask, |
734 | &src2->ipv6_src_mask); | |
735 | dst->ipv6_dst_mask = ipv6_addr_bitand(&src1->ipv6_dst_mask, | |
736 | &src2->ipv6_dst_mask); | |
32455024 | 737 | dst->ipv6_label_mask = src1->ipv6_label_mask & src2->ipv6_label_mask; |
47284b1f AA |
738 | dst->nd_target_mask = ipv6_addr_bitand(&src1->nd_target_mask, |
739 | &src2->nd_target_mask); | |
b6c9e612 BP |
740 | for (i = 0; i < FLOW_N_REGS; i++) { |
741 | dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i]; | |
742 | } | |
969fc56c | 743 | dst->metadata_mask = src1->metadata_mask & src2->metadata_mask; |
66642cb4 | 744 | dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask; |
73f33563 BP |
745 | dst->tp_src_mask = src1->tp_src_mask & src2->tp_src_mask; |
746 | dst->tp_dst_mask = src1->tp_dst_mask & src2->tp_dst_mask; | |
73c0ce34 JS |
747 | eth_addr_bitand(src1->dl_src_mask, src2->dl_src_mask, dst->dl_src_mask); |
748 | eth_addr_bitand(src1->dl_dst_mask, src2->dl_dst_mask, dst->dl_dst_mask); | |
e878338b SH |
749 | eth_addr_bitand(src1->arp_sha_mask, src2->arp_sha_mask, dst->arp_sha_mask); |
750 | eth_addr_bitand(src1->arp_tha_mask, src2->arp_tha_mask, dst->arp_tha_mask); | |
b5d97350 BP |
751 | } |
752 | ||
753 | /* Returns a hash of the wildcards in 'wc'. */ | |
754 | uint32_t | |
1006cda6 | 755 | flow_wildcards_hash(const struct flow_wildcards *wc, uint32_t basis) |
b5d97350 | 756 | { |
d8ae4d67 BP |
757 | /* If you change struct flow_wildcards and thereby trigger this |
758 | * assertion, please check that the new struct flow_wildcards has no holes | |
759 | * in it before you update the assertion. */ | |
e878338b | 760 | BUILD_ASSERT_DECL(sizeof *wc == 112 + FLOW_N_REGS * 4); |
1006cda6 | 761 | return hash_bytes(wc, sizeof *wc, basis); |
b5d97350 BP |
762 | } |
763 | ||
764 | /* Returns true if 'a' and 'b' represent the same wildcards, false if they are | |
765 | * different. */ | |
766 | bool | |
767 | flow_wildcards_equal(const struct flow_wildcards *a, | |
768 | const struct flow_wildcards *b) | |
769 | { | |
b6c9e612 BP |
770 | int i; |
771 | ||
e878338b | 772 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
a79c50f3 | 773 | |
d8ae4d67 | 774 | if (a->wildcards != b->wildcards |
8368c090 | 775 | || a->tun_id_mask != b->tun_id_mask |
d8ae4d67 | 776 | || a->nw_src_mask != b->nw_src_mask |
66642cb4 | 777 | || a->nw_dst_mask != b->nw_dst_mask |
b53055f4 | 778 | || a->vlan_tci_mask != b->vlan_tci_mask |
969fc56c | 779 | || a->metadata_mask != b->metadata_mask |
d31f1109 | 780 | || !ipv6_addr_equals(&a->ipv6_src_mask, &b->ipv6_src_mask) |
73f33563 | 781 | || !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask) |
32455024 | 782 | || a->ipv6_label_mask != b->ipv6_label_mask |
47284b1f | 783 | || !ipv6_addr_equals(&a->nd_target_mask, &b->nd_target_mask) |
73f33563 | 784 | || a->tp_src_mask != b->tp_src_mask |
73c0ce34 JS |
785 | || a->tp_dst_mask != b->tp_dst_mask |
786 | || !eth_addr_equals(a->dl_src_mask, b->dl_src_mask) | |
e878338b SH |
787 | || !eth_addr_equals(a->dl_dst_mask, b->dl_dst_mask) |
788 | || !eth_addr_equals(a->arp_sha_mask, b->arp_sha_mask) | |
789 | || !eth_addr_equals(a->arp_tha_mask, b->arp_tha_mask)) { | |
b6c9e612 BP |
790 | return false; |
791 | } | |
792 | ||
793 | for (i = 0; i < FLOW_N_REGS; i++) { | |
794 | if (a->reg_masks[i] != b->reg_masks[i]) { | |
795 | return false; | |
796 | } | |
797 | } | |
798 | ||
799 | return true; | |
b5d97350 BP |
800 | } |
801 | ||
802 | /* Returns true if at least one bit or field is wildcarded in 'a' but not in | |
803 | * 'b', false otherwise. */ | |
804 | bool | |
805 | flow_wildcards_has_extra(const struct flow_wildcards *a, | |
806 | const struct flow_wildcards *b) | |
807 | { | |
b6c9e612 | 808 | int i; |
73c0ce34 | 809 | uint8_t eth_masked[ETH_ADDR_LEN]; |
d31f1109 | 810 | struct in6_addr ipv6_masked; |
b6c9e612 | 811 | |
e878338b | 812 | BUILD_ASSERT_DECL(FLOW_WC_SEQ == 14); |
a79c50f3 | 813 | |
b6c9e612 BP |
814 | for (i = 0; i < FLOW_N_REGS; i++) { |
815 | if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) { | |
816 | return true; | |
817 | } | |
818 | } | |
819 | ||
73c0ce34 JS |
820 | eth_addr_bitand(a->dl_src_mask, b->dl_src_mask, eth_masked); |
821 | if (!eth_addr_equals(eth_masked, b->dl_src_mask)) { | |
822 | return true; | |
823 | } | |
824 | ||
825 | eth_addr_bitand(a->dl_dst_mask, b->dl_dst_mask, eth_masked); | |
826 | if (!eth_addr_equals(eth_masked, b->dl_dst_mask)) { | |
827 | return true; | |
828 | } | |
829 | ||
e878338b SH |
830 | eth_addr_bitand(a->arp_sha_mask, b->arp_sha_mask, eth_masked); |
831 | if (!eth_addr_equals(eth_masked, b->arp_sha_mask)) { | |
832 | return true; | |
833 | } | |
834 | ||
835 | eth_addr_bitand(a->arp_tha_mask, b->arp_tha_mask, eth_masked); | |
836 | if (!eth_addr_equals(eth_masked, b->arp_tha_mask)) { | |
837 | return true; | |
838 | } | |
839 | ||
d31f1109 JP |
840 | ipv6_masked = ipv6_addr_bitand(&a->ipv6_src_mask, &b->ipv6_src_mask); |
841 | if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_src_mask)) { | |
842 | return true; | |
843 | } | |
844 | ||
845 | ipv6_masked = ipv6_addr_bitand(&a->ipv6_dst_mask, &b->ipv6_dst_mask); | |
846 | if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_dst_mask)) { | |
847 | return true; | |
848 | } | |
849 | ||
47284b1f AA |
850 | ipv6_masked = ipv6_addr_bitand(&a->nd_target_mask, &b->nd_target_mask); |
851 | if (!ipv6_addr_equals(&ipv6_masked, &b->nd_target_mask)) { | |
852 | return true; | |
853 | } | |
854 | ||
d8ae4d67 | 855 | return (a->wildcards & ~b->wildcards |
8368c090 | 856 | || (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask |
b5d97350 | 857 | || (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask |
66642cb4 | 858 | || (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask |
32455024 | 859 | || (a->ipv6_label_mask & b->ipv6_label_mask) != b->ipv6_label_mask |
73f33563 | 860 | || (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask |
969fc56c | 861 | || (a->metadata_mask & b->metadata_mask) != b->metadata_mask |
73f33563 BP |
862 | || (a->tp_src_mask & b->tp_src_mask) != b->tp_src_mask |
863 | || (a->tp_dst_mask & b->tp_dst_mask) != b->tp_dst_mask); | |
b5d97350 BP |
864 | } |
865 | ||
b6c9e612 BP |
866 | /* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'. |
867 | * (A 0-bit indicates a wildcard bit.) */ | |
868 | void | |
869 | flow_wildcards_set_reg_mask(struct flow_wildcards *wc, int idx, uint32_t mask) | |
870 | { | |
d8ae4d67 | 871 | wc->reg_masks[idx] = mask; |
b6c9e612 | 872 | } |
ff55ea1f EJ |
873 | |
874 | /* Hashes 'flow' based on its L2 through L4 protocol information. */ | |
875 | uint32_t | |
876 | flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis) | |
877 | { | |
878 | struct { | |
d31f1109 JP |
879 | union { |
880 | ovs_be32 ipv4_addr; | |
881 | struct in6_addr ipv6_addr; | |
882 | }; | |
ff55ea1f EJ |
883 | ovs_be16 eth_type; |
884 | ovs_be16 vlan_tci; | |
5b909cbb | 885 | ovs_be16 tp_port; |
ff55ea1f EJ |
886 | uint8_t eth_addr[ETH_ADDR_LEN]; |
887 | uint8_t ip_proto; | |
888 | } fields; | |
889 | ||
890 | int i; | |
891 | ||
892 | memset(&fields, 0, sizeof fields); | |
893 | for (i = 0; i < ETH_ADDR_LEN; i++) { | |
894 | fields.eth_addr[i] = flow->dl_src[i] ^ flow->dl_dst[i]; | |
895 | } | |
896 | fields.vlan_tci = flow->vlan_tci & htons(VLAN_VID_MASK); | |
897 | fields.eth_type = flow->dl_type; | |
3e3eda95 EJ |
898 | |
899 | /* UDP source and destination port are not taken into account because they | |
900 | * will not necessarily be symmetric in a bidirectional flow. */ | |
ff55ea1f | 901 | if (fields.eth_type == htons(ETH_TYPE_IP)) { |
d31f1109 JP |
902 | fields.ipv4_addr = flow->nw_src ^ flow->nw_dst; |
903 | fields.ip_proto = flow->nw_proto; | |
3e3eda95 | 904 | if (fields.ip_proto == IPPROTO_TCP) { |
5b909cbb | 905 | fields.tp_port = flow->tp_src ^ flow->tp_dst; |
d31f1109 JP |
906 | } |
907 | } else if (fields.eth_type == htons(ETH_TYPE_IPV6)) { | |
908 | const uint8_t *a = &flow->ipv6_src.s6_addr[0]; | |
909 | const uint8_t *b = &flow->ipv6_dst.s6_addr[0]; | |
910 | uint8_t *ipv6_addr = &fields.ipv6_addr.s6_addr[0]; | |
911 | ||
912 | for (i=0; i<16; i++) { | |
913 | ipv6_addr[i] = a[i] ^ b[i]; | |
914 | } | |
ff55ea1f | 915 | fields.ip_proto = flow->nw_proto; |
3e3eda95 | 916 | if (fields.ip_proto == IPPROTO_TCP) { |
5b909cbb | 917 | fields.tp_port = flow->tp_src ^ flow->tp_dst; |
ff55ea1f | 918 | } |
ff55ea1f EJ |
919 | } |
920 | return hash_bytes(&fields, sizeof fields, basis); | |
921 | } | |
520e9a2a EJ |
922 | |
923 | /* Hashes the portions of 'flow' designated by 'fields'. */ | |
924 | uint32_t | |
925 | flow_hash_fields(const struct flow *flow, enum nx_hash_fields fields, | |
926 | uint16_t basis) | |
927 | { | |
928 | switch (fields) { | |
929 | ||
930 | case NX_HASH_FIELDS_ETH_SRC: | |
931 | return hash_bytes(flow->dl_src, sizeof flow->dl_src, basis); | |
932 | ||
933 | case NX_HASH_FIELDS_SYMMETRIC_L4: | |
934 | return flow_hash_symmetric_l4(flow, basis); | |
935 | } | |
936 | ||
937 | NOT_REACHED(); | |
938 | } | |
939 | ||
940 | /* Returns a string representation of 'fields'. */ | |
941 | const char * | |
942 | flow_hash_fields_to_str(enum nx_hash_fields fields) | |
943 | { | |
944 | switch (fields) { | |
945 | case NX_HASH_FIELDS_ETH_SRC: return "eth_src"; | |
946 | case NX_HASH_FIELDS_SYMMETRIC_L4: return "symmetric_l4"; | |
947 | default: return "<unknown>"; | |
948 | } | |
949 | } | |
950 | ||
951 | /* Returns true if the value of 'fields' is supported. Otherwise false. */ | |
952 | bool | |
953 | flow_hash_fields_valid(enum nx_hash_fields fields) | |
954 | { | |
955 | return fields == NX_HASH_FIELDS_ETH_SRC | |
956 | || fields == NX_HASH_FIELDS_SYMMETRIC_L4; | |
957 | } | |
8b3b8dd1 | 958 | |
3719455c BP |
959 | /* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an |
960 | * OpenFlow 1.0 "dl_vlan" value: | |
961 | * | |
962 | * - If it is in the range 0...4095, 'flow->vlan_tci' is set to match | |
963 | * that VLAN. Any existing PCP match is unchanged (it becomes 0 if | |
964 | * 'flow' previously matched packets without a VLAN header). | |
965 | * | |
966 | * - If it is OFP_VLAN_NONE, 'flow->vlan_tci' is set to match a packet | |
967 | * without a VLAN tag. | |
968 | * | |
969 | * - Other values of 'vid' should not be used. */ | |
970 | void | |
971 | flow_set_vlan_vid(struct flow *flow, ovs_be16 vid) | |
972 | { | |
0c436519 | 973 | if (vid == htons(OFP10_VLAN_NONE)) { |
3719455c BP |
974 | flow->vlan_tci = htons(0); |
975 | } else { | |
976 | vid &= htons(VLAN_VID_MASK); | |
977 | flow->vlan_tci &= ~htons(VLAN_VID_MASK); | |
978 | flow->vlan_tci |= htons(VLAN_CFI) | vid; | |
979 | } | |
980 | } | |
981 | ||
982 | /* Sets the VLAN PCP that 'flow' matches to 'pcp', which should be in the | |
983 | * range 0...7. | |
984 | * | |
985 | * This function has no effect on the VLAN ID that 'flow' matches. | |
986 | * | |
987 | * After calling this function, 'flow' will not match packets without a VLAN | |
988 | * header. */ | |
989 | void | |
990 | flow_set_vlan_pcp(struct flow *flow, uint8_t pcp) | |
991 | { | |
992 | pcp &= 0x07; | |
993 | flow->vlan_tci &= ~htons(VLAN_PCP_MASK); | |
994 | flow->vlan_tci |= htons((pcp << VLAN_PCP_SHIFT) | VLAN_CFI); | |
995 | } | |
996 | ||
8b3b8dd1 BP |
997 | /* Puts into 'b' a packet that flow_extract() would parse as having the given |
998 | * 'flow'. | |
999 | * | |
1000 | * (This is useful only for testing, obviously, and the packet isn't really | |
1001 | * valid. It hasn't got any checksums filled in, for one, and lots of fields | |
1002 | * are just zeroed.) */ | |
1003 | void | |
1004 | flow_compose(struct ofpbuf *b, const struct flow *flow) | |
1005 | { | |
1006 | eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0); | |
1007 | if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) { | |
1008 | struct eth_header *eth = b->l2; | |
1009 | eth->eth_type = htons(b->size); | |
1010 | return; | |
1011 | } | |
1012 | ||
1013 | if (flow->vlan_tci & htons(VLAN_CFI)) { | |
2f4ca41b | 1014 | eth_push_vlan(b, flow->vlan_tci); |
8b3b8dd1 BP |
1015 | } |
1016 | ||
1017 | if (flow->dl_type == htons(ETH_TYPE_IP)) { | |
1018 | struct ip_header *ip; | |
1019 | ||
1020 | b->l3 = ip = ofpbuf_put_zeros(b, sizeof *ip); | |
1021 | ip->ip_ihl_ver = IP_IHL_VER(5, 4); | |
eadef313 | 1022 | ip->ip_tos = flow->nw_tos; |
8b3b8dd1 BP |
1023 | ip->ip_proto = flow->nw_proto; |
1024 | ip->ip_src = flow->nw_src; | |
1025 | ip->ip_dst = flow->nw_dst; | |
1026 | ||
eadef313 | 1027 | if (flow->nw_frag & FLOW_NW_FRAG_ANY) { |
7257b535 | 1028 | ip->ip_frag_off |= htons(IP_MORE_FRAGMENTS); |
eadef313 | 1029 | if (flow->nw_frag & FLOW_NW_FRAG_LATER) { |
7257b535 BP |
1030 | ip->ip_frag_off |= htons(100); |
1031 | } | |
1032 | } | |
eadef313 JP |
1033 | if (!(flow->nw_frag & FLOW_NW_FRAG_ANY) |
1034 | || !(flow->nw_frag & FLOW_NW_FRAG_LATER)) { | |
7257b535 BP |
1035 | if (flow->nw_proto == IPPROTO_TCP) { |
1036 | struct tcp_header *tcp; | |
1037 | ||
1038 | b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp); | |
1039 | tcp->tcp_src = flow->tp_src; | |
1040 | tcp->tcp_dst = flow->tp_dst; | |
df9b6612 | 1041 | tcp->tcp_ctl = TCP_CTL(0, 5); |
7257b535 BP |
1042 | } else if (flow->nw_proto == IPPROTO_UDP) { |
1043 | struct udp_header *udp; | |
1044 | ||
1045 | b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp); | |
1046 | udp->udp_src = flow->tp_src; | |
1047 | udp->udp_dst = flow->tp_dst; | |
1048 | } else if (flow->nw_proto == IPPROTO_ICMP) { | |
1049 | struct icmp_header *icmp; | |
1050 | ||
1051 | b->l4 = icmp = ofpbuf_put_zeros(b, sizeof *icmp); | |
1052 | icmp->icmp_type = ntohs(flow->tp_src); | |
1053 | icmp->icmp_code = ntohs(flow->tp_dst); | |
1054 | } | |
8b3b8dd1 | 1055 | } |
df9b6612 BP |
1056 | |
1057 | ip->ip_tot_len = htons((uint8_t *) b->data + b->size | |
1058 | - (uint8_t *) b->l3); | |
8b3b8dd1 BP |
1059 | } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { |
1060 | /* XXX */ | |
1061 | } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { | |
1062 | struct arp_eth_header *arp; | |
1063 | ||
1064 | b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp); | |
1065 | arp->ar_hrd = htons(1); | |
1066 | arp->ar_pro = htons(ETH_TYPE_IP); | |
1067 | arp->ar_hln = ETH_ADDR_LEN; | |
1068 | arp->ar_pln = 4; | |
1069 | arp->ar_op = htons(flow->nw_proto); | |
1070 | ||
1071 | if (flow->nw_proto == ARP_OP_REQUEST || | |
1072 | flow->nw_proto == ARP_OP_REPLY) { | |
1073 | arp->ar_spa = flow->nw_src; | |
1074 | arp->ar_tpa = flow->nw_dst; | |
1075 | memcpy(arp->ar_sha, flow->arp_sha, ETH_ADDR_LEN); | |
1076 | memcpy(arp->ar_tha, flow->arp_tha, ETH_ADDR_LEN); | |
1077 | } | |
1078 | } | |
1079 | } |