]>
Commit | Line | Data |
---|---|---|
6a885fd0 BP |
1 | /* |
2 | * Copyright (c) 2011 Nicira Networks. | |
3 | * | |
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: | |
7 | * | |
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. | |
15 | */ | |
16 | ||
17 | #include <config.h> | |
18 | ||
19 | #include "meta-flow.h" | |
20 | ||
21 | #include <assert.h> | |
22 | #include <errno.h> | |
23 | #include <limits.h> | |
24 | #include <netinet/icmp6.h> | |
25 | #include <netinet/ip6.h> | |
26 | ||
27 | #include "classifier.h" | |
28 | #include "dynamic-string.h" | |
29 | #include "ofp-util.h" | |
30 | #include "packets.h" | |
31 | #include "random.h" | |
32 | #include "shash.h" | |
33 | #include "socket-util.h" | |
34 | #include "unaligned.h" | |
35 | ||
36 | #define MF_FIELD_SIZES(MEMBER) \ | |
37 | sizeof ((union mf_value *)0)->MEMBER, \ | |
38 | 8 * sizeof ((union mf_value *)0)->MEMBER | |
39 | ||
40 | static const struct mf_field mf_fields[MFF_N_IDS] = { | |
41 | /* ## -------- ## */ | |
42 | /* ## metadata ## */ | |
43 | /* ## -------- ## */ | |
44 | ||
45 | { | |
46 | MFF_TUN_ID, "tun_id", NULL, | |
47 | MF_FIELD_SIZES(be64), | |
48 | MFM_FULLY, 0, | |
49 | MFS_HEXADECIMAL, | |
50 | MFP_NONE, | |
51 | NXM_NX_TUN_ID, | |
52 | }, { | |
53 | MFF_IN_PORT, "in_port", NULL, | |
54 | MF_FIELD_SIZES(be16), | |
55 | MFM_NONE, FWW_IN_PORT, | |
56 | MFS_OFP_PORT, | |
57 | MFP_NONE, | |
58 | NXM_OF_IN_PORT, | |
59 | }, | |
60 | ||
61 | #define REGISTER(IDX) \ | |
62 | { \ | |
63 | MFF_REG##IDX, "reg" #IDX, NULL, \ | |
64 | MF_FIELD_SIZES(be32), \ | |
65 | MFM_FULLY, 0, \ | |
66 | MFS_HEXADECIMAL, \ | |
67 | MFP_NONE, \ | |
68 | NXM_NX_REG(IDX), \ | |
69 | } | |
70 | #if FLOW_N_REGS > 0 | |
71 | REGISTER(0), | |
72 | #endif | |
73 | #if FLOW_N_REGS > 1 | |
74 | REGISTER(1), | |
75 | #endif | |
76 | #if FLOW_N_REGS > 2 | |
77 | REGISTER(2), | |
78 | #endif | |
79 | #if FLOW_N_REGS > 3 | |
80 | REGISTER(3), | |
81 | #endif | |
82 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
83 | REGISTER(4), |
84 | #endif | |
85 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
86 | #error |
87 | #endif | |
88 | ||
89 | /* ## -- ## */ | |
90 | /* ## L2 ## */ | |
91 | /* ## -- ## */ | |
92 | ||
93 | { | |
94 | MFF_ETH_SRC, "eth_src", "dl_src", | |
95 | MF_FIELD_SIZES(mac), | |
96 | MFM_NONE, FWW_DL_SRC, | |
97 | MFS_ETHERNET, | |
98 | MFP_NONE, | |
99 | NXM_OF_ETH_SRC, | |
100 | }, { | |
101 | MFF_ETH_DST, "eth_dst", "dl_dst", | |
102 | MF_FIELD_SIZES(mac), | |
103 | MFM_MCAST, 0, | |
104 | MFS_ETHERNET, | |
105 | MFP_NONE, | |
106 | NXM_OF_ETH_DST, | |
107 | }, { | |
108 | MFF_ETH_TYPE, "eth_type", "dl_type", | |
109 | MF_FIELD_SIZES(be16), | |
110 | MFM_NONE, FWW_DL_TYPE, | |
111 | MFS_HEXADECIMAL, | |
112 | MFP_NONE, | |
113 | NXM_OF_ETH_TYPE, | |
114 | }, | |
115 | ||
116 | { | |
117 | MFF_VLAN_TCI, "vlan_tci", NULL, | |
118 | MF_FIELD_SIZES(be16), | |
119 | MFM_FULLY, 0, | |
120 | MFS_HEXADECIMAL, | |
121 | MFP_NONE, | |
122 | NXM_OF_VLAN_TCI, | |
123 | }, { | |
124 | MFF_VLAN_VID, "dl_vlan", NULL, | |
125 | sizeof(ovs_be16), 12, | |
126 | MFM_NONE, 0, | |
127 | MFS_DECIMAL, | |
128 | MFP_NONE, | |
129 | 0, | |
130 | }, { | |
131 | MFF_VLAN_PCP, "dl_vlan_pcp", NULL, | |
132 | 1, 3, | |
133 | MFM_NONE, 0, | |
134 | MFS_DECIMAL, | |
135 | MFP_NONE, | |
136 | 0, | |
137 | }, | |
138 | ||
139 | /* ## -- ## */ | |
140 | /* ## L3 ## */ | |
141 | /* ## -- ## */ | |
142 | ||
143 | { | |
144 | MFF_IPV4_SRC, "ip_src", "nw_src", | |
145 | MF_FIELD_SIZES(be32), | |
146 | MFM_CIDR, 0, | |
147 | MFS_IPV4, | |
148 | MFP_IPV4, | |
149 | NXM_OF_IP_SRC, | |
150 | }, { | |
151 | MFF_IPV4_DST, "ip_dst", "nw_dst", | |
152 | MF_FIELD_SIZES(be32), | |
153 | MFM_CIDR, 0, | |
154 | MFS_IPV4, | |
155 | MFP_IPV4, | |
156 | NXM_OF_IP_DST, | |
157 | }, | |
158 | ||
159 | { | |
160 | MFF_IPV6_SRC, "ipv6_src", NULL, | |
161 | MF_FIELD_SIZES(ipv6), | |
162 | MFM_CIDR, 0, | |
163 | MFS_IPV6, | |
164 | MFP_IPV6, | |
165 | NXM_NX_IPV6_SRC, | |
166 | }, { | |
167 | MFF_IPV6_DST, "ipv6_dst", NULL, | |
168 | MF_FIELD_SIZES(ipv6), | |
169 | MFM_CIDR, 0, | |
170 | MFS_IPV6, | |
171 | MFP_IPV6, | |
172 | NXM_NX_IPV6_DST, | |
173 | }, | |
fa8223b7 JP |
174 | { |
175 | MFF_IPV6_LABEL, "ipv6_label", NULL, | |
176 | 4, 20, | |
177 | MFM_NONE, FWW_IPV6_LABEL, | |
178 | MFS_HEXADECIMAL, | |
179 | MFP_IPV6, | |
180 | NXM_NX_IPV6_LABEL, | |
181 | }, | |
6a885fd0 BP |
182 | |
183 | { | |
184 | MFF_IP_PROTO, "nw_proto", NULL, | |
185 | MF_FIELD_SIZES(u8), | |
186 | MFM_NONE, FWW_NW_PROTO, | |
187 | MFS_DECIMAL, | |
188 | MFP_IP_ANY, | |
189 | NXM_OF_IP_PROTO, | |
190 | }, { | |
530180fd | 191 | MFF_IP_DSCP, "nw_tos", NULL, |
6a885fd0 | 192 | MF_FIELD_SIZES(u8), |
7257b535 | 193 | MFM_NONE, 0, |
6a885fd0 BP |
194 | MFS_DECIMAL, |
195 | MFP_IP_ANY, | |
196 | NXM_OF_IP_TOS, | |
530180fd JP |
197 | }, { |
198 | MFF_IP_ECN, "nw_ecn", NULL, | |
199 | 1, 2, | |
200 | MFM_NONE, 0, | |
201 | MFS_DECIMAL, | |
202 | MFP_IP_ANY, | |
203 | NXM_NX_IP_ECN, | |
a61680c6 JP |
204 | }, { |
205 | MFF_IP_TTL, "nw_ttl", NULL, | |
206 | MF_FIELD_SIZES(u8), | |
207 | MFM_NONE, FWW_NW_TTL, | |
208 | MFS_DECIMAL, | |
209 | MFP_IP_ANY, | |
210 | NXM_NX_IP_TTL, | |
7257b535 BP |
211 | }, { |
212 | MFF_IP_FRAG, "ip_frag", NULL, | |
213 | 1, 2, | |
214 | MFM_FULLY, 0, | |
215 | MFS_FRAG, | |
216 | MFP_IP_ANY, | |
217 | NXM_NX_IP_FRAG, | |
6a885fd0 BP |
218 | }, |
219 | ||
220 | { | |
221 | MFF_ARP_OP, "arp_op", NULL, | |
222 | MF_FIELD_SIZES(be16), | |
223 | MFM_NONE, FWW_NW_PROTO, | |
224 | MFS_DECIMAL, | |
225 | MFP_ARP, | |
226 | NXM_OF_ARP_OP, | |
227 | }, { | |
228 | MFF_ARP_SPA, "arp_spa", NULL, | |
229 | MF_FIELD_SIZES(be32), | |
230 | MFM_CIDR, 0, | |
231 | MFS_IPV4, | |
232 | MFP_ARP, | |
233 | NXM_OF_ARP_SPA, | |
234 | }, { | |
235 | MFF_ARP_TPA, "arp_tpa", NULL, | |
236 | MF_FIELD_SIZES(be32), | |
237 | MFM_CIDR, 0, | |
238 | MFS_IPV4, | |
239 | MFP_ARP, | |
240 | NXM_OF_ARP_TPA, | |
241 | }, { | |
242 | MFF_ARP_SHA, "arp_sha", NULL, | |
243 | MF_FIELD_SIZES(mac), | |
244 | MFM_NONE, FWW_ARP_SHA, | |
245 | MFS_ETHERNET, | |
246 | MFP_ARP, | |
247 | NXM_NX_ARP_SHA, | |
248 | }, { | |
249 | MFF_ARP_THA, "arp_tha", NULL, | |
250 | MF_FIELD_SIZES(mac), | |
251 | MFM_NONE, FWW_ARP_THA, | |
252 | MFS_ETHERNET, | |
253 | MFP_ARP, | |
254 | NXM_NX_ARP_THA, | |
255 | }, | |
256 | ||
257 | /* ## -- ## */ | |
258 | /* ## L4 ## */ | |
259 | /* ## -- ## */ | |
260 | ||
261 | { | |
262 | MFF_TCP_SRC, "tcp_src", "tp_src", | |
263 | MF_FIELD_SIZES(be16), | |
264 | MFM_NONE, FWW_TP_SRC, | |
265 | MFS_DECIMAL, | |
266 | MFP_TCP, | |
267 | NXM_OF_TCP_SRC, | |
268 | }, { | |
269 | MFF_TCP_DST, "tcp_dst", "tp_dst", | |
270 | MF_FIELD_SIZES(be16), | |
271 | MFM_NONE, FWW_TP_DST, | |
272 | MFS_DECIMAL, | |
273 | MFP_TCP, | |
274 | NXM_OF_TCP_DST, | |
275 | }, | |
276 | ||
277 | { | |
278 | MFF_UDP_SRC, "udp_src", NULL, | |
279 | MF_FIELD_SIZES(be16), | |
280 | MFM_NONE, FWW_TP_SRC, | |
281 | MFS_DECIMAL, | |
282 | MFP_UDP, | |
283 | NXM_OF_UDP_SRC, | |
284 | }, { | |
285 | MFF_UDP_DST, "udp_dst", NULL, | |
286 | MF_FIELD_SIZES(be16), | |
287 | MFM_NONE, FWW_TP_DST, | |
288 | MFS_DECIMAL, | |
289 | MFP_UDP, | |
290 | NXM_OF_UDP_DST, | |
291 | }, | |
292 | ||
293 | { | |
294 | MFF_ICMP_TYPE, "icmp_type", NULL, | |
295 | MF_FIELD_SIZES(u8), | |
296 | MFM_NONE, FWW_TP_SRC, | |
297 | MFS_DECIMAL, | |
298 | MFP_ICMP_ANY, | |
299 | NXM_OF_ICMP_TYPE, | |
300 | }, { | |
301 | MFF_ICMP_CODE, "icmp_code", NULL, | |
302 | MF_FIELD_SIZES(u8), | |
029b26f3 | 303 | MFM_NONE, FWW_TP_DST, |
6a885fd0 BP |
304 | MFS_DECIMAL, |
305 | MFP_ICMP_ANY, | |
306 | NXM_OF_ICMP_CODE, | |
307 | }, | |
308 | ||
309 | /* ## ---- ## */ | |
310 | /* ## L"5" ## */ | |
311 | /* ## ---- ## */ | |
312 | ||
313 | { | |
314 | MFF_ND_TARGET, "nd_target", NULL, | |
315 | MF_FIELD_SIZES(ipv6), | |
316 | MFM_NONE, FWW_ND_TARGET, | |
317 | MFS_IPV6, | |
318 | MFP_ND, | |
319 | NXM_NX_ND_TARGET, | |
320 | }, { | |
321 | MFF_ND_SLL, "nd_sll", NULL, | |
322 | MF_FIELD_SIZES(mac), | |
323 | MFM_NONE, FWW_ARP_SHA, | |
324 | MFS_ETHERNET, | |
325 | MFP_ND_SOLICIT, | |
326 | NXM_NX_ND_SLL, | |
327 | }, { | |
328 | MFF_ND_TLL, "nd_tll", NULL, | |
329 | MF_FIELD_SIZES(mac), | |
330 | MFM_NONE, FWW_ARP_THA, | |
331 | MFS_ETHERNET, | |
332 | MFP_ND_ADVERT, | |
333 | NXM_NX_ND_TLL, | |
334 | } | |
335 | }; | |
336 | ||
6a885fd0 BP |
337 | /* Returns the field with the given 'id'. */ |
338 | const struct mf_field * | |
339 | mf_from_id(enum mf_field_id id) | |
340 | { | |
341 | assert((unsigned int) id < MFF_N_IDS); | |
342 | return &mf_fields[id]; | |
343 | } | |
344 | ||
345 | /* Returns the field with the given 'name', or a null pointer if no field has | |
346 | * that name. */ | |
347 | const struct mf_field * | |
348 | mf_from_name(const char *name) | |
349 | { | |
350 | static struct shash mf_by_name = SHASH_INITIALIZER(&mf_by_name); | |
351 | ||
352 | if (shash_is_empty(&mf_by_name)) { | |
353 | const struct mf_field *mf; | |
354 | ||
355 | for (mf = mf_fields; mf < &mf_fields[MFF_N_IDS]; mf++) { | |
356 | shash_add_once(&mf_by_name, mf->name, mf); | |
357 | if (mf->extra_name) { | |
358 | shash_add_once(&mf_by_name, mf->extra_name, mf); | |
359 | } | |
360 | } | |
361 | } | |
362 | ||
363 | return shash_find_data(&mf_by_name, name); | |
364 | } | |
365 | ||
366 | /* Returns true if 'wc' wildcards all the bits in field 'mf', false if 'wc' | |
367 | * specifies at least one bit in the field. | |
368 | * | |
369 | * The caller is responsible for ensuring that 'wc' corresponds to a flow that | |
370 | * meets 'mf''s prerequisites. */ | |
371 | bool | |
372 | mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) | |
373 | { | |
374 | switch (mf->id) { | |
375 | case MFF_IN_PORT: | |
376 | case MFF_ETH_SRC: | |
377 | case MFF_ETH_TYPE: | |
378 | case MFF_IP_PROTO: | |
a61680c6 | 379 | case MFF_IP_TTL: |
fa8223b7 | 380 | case MFF_IPV6_LABEL: |
6a885fd0 BP |
381 | case MFF_ARP_OP: |
382 | case MFF_ARP_SHA: | |
383 | case MFF_ARP_THA: | |
384 | case MFF_TCP_SRC: | |
385 | case MFF_TCP_DST: | |
386 | case MFF_UDP_SRC: | |
387 | case MFF_UDP_DST: | |
388 | case MFF_ICMP_TYPE: | |
389 | case MFF_ICMP_CODE: | |
390 | case MFF_ND_TARGET: | |
391 | case MFF_ND_SLL: | |
392 | case MFF_ND_TLL: | |
393 | assert(mf->fww_bit != 0); | |
394 | return (wc->wildcards & mf->fww_bit) != 0; | |
395 | ||
396 | case MFF_TUN_ID: | |
397 | return !wc->tun_id_mask; | |
398 | ||
399 | #if FLOW_N_REGS > 0 | |
400 | case MFF_REG0: | |
401 | #endif | |
402 | #if FLOW_N_REGS > 1 | |
403 | case MFF_REG1: | |
404 | #endif | |
405 | #if FLOW_N_REGS > 2 | |
406 | case MFF_REG2: | |
407 | #endif | |
408 | #if FLOW_N_REGS > 3 | |
409 | case MFF_REG3: | |
410 | #endif | |
411 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
412 | case MFF_REG4: |
413 | #endif | |
414 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
415 | #error |
416 | #endif | |
417 | return !wc->reg_masks[mf->id - MFF_REG0]; | |
418 | ||
419 | case MFF_ETH_DST: | |
420 | return ((wc->wildcards & (FWW_ETH_MCAST | FWW_DL_DST)) | |
421 | == (FWW_ETH_MCAST | FWW_DL_DST)); | |
422 | ||
423 | case MFF_VLAN_TCI: | |
424 | return !wc->vlan_tci_mask; | |
425 | case MFF_VLAN_VID: | |
426 | return !(wc->vlan_tci_mask & htons(VLAN_VID_MASK)); | |
427 | case MFF_VLAN_PCP: | |
428 | return !(wc->vlan_tci_mask & htons(VLAN_PCP_MASK)); | |
429 | ||
430 | case MFF_IPV4_SRC: | |
431 | return !wc->nw_src_mask; | |
432 | case MFF_IPV4_DST: | |
433 | return !wc->nw_dst_mask; | |
434 | ||
435 | case MFF_IPV6_SRC: | |
436 | return ipv6_mask_is_any(&wc->ipv6_src_mask); | |
437 | case MFF_IPV6_DST: | |
438 | return ipv6_mask_is_any(&wc->ipv6_dst_mask); | |
439 | ||
530180fd | 440 | case MFF_IP_DSCP: |
9e44d715 | 441 | return !(wc->tos_mask & IP_DSCP_MASK); |
530180fd JP |
442 | case MFF_IP_ECN: |
443 | return !(wc->tos_mask & IP_ECN_MASK); | |
7257b535 | 444 | case MFF_IP_FRAG: |
9e44d715 | 445 | return !(wc->frag_mask & FLOW_FRAG_MASK); |
7257b535 | 446 | |
6a885fd0 BP |
447 | case MFF_ARP_SPA: |
448 | return !wc->nw_src_mask; | |
449 | case MFF_ARP_TPA: | |
450 | return !wc->nw_dst_mask; | |
451 | ||
452 | case MFF_N_IDS: | |
453 | default: | |
454 | NOT_REACHED(); | |
455 | } | |
456 | } | |
457 | ||
458 | /* Initializes 'mask' with the wildcard bit pattern for field 'mf' within 'wc'. | |
459 | * Each bit in 'mask' will be set to 1 if the bit is significant for matching | |
460 | * purposes, or to 0 if it is wildcarded. | |
461 | * | |
462 | * The caller is responsible for ensuring that 'wc' corresponds to a flow that | |
463 | * meets 'mf''s prerequisites. */ | |
464 | void | |
465 | mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc, | |
466 | union mf_value *mask) | |
467 | { | |
468 | switch (mf->id) { | |
469 | case MFF_IN_PORT: | |
470 | case MFF_ETH_SRC: | |
471 | case MFF_ETH_TYPE: | |
472 | case MFF_IP_PROTO: | |
a61680c6 | 473 | case MFF_IP_TTL: |
fa8223b7 | 474 | case MFF_IPV6_LABEL: |
6a885fd0 BP |
475 | case MFF_ARP_OP: |
476 | case MFF_ARP_SHA: | |
477 | case MFF_ARP_THA: | |
478 | case MFF_TCP_SRC: | |
479 | case MFF_TCP_DST: | |
480 | case MFF_UDP_SRC: | |
481 | case MFF_UDP_DST: | |
482 | case MFF_ICMP_TYPE: | |
483 | case MFF_ICMP_CODE: | |
484 | case MFF_ND_TARGET: | |
485 | case MFF_ND_SLL: | |
486 | case MFF_ND_TLL: | |
487 | assert(mf->fww_bit != 0); | |
488 | memset(mask, wc->wildcards & mf->fww_bit ? 0x00 : 0xff, mf->n_bytes); | |
489 | break; | |
490 | ||
491 | case MFF_TUN_ID: | |
492 | mask->be64 = wc->tun_id_mask; | |
493 | break; | |
494 | ||
495 | #if FLOW_N_REGS > 0 | |
496 | case MFF_REG0: | |
497 | #endif | |
498 | #if FLOW_N_REGS > 1 | |
499 | case MFF_REG1: | |
500 | #endif | |
501 | #if FLOW_N_REGS > 2 | |
502 | case MFF_REG2: | |
503 | #endif | |
504 | #if FLOW_N_REGS > 3 | |
505 | case MFF_REG3: | |
506 | #endif | |
507 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
508 | case MFF_REG4: |
509 | #endif | |
510 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
511 | #error |
512 | #endif | |
513 | mask->be32 = htonl(wc->reg_masks[mf->id - MFF_REG0]); | |
514 | break; | |
515 | ||
516 | case MFF_ETH_DST: | |
517 | memcpy(mask->mac, flow_wildcards_to_dl_dst_mask(wc->wildcards), | |
518 | ETH_ADDR_LEN); | |
519 | break; | |
520 | ||
521 | case MFF_VLAN_TCI: | |
522 | mask->be16 = wc->vlan_tci_mask; | |
523 | break; | |
524 | case MFF_VLAN_VID: | |
525 | mask->be16 = wc->vlan_tci_mask & htons(VLAN_VID_MASK); | |
526 | break; | |
527 | case MFF_VLAN_PCP: | |
528 | mask->u8 = vlan_tci_to_pcp(wc->vlan_tci_mask); | |
529 | break; | |
530 | ||
531 | case MFF_IPV4_SRC: | |
532 | mask->be32 = wc->nw_src_mask; | |
533 | break; | |
534 | case MFF_IPV4_DST: | |
535 | mask->be32 = wc->nw_dst_mask; | |
536 | break; | |
537 | ||
538 | case MFF_IPV6_SRC: | |
539 | mask->ipv6 = wc->ipv6_src_mask; | |
540 | break; | |
541 | case MFF_IPV6_DST: | |
542 | mask->ipv6 = wc->ipv6_dst_mask; | |
543 | break; | |
544 | ||
530180fd | 545 | case MFF_IP_DSCP: |
9e44d715 | 546 | mask->u8 = wc->tos_mask & IP_DSCP_MASK; |
7257b535 | 547 | break; |
530180fd JP |
548 | case MFF_IP_ECN: |
549 | mask->u8 = wc->tos_mask & IP_ECN_MASK; | |
550 | break; | |
7257b535 | 551 | case MFF_IP_FRAG: |
9e44d715 | 552 | mask->u8 = wc->frag_mask & FLOW_FRAG_MASK; |
7257b535 BP |
553 | break; |
554 | ||
6a885fd0 BP |
555 | case MFF_ARP_SPA: |
556 | mask->be32 = wc->nw_src_mask; | |
557 | break; | |
558 | case MFF_ARP_TPA: | |
559 | mask->be32 = wc->nw_dst_mask; | |
560 | break; | |
561 | ||
562 | case MFF_N_IDS: | |
563 | default: | |
564 | NOT_REACHED(); | |
565 | } | |
566 | } | |
567 | ||
568 | /* Tests whether 'mask' is a valid wildcard bit pattern for 'mf'. Returns true | |
569 | * if the mask is valid, false otherwise. */ | |
570 | bool | |
571 | mf_is_mask_valid(const struct mf_field *mf, const union mf_value *mask) | |
572 | { | |
573 | switch (mf->maskable) { | |
574 | case MFM_NONE: | |
575 | return (is_all_zeros((const uint8_t *) mask, mf->n_bytes) || | |
576 | is_all_ones((const uint8_t *) mask, mf->n_bytes)); | |
577 | ||
578 | case MFM_FULLY: | |
579 | return true; | |
580 | ||
581 | case MFM_CIDR: | |
582 | return (mf->n_bytes == 4 | |
583 | ? ip_is_cidr(mask->be32) | |
584 | : ipv6_is_cidr(&mask->ipv6)); | |
585 | ||
586 | case MFM_MCAST: | |
587 | return flow_wildcards_is_dl_dst_mask_valid(mask->mac); | |
588 | } | |
589 | ||
590 | NOT_REACHED(); | |
591 | } | |
592 | ||
593 | static bool | |
594 | is_ip_any(const struct flow *flow) | |
595 | { | |
596 | return (flow->dl_type == htons(ETH_TYPE_IP) || | |
597 | flow->dl_type == htons(ETH_TYPE_IPV6)); | |
598 | } | |
599 | ||
600 | static bool | |
601 | is_icmpv4(const struct flow *flow) | |
602 | { | |
603 | return (flow->dl_type == htons(ETH_TYPE_IP) | |
604 | && flow->nw_proto == IPPROTO_ICMP); | |
605 | } | |
606 | ||
607 | static bool | |
608 | is_icmpv6(const struct flow *flow) | |
609 | { | |
610 | return (flow->dl_type == htons(ETH_TYPE_IPV6) | |
611 | && flow->nw_proto == IPPROTO_ICMPV6); | |
612 | } | |
613 | ||
614 | /* Returns true if 'flow' meets the prerequisites for 'mf', false otherwise. */ | |
615 | bool | |
616 | mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow) | |
617 | { | |
618 | switch (mf->prereqs) { | |
619 | case MFP_NONE: | |
620 | return true; | |
621 | ||
622 | case MFP_ARP: | |
623 | return flow->dl_type == htons(ETH_TYPE_ARP); | |
624 | case MFP_IPV4: | |
625 | return flow->dl_type == htons(ETH_TYPE_IP); | |
626 | case MFP_IPV6: | |
627 | return flow->dl_type == htons(ETH_TYPE_IPV6); | |
628 | case MFP_IP_ANY: | |
629 | return is_ip_any(flow); | |
630 | ||
631 | case MFP_TCP: | |
632 | return is_ip_any(flow) && flow->nw_proto == IPPROTO_TCP; | |
633 | case MFP_UDP: | |
634 | return is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP; | |
635 | case MFP_ICMPV6: | |
636 | return is_icmpv6(flow); | |
637 | case MFP_ICMP_ANY: | |
638 | return is_icmpv4(flow) || is_icmpv6(flow); | |
639 | ||
640 | case MFP_ND: | |
641 | return (is_icmpv6(flow) | |
3ee8a9f0 BP |
642 | && flow->tp_dst == htons(0) |
643 | && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) || | |
644 | flow->tp_src == htons(ND_NEIGHBOR_ADVERT))); | |
6a885fd0 BP |
645 | case MFP_ND_SOLICIT: |
646 | return (is_icmpv6(flow) | |
3ee8a9f0 BP |
647 | && flow->tp_dst == htons(0) |
648 | && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT))); | |
6a885fd0 BP |
649 | case MFP_ND_ADVERT: |
650 | return (is_icmpv6(flow) | |
3ee8a9f0 BP |
651 | && flow->tp_dst == htons(0) |
652 | && (flow->tp_src == htons(ND_NEIGHBOR_ADVERT))); | |
6a885fd0 BP |
653 | } |
654 | ||
655 | NOT_REACHED(); | |
656 | } | |
657 | ||
658 | /* Returns true if 'value' may be a valid value *as part of a masked match*, | |
659 | * false otherwise. | |
660 | * | |
661 | * A value is not rejected just because it is not valid for the field in | |
662 | * question, but only if it doesn't make sense to test the bits in question at | |
663 | * all. For example, the MFF_VLAN_TCI field will never have a nonzero value | |
664 | * without the VLAN_CFI bit being set, but we can't reject those values because | |
665 | * it is still legitimate to test just for those bits (see the documentation | |
666 | * for NXM_OF_VLAN_TCI in nicira-ext.h). On the other hand, there is never a | |
530180fd | 667 | * reason to set the low bit of MFF_IP_DSCP to 1, so we reject that. */ |
6a885fd0 BP |
668 | bool |
669 | mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) | |
670 | { | |
671 | switch (mf->id) { | |
672 | case MFF_TUN_ID: | |
673 | case MFF_IN_PORT: | |
674 | #if FLOW_N_REGS > 0 | |
675 | case MFF_REG0: | |
676 | #endif | |
677 | #if FLOW_N_REGS > 1 | |
678 | case MFF_REG1: | |
679 | #endif | |
680 | #if FLOW_N_REGS > 2 | |
681 | case MFF_REG2: | |
682 | #endif | |
683 | #if FLOW_N_REGS > 3 | |
684 | case MFF_REG3: | |
685 | #endif | |
686 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
687 | case MFF_REG4: |
688 | #endif | |
689 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
690 | #error |
691 | #endif | |
692 | case MFF_ETH_SRC: | |
693 | case MFF_ETH_DST: | |
694 | case MFF_ETH_TYPE: | |
695 | case MFF_VLAN_TCI: | |
696 | case MFF_IPV4_SRC: | |
697 | case MFF_IPV4_DST: | |
698 | case MFF_IPV6_SRC: | |
699 | case MFF_IPV6_DST: | |
700 | case MFF_IP_PROTO: | |
a61680c6 | 701 | case MFF_IP_TTL: |
6a885fd0 BP |
702 | case MFF_ARP_SPA: |
703 | case MFF_ARP_TPA: | |
704 | case MFF_ARP_SHA: | |
705 | case MFF_ARP_THA: | |
706 | case MFF_TCP_SRC: | |
707 | case MFF_TCP_DST: | |
708 | case MFF_UDP_SRC: | |
709 | case MFF_UDP_DST: | |
710 | case MFF_ICMP_TYPE: | |
711 | case MFF_ICMP_CODE: | |
712 | case MFF_ND_TARGET: | |
713 | case MFF_ND_SLL: | |
714 | case MFF_ND_TLL: | |
715 | return true; | |
716 | ||
530180fd | 717 | case MFF_IP_DSCP: |
7257b535 | 718 | return !(value->u8 & ~IP_DSCP_MASK); |
530180fd JP |
719 | case MFF_IP_ECN: |
720 | return !(value->u8 & ~IP_ECN_MASK); | |
7257b535 BP |
721 | case MFF_IP_FRAG: |
722 | return !(value->u8 & ~FLOW_FRAG_MASK); | |
6a885fd0 BP |
723 | |
724 | case MFF_ARP_OP: | |
725 | return !(value->be16 & htons(0xff00)); | |
726 | ||
727 | case MFF_VLAN_VID: | |
728 | return !(value->be16 & htons(VLAN_CFI | VLAN_PCP_MASK)); | |
729 | ||
730 | case MFF_VLAN_PCP: | |
731 | return !(value->u8 & ~7); | |
732 | ||
fa8223b7 JP |
733 | case MFF_IPV6_LABEL: |
734 | return !(value->be32 & ~htonl(IPV6_LABEL_MASK)); | |
735 | ||
6a885fd0 BP |
736 | case MFF_N_IDS: |
737 | default: | |
738 | NOT_REACHED(); | |
739 | } | |
740 | } | |
741 | ||
742 | /* Copies the value of field 'mf' from 'flow' into 'value'. The caller is | |
743 | * responsible for ensuring that 'flow' meets 'mf''s prerequisites. */ | |
744 | void | |
745 | mf_get_value(const struct mf_field *mf, const struct flow *flow, | |
746 | union mf_value *value) | |
747 | { | |
748 | switch (mf->id) { | |
749 | case MFF_TUN_ID: | |
750 | value->be64 = flow->tun_id; | |
751 | break; | |
752 | ||
753 | case MFF_IN_PORT: | |
754 | value->be16 = htons(flow->in_port); | |
755 | break; | |
756 | ||
757 | #if FLOW_N_REGS > 0 | |
758 | case MFF_REG0: | |
759 | #endif | |
760 | #if FLOW_N_REGS > 1 | |
761 | case MFF_REG1: | |
762 | #endif | |
763 | #if FLOW_N_REGS > 2 | |
764 | case MFF_REG2: | |
765 | #endif | |
766 | #if FLOW_N_REGS > 3 | |
767 | case MFF_REG3: | |
768 | #endif | |
769 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
770 | case MFF_REG4: |
771 | #endif | |
772 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
773 | #error |
774 | #endif | |
2f98b0b7 | 775 | value->be32 = htonl(flow->regs[mf->id - MFF_REG0]); |
6a885fd0 BP |
776 | break; |
777 | ||
778 | case MFF_ETH_SRC: | |
779 | memcpy(value->mac, flow->dl_src, ETH_ADDR_LEN); | |
780 | break; | |
781 | ||
782 | case MFF_ETH_DST: | |
783 | memcpy(value->mac, flow->dl_dst, ETH_ADDR_LEN); | |
784 | break; | |
785 | ||
786 | case MFF_ETH_TYPE: | |
787 | value->be16 = flow->dl_type; | |
788 | break; | |
789 | ||
790 | case MFF_VLAN_TCI: | |
791 | value->be16 = flow->vlan_tci; | |
792 | break; | |
793 | ||
794 | case MFF_VLAN_VID: | |
795 | value->be16 = flow->vlan_tci & htons(VLAN_VID_MASK); | |
796 | break; | |
797 | ||
798 | case MFF_VLAN_PCP: | |
799 | value->u8 = vlan_tci_to_pcp(flow->vlan_tci); | |
800 | break; | |
801 | ||
802 | case MFF_IPV4_SRC: | |
803 | value->be32 = flow->nw_src; | |
804 | break; | |
805 | ||
806 | case MFF_IPV4_DST: | |
807 | value->be32 = flow->nw_dst; | |
808 | break; | |
809 | ||
810 | case MFF_IPV6_SRC: | |
811 | value->ipv6 = flow->ipv6_src; | |
812 | break; | |
813 | ||
814 | case MFF_IPV6_DST: | |
815 | value->ipv6 = flow->ipv6_dst; | |
816 | break; | |
817 | ||
fa8223b7 JP |
818 | case MFF_IPV6_LABEL: |
819 | value->be32 = flow->ipv6_label; | |
820 | break; | |
821 | ||
6a885fd0 BP |
822 | case MFF_IP_PROTO: |
823 | value->u8 = flow->nw_proto; | |
824 | break; | |
825 | ||
530180fd | 826 | case MFF_IP_DSCP: |
9e44d715 | 827 | value->u8 = flow->tos & IP_DSCP_MASK; |
7257b535 BP |
828 | break; |
829 | ||
530180fd JP |
830 | case MFF_IP_ECN: |
831 | value->u8 = flow->tos & IP_ECN_MASK; | |
832 | break; | |
833 | ||
a61680c6 JP |
834 | case MFF_IP_TTL: |
835 | value->u8 = flow->nw_ttl; | |
836 | break; | |
837 | ||
7257b535 | 838 | case MFF_IP_FRAG: |
9e44d715 | 839 | value->u8 = flow->frag; |
6a885fd0 BP |
840 | break; |
841 | ||
842 | case MFF_ARP_OP: | |
843 | value->be16 = htons(flow->nw_proto); | |
844 | break; | |
845 | ||
846 | case MFF_ARP_SPA: | |
847 | value->be32 = flow->nw_src; | |
848 | break; | |
849 | ||
850 | case MFF_ARP_TPA: | |
851 | value->be32 = flow->nw_dst; | |
852 | break; | |
853 | ||
854 | case MFF_ARP_SHA: | |
855 | case MFF_ND_SLL: | |
856 | memcpy(value->mac, flow->arp_sha, ETH_ADDR_LEN); | |
857 | break; | |
858 | ||
859 | case MFF_ARP_THA: | |
860 | case MFF_ND_TLL: | |
861 | memcpy(value->mac, flow->arp_tha, ETH_ADDR_LEN); | |
862 | break; | |
863 | ||
864 | case MFF_TCP_SRC: | |
865 | value->be16 = flow->tp_src; | |
866 | break; | |
867 | ||
868 | case MFF_TCP_DST: | |
869 | value->be16 = flow->tp_dst; | |
870 | break; | |
871 | ||
872 | case MFF_UDP_SRC: | |
873 | value->be16 = flow->tp_src; | |
874 | break; | |
875 | ||
876 | case MFF_UDP_DST: | |
877 | value->be16 = flow->tp_dst; | |
878 | break; | |
879 | ||
880 | case MFF_ICMP_TYPE: | |
881 | value->u8 = ntohs(flow->tp_src); | |
882 | break; | |
883 | ||
884 | case MFF_ICMP_CODE: | |
885 | value->u8 = ntohs(flow->tp_dst); | |
886 | break; | |
887 | ||
888 | case MFF_ND_TARGET: | |
889 | value->ipv6 = flow->nd_target; | |
890 | break; | |
891 | ||
892 | case MFF_N_IDS: | |
893 | default: | |
894 | NOT_REACHED(); | |
895 | } | |
896 | } | |
897 | ||
898 | /* Makes 'rule' match field 'mf' exactly, with the value matched taken from | |
899 | * 'value'. The caller is responsible for ensuring that 'rule' meets 'mf''s | |
900 | * prerequisites. */ | |
901 | void | |
902 | mf_set_value(const struct mf_field *mf, | |
903 | const union mf_value *value, struct cls_rule *rule) | |
904 | { | |
905 | switch (mf->id) { | |
906 | case MFF_TUN_ID: | |
907 | cls_rule_set_tun_id(rule, value->be64); | |
908 | break; | |
909 | ||
910 | case MFF_IN_PORT: | |
911 | cls_rule_set_in_port(rule, ntohs(value->be16)); | |
912 | break; | |
913 | ||
914 | #if FLOW_N_REGS > 0 | |
915 | case MFF_REG0: | |
916 | #endif | |
917 | #if FLOW_N_REGS > 1 | |
918 | case MFF_REG1: | |
919 | #endif | |
920 | #if FLOW_N_REGS > 2 | |
921 | case MFF_REG2: | |
922 | #endif | |
923 | #if FLOW_N_REGS > 3 | |
924 | case MFF_REG3: | |
925 | #endif | |
926 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
927 | case MFF_REG4: |
928 | #endif | |
929 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
930 | #error |
931 | #endif | |
932 | #if FLOW_N_REGS > 0 | |
933 | cls_rule_set_reg(rule, mf->id - MFF_REG0, ntohl(value->be32)); | |
934 | break; | |
935 | #endif | |
936 | ||
937 | case MFF_ETH_SRC: | |
938 | cls_rule_set_dl_src(rule, value->mac); | |
939 | break; | |
940 | ||
941 | case MFF_ETH_DST: | |
942 | cls_rule_set_dl_dst(rule, value->mac); | |
943 | break; | |
944 | ||
945 | case MFF_ETH_TYPE: | |
946 | cls_rule_set_dl_type(rule, value->be16); | |
947 | break; | |
948 | ||
949 | case MFF_VLAN_TCI: | |
950 | cls_rule_set_dl_tci(rule, value->be16); | |
951 | break; | |
952 | ||
953 | case MFF_VLAN_VID: | |
954 | cls_rule_set_dl_vlan(rule, value->be16); | |
955 | break; | |
956 | ||
957 | case MFF_VLAN_PCP: | |
958 | cls_rule_set_dl_vlan_pcp(rule, value->u8); | |
959 | break; | |
960 | ||
961 | case MFF_IPV4_SRC: | |
962 | cls_rule_set_nw_src(rule, value->be32); | |
963 | break; | |
964 | ||
965 | case MFF_IPV4_DST: | |
966 | cls_rule_set_nw_dst(rule, value->be32); | |
967 | break; | |
968 | ||
969 | case MFF_IPV6_SRC: | |
970 | cls_rule_set_ipv6_src(rule, &value->ipv6); | |
971 | break; | |
972 | ||
973 | case MFF_IPV6_DST: | |
974 | cls_rule_set_ipv6_dst(rule, &value->ipv6); | |
975 | break; | |
976 | ||
fa8223b7 JP |
977 | case MFF_IPV6_LABEL: |
978 | cls_rule_set_ipv6_label(rule, value->be32); | |
979 | break; | |
980 | ||
6a885fd0 BP |
981 | case MFF_IP_PROTO: |
982 | cls_rule_set_nw_proto(rule, value->u8); | |
983 | break; | |
984 | ||
530180fd JP |
985 | case MFF_IP_DSCP: |
986 | cls_rule_set_nw_dscp(rule, value->u8); | |
987 | break; | |
988 | ||
989 | case MFF_IP_ECN: | |
990 | cls_rule_set_nw_ecn(rule, value->u8); | |
6a885fd0 BP |
991 | break; |
992 | ||
a61680c6 JP |
993 | case MFF_IP_TTL: |
994 | cls_rule_set_nw_ttl(rule, value->u8); | |
995 | break; | |
996 | ||
7257b535 BP |
997 | case MFF_IP_FRAG: |
998 | cls_rule_set_frag(rule, value->u8); | |
999 | break; | |
1000 | ||
6a885fd0 BP |
1001 | case MFF_ARP_OP: |
1002 | cls_rule_set_nw_proto(rule, ntohs(value->be16)); | |
1003 | break; | |
1004 | ||
1005 | case MFF_ARP_SPA: | |
1006 | cls_rule_set_nw_src(rule, value->be32); | |
1007 | break; | |
1008 | ||
1009 | case MFF_ARP_TPA: | |
1010 | cls_rule_set_nw_dst(rule, value->be32); | |
1011 | break; | |
1012 | ||
1013 | case MFF_ARP_SHA: | |
1014 | case MFF_ND_SLL: | |
1015 | cls_rule_set_arp_sha(rule, value->mac); | |
1016 | break; | |
1017 | ||
1018 | case MFF_ARP_THA: | |
1019 | case MFF_ND_TLL: | |
1020 | cls_rule_set_arp_tha(rule, value->mac); | |
1021 | break; | |
1022 | ||
1023 | case MFF_TCP_SRC: | |
1024 | cls_rule_set_tp_src(rule, value->be16); | |
1025 | break; | |
1026 | ||
1027 | case MFF_TCP_DST: | |
1028 | cls_rule_set_tp_dst(rule, value->be16); | |
1029 | break; | |
1030 | ||
1031 | case MFF_UDP_SRC: | |
1032 | cls_rule_set_tp_src(rule, value->be16); | |
1033 | break; | |
1034 | ||
1035 | case MFF_UDP_DST: | |
1036 | cls_rule_set_tp_dst(rule, value->be16); | |
1037 | break; | |
1038 | ||
1039 | case MFF_ICMP_TYPE: | |
1040 | cls_rule_set_icmp_type(rule, value->u8); | |
1041 | break; | |
1042 | ||
1043 | case MFF_ICMP_CODE: | |
1044 | cls_rule_set_icmp_code(rule, value->u8); | |
1045 | break; | |
1046 | ||
1047 | case MFF_ND_TARGET: | |
1048 | cls_rule_set_nd_target(rule, &value->ipv6); | |
1049 | break; | |
1050 | ||
1051 | case MFF_N_IDS: | |
1052 | default: | |
1053 | NOT_REACHED(); | |
1054 | } | |
1055 | } | |
1056 | ||
1057 | /* Makes 'rule' wildcard field 'mf'. | |
1058 | * | |
1059 | * The caller is responsible for ensuring that 'rule' meets 'mf''s | |
1060 | * prerequisites. */ | |
1061 | void | |
1062 | mf_set_wild(const struct mf_field *mf, struct cls_rule *rule) | |
1063 | { | |
1064 | switch (mf->id) { | |
1065 | case MFF_TUN_ID: | |
1066 | cls_rule_set_tun_id_masked(rule, htonll(0), htonll(0)); | |
1067 | break; | |
1068 | ||
1069 | case MFF_IN_PORT: | |
1070 | rule->wc.wildcards |= FWW_IN_PORT; | |
1071 | rule->flow.in_port = 0; | |
1072 | break; | |
1073 | ||
1074 | #if FLOW_N_REGS > 0 | |
1075 | case MFF_REG0: | |
1076 | cls_rule_set_reg_masked(rule, 0, 0, 0); | |
1077 | break; | |
1078 | #endif | |
1079 | #if FLOW_N_REGS > 1 | |
1080 | case MFF_REG1: | |
1081 | cls_rule_set_reg_masked(rule, 1, 0, 0); | |
1082 | break; | |
1083 | #endif | |
1084 | #if FLOW_N_REGS > 2 | |
1085 | case MFF_REG2: | |
1086 | cls_rule_set_reg_masked(rule, 2, 0, 0); | |
1087 | break; | |
1088 | #endif | |
1089 | #if FLOW_N_REGS > 3 | |
1090 | case MFF_REG3: | |
1091 | cls_rule_set_reg_masked(rule, 3, 0, 0); | |
1092 | break; | |
1093 | #endif | |
1094 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
1095 | case MFF_REG4: |
1096 | cls_rule_set_reg_masked(rule, 4, 0, 0); | |
1097 | break; | |
1098 | #endif | |
1099 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
1100 | #error |
1101 | #endif | |
1102 | ||
1103 | case MFF_ETH_SRC: | |
1104 | rule->wc.wildcards |= FWW_DL_SRC; | |
1105 | memset(rule->flow.dl_src, 0, sizeof rule->flow.dl_src); | |
1106 | break; | |
1107 | ||
1108 | case MFF_ETH_DST: | |
1109 | rule->wc.wildcards |= FWW_DL_DST | FWW_ETH_MCAST; | |
1110 | memset(rule->flow.dl_dst, 0, sizeof rule->flow.dl_dst); | |
1111 | break; | |
1112 | ||
1113 | case MFF_ETH_TYPE: | |
1114 | rule->wc.wildcards |= FWW_DL_TYPE; | |
1115 | rule->flow.dl_type = htons(0); | |
1116 | break; | |
1117 | ||
1118 | case MFF_VLAN_TCI: | |
1119 | cls_rule_set_dl_tci_masked(rule, htons(0), htons(0)); | |
1120 | break; | |
1121 | ||
1122 | case MFF_VLAN_VID: | |
1123 | cls_rule_set_any_vid(rule); | |
1124 | break; | |
1125 | ||
1126 | case MFF_VLAN_PCP: | |
1127 | cls_rule_set_any_pcp(rule); | |
1128 | break; | |
1129 | ||
1130 | case MFF_IPV4_SRC: | |
1131 | case MFF_ARP_SPA: | |
1132 | cls_rule_set_nw_src_masked(rule, htonl(0), htonl(0)); | |
1133 | break; | |
1134 | ||
1135 | case MFF_IPV4_DST: | |
1136 | case MFF_ARP_TPA: | |
1137 | cls_rule_set_nw_dst_masked(rule, htonl(0), htonl(0)); | |
1138 | break; | |
1139 | ||
1140 | case MFF_IPV6_SRC: | |
1141 | memset(&rule->wc.ipv6_src_mask, 0, sizeof rule->wc.ipv6_src_mask); | |
1142 | memset(&rule->flow.ipv6_src, 0, sizeof rule->flow.ipv6_src); | |
1143 | break; | |
1144 | ||
1145 | case MFF_IPV6_DST: | |
1146 | memset(&rule->wc.ipv6_dst_mask, 0, sizeof rule->wc.ipv6_dst_mask); | |
1147 | memset(&rule->flow.ipv6_dst, 0, sizeof rule->flow.ipv6_dst); | |
1148 | break; | |
1149 | ||
fa8223b7 JP |
1150 | case MFF_IPV6_LABEL: |
1151 | rule->wc.wildcards |= FWW_IPV6_LABEL; | |
1152 | rule->flow.ipv6_label = 0; | |
1153 | break; | |
1154 | ||
6a885fd0 BP |
1155 | case MFF_IP_PROTO: |
1156 | rule->wc.wildcards |= FWW_NW_PROTO; | |
1157 | rule->flow.nw_proto = 0; | |
1158 | break; | |
1159 | ||
530180fd | 1160 | case MFF_IP_DSCP: |
9e44d715 JP |
1161 | rule->wc.tos_mask |= IP_DSCP_MASK; |
1162 | rule->flow.tos &= ~IP_DSCP_MASK; | |
7257b535 BP |
1163 | break; |
1164 | ||
530180fd JP |
1165 | case MFF_IP_ECN: |
1166 | rule->wc.tos_mask |= IP_ECN_MASK; | |
1167 | rule->flow.tos &= ~IP_ECN_MASK; | |
1168 | break; | |
1169 | ||
a61680c6 JP |
1170 | case MFF_IP_TTL: |
1171 | rule->wc.wildcards |= FWW_NW_TTL; | |
1172 | rule->flow.nw_ttl = 0; | |
1173 | break; | |
1174 | ||
7257b535 | 1175 | case MFF_IP_FRAG: |
9e44d715 JP |
1176 | rule->wc.frag_mask |= FLOW_FRAG_MASK; |
1177 | rule->flow.frag &= ~FLOW_FRAG_MASK; | |
6a885fd0 BP |
1178 | break; |
1179 | ||
1180 | case MFF_ARP_OP: | |
1181 | rule->wc.wildcards |= FWW_NW_PROTO; | |
1182 | rule->flow.nw_proto = 0; | |
1183 | break; | |
1184 | ||
1185 | case MFF_ARP_SHA: | |
1186 | case MFF_ND_SLL: | |
1187 | rule->wc.wildcards |= FWW_ARP_SHA; | |
1188 | memset(rule->flow.arp_sha, 0, sizeof rule->flow.arp_sha); | |
1189 | break; | |
1190 | ||
1191 | case MFF_ARP_THA: | |
1192 | case MFF_ND_TLL: | |
1193 | rule->wc.wildcards |= FWW_ARP_THA; | |
1194 | memset(rule->flow.arp_tha, 0, sizeof rule->flow.arp_tha); | |
1195 | break; | |
1196 | ||
1197 | case MFF_TCP_SRC: | |
1198 | case MFF_UDP_SRC: | |
1199 | case MFF_ICMP_TYPE: | |
1200 | rule->wc.wildcards |= FWW_TP_SRC; | |
1201 | rule->flow.tp_src = htons(0); | |
1202 | break; | |
1203 | ||
1204 | case MFF_TCP_DST: | |
1205 | case MFF_UDP_DST: | |
1206 | case MFF_ICMP_CODE: | |
1207 | rule->wc.wildcards |= FWW_TP_DST; | |
1208 | rule->flow.tp_dst = htons(0); | |
1209 | break; | |
1210 | ||
1211 | case MFF_ND_TARGET: | |
1212 | rule->wc.wildcards |= FWW_ND_TARGET; | |
1213 | memset(&rule->flow.nd_target, 0, sizeof rule->flow.nd_target); | |
1214 | break; | |
1215 | ||
1216 | case MFF_N_IDS: | |
1217 | default: | |
1218 | NOT_REACHED(); | |
1219 | } | |
1220 | } | |
1221 | ||
1222 | /* Makes 'rule' match field 'mf' with the specified 'value' and 'mask'. | |
1223 | * 'value' specifies a value to match and 'mask' specifies a wildcard pattern, | |
1224 | * with a 1-bit indicating that the corresponding value bit must match and a | |
1225 | * 0-bit indicating a don't-care. | |
1226 | * | |
1227 | * If 'mask' is NULL or points to all-1-bits, then this call is equivalent to | |
1228 | * mf_set_value(mf, value, rule). If 'mask' points to all-0-bits, then this | |
1229 | * call is equivalent to mf_set_wild(mf, rule). | |
1230 | * | |
1231 | * 'mask' must be a valid mask for 'mf' (see mf_is_mask_valid()). The caller | |
1232 | * is responsible for ensuring that 'rule' meets 'mf''s prerequisites. */ | |
1233 | void | |
1234 | mf_set(const struct mf_field *mf, | |
1235 | const union mf_value *value, const union mf_value *mask, | |
1236 | struct cls_rule *rule) | |
1237 | { | |
1238 | if (!mask || is_all_ones((const uint8_t *) mask, mf->n_bytes)) { | |
1239 | mf_set_value(mf, value, rule); | |
1240 | return; | |
1241 | } else if (is_all_zeros((const uint8_t *) mask, mf->n_bytes)) { | |
1242 | mf_set_wild(mf, rule); | |
1243 | return; | |
1244 | } | |
1245 | ||
1246 | switch (mf->id) { | |
1247 | case MFF_IN_PORT: | |
1248 | case MFF_ETH_SRC: | |
1249 | case MFF_ETH_TYPE: | |
1250 | case MFF_VLAN_VID: | |
1251 | case MFF_VLAN_PCP: | |
fa8223b7 | 1252 | case MFF_IPV6_LABEL: |
6a885fd0 | 1253 | case MFF_IP_PROTO: |
a61680c6 | 1254 | case MFF_IP_TTL: |
530180fd JP |
1255 | case MFF_IP_DSCP: |
1256 | case MFF_IP_ECN: | |
6a885fd0 BP |
1257 | case MFF_ARP_OP: |
1258 | case MFF_ARP_SHA: | |
1259 | case MFF_ARP_THA: | |
1260 | case MFF_TCP_SRC: | |
1261 | case MFF_TCP_DST: | |
1262 | case MFF_UDP_SRC: | |
1263 | case MFF_UDP_DST: | |
1264 | case MFF_ICMP_TYPE: | |
1265 | case MFF_ICMP_CODE: | |
1266 | case MFF_ND_TARGET: | |
1267 | case MFF_ND_SLL: | |
1268 | case MFF_ND_TLL: | |
1269 | NOT_REACHED(); | |
1270 | ||
1271 | case MFF_TUN_ID: | |
1272 | cls_rule_set_tun_id_masked(rule, value->be64, mask->be64); | |
1273 | break; | |
1274 | ||
1275 | #if FLOW_N_REGS > 0 | |
1276 | case MFF_REG0: | |
1277 | #endif | |
1278 | #if FLOW_N_REGS > 1 | |
1279 | case MFF_REG1: | |
1280 | #endif | |
1281 | #if FLOW_N_REGS > 2 | |
1282 | case MFF_REG2: | |
1283 | #endif | |
1284 | #if FLOW_N_REGS > 3 | |
1285 | case MFF_REG3: | |
1286 | #endif | |
1287 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
1288 | case MFF_REG4: |
1289 | #endif | |
1290 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
1291 | #error |
1292 | #endif | |
1293 | cls_rule_set_reg_masked(rule, mf->id - MFF_REG0, | |
1294 | ntohl(value->be32), ntohl(mask->be32)); | |
1295 | break; | |
1296 | ||
1297 | case MFF_ETH_DST: | |
1298 | if (flow_wildcards_is_dl_dst_mask_valid(mask->mac)) { | |
1299 | cls_rule_set_dl_dst_masked(rule, value->mac, mask->mac); | |
1300 | } | |
1301 | break; | |
1302 | ||
1303 | case MFF_VLAN_TCI: | |
1304 | cls_rule_set_dl_tci_masked(rule, value->be16, mask->be16); | |
1305 | break; | |
1306 | ||
1307 | case MFF_IPV4_SRC: | |
1308 | cls_rule_set_nw_src_masked(rule, value->be32, mask->be32); | |
1309 | break; | |
1310 | ||
1311 | case MFF_IPV4_DST: | |
1312 | cls_rule_set_nw_dst_masked(rule, value->be32, mask->be32); | |
1313 | break; | |
1314 | ||
1315 | case MFF_IPV6_SRC: | |
1316 | cls_rule_set_ipv6_src_masked(rule, &value->ipv6, &mask->ipv6); | |
1317 | break; | |
1318 | ||
1319 | case MFF_IPV6_DST: | |
1320 | cls_rule_set_ipv6_dst_masked(rule, &value->ipv6, &mask->ipv6); | |
1321 | break; | |
1322 | ||
7257b535 BP |
1323 | case MFF_IP_FRAG: |
1324 | cls_rule_set_frag_masked(rule, value->u8, mask->u8); | |
1325 | break; | |
1326 | ||
6a885fd0 BP |
1327 | case MFF_ARP_SPA: |
1328 | cls_rule_set_nw_src_masked(rule, value->be32, mask->be32); | |
1329 | break; | |
1330 | ||
1331 | case MFF_ARP_TPA: | |
1332 | cls_rule_set_nw_dst_masked(rule, value->be32, mask->be32); | |
1333 | break; | |
1334 | ||
1335 | case MFF_N_IDS: | |
1336 | default: | |
1337 | NOT_REACHED(); | |
1338 | } | |
1339 | } | |
1340 | ||
1341 | /* Makes a subfield starting at bit offset 'ofs' and continuing for 'n_bits' in | |
1342 | * 'rule''s field 'mf' exactly match the 'n_bits' least-significant bits of | |
1343 | * 'x'. | |
1344 | * | |
1345 | * Example: suppose that 'mf' is originally the following 2-byte field in | |
1346 | * 'rule': | |
1347 | * | |
1348 | * value == 0xe00a == 2#1110000000001010 | |
1349 | * mask == 0xfc3f == 2#1111110000111111 | |
1350 | * | |
1351 | * The call mf_set_subfield(mf, 0x55, 8, 7, rule) would have the following | |
1352 | * effect (note that 0x55 is 2#1010101): | |
1353 | * | |
1354 | * value == 0xd50a == 2#1101010100001010 | |
1355 | * mask == 0xff3f == 2#1111111100111111 | |
1356 | * | |
1357 | * The caller is responsible for ensuring that the result will be a valid | |
1358 | * wildcard pattern for 'mf'. The caller is responsible for ensuring that | |
1359 | * 'rule' meets 'mf''s prerequisites. */ | |
1360 | void | |
1361 | mf_set_subfield(const struct mf_field *mf, uint64_t x, unsigned int ofs, | |
1362 | unsigned int n_bits, struct cls_rule *rule) | |
1363 | { | |
1364 | if (ofs == 0 && mf->n_bytes * 8 == n_bits) { | |
1365 | union mf_value value; | |
1366 | int i; | |
1367 | ||
1368 | for (i = mf->n_bytes - 1; i >= 0; i--) { | |
1369 | ((uint8_t *) &value)[i] = x; | |
1370 | x >>= 8; | |
1371 | } | |
1372 | mf_set_value(mf, &value, rule); | |
1373 | } else { | |
1374 | union mf_value value, mask; | |
1375 | uint8_t *vp, *mp; | |
1376 | unsigned int byte_ofs; | |
1377 | ||
1378 | mf_get(mf, rule, &value, &mask); | |
1379 | ||
1380 | byte_ofs = mf->n_bytes - ofs / 8; | |
1381 | vp = &((uint8_t *) &value)[byte_ofs]; | |
1382 | mp = &((uint8_t *) &mask)[byte_ofs]; | |
1383 | if (ofs % 8) { | |
1384 | unsigned int chunk = MIN(8 - ofs % 8, n_bits); | |
1385 | uint8_t chunk_mask = ((1 << chunk) - 1) << (ofs % 8); | |
1386 | ||
1387 | *--vp &= ~chunk_mask; | |
1388 | *vp |= chunk_mask & (x << (ofs % 8)); | |
1389 | *--mp |= chunk_mask; | |
1390 | ||
1391 | x >>= chunk; | |
1392 | n_bits -= chunk; | |
1393 | ofs += chunk; | |
1394 | } | |
1395 | while (n_bits >= 8) { | |
1396 | *--vp = x; | |
1397 | *--mp = 0xff; | |
1398 | x >>= 8; | |
1399 | n_bits -= 8; | |
1400 | ofs += 8; | |
1401 | } | |
1402 | if (n_bits) { | |
1403 | uint8_t chunk_mask = (1 << n_bits) - 1; | |
1404 | ||
1405 | *--vp &= ~chunk_mask; | |
1406 | *vp |= chunk_mask & x; | |
1407 | *--mp |= chunk_mask; | |
1408 | } | |
1409 | ||
1410 | mf_set(mf, &value, &mask, rule); | |
1411 | } | |
1412 | } | |
1413 | ||
1414 | /* Copies the value and wildcard bit pattern for 'mf' from 'rule' into the | |
1415 | * 'value' and 'mask', respectively. */ | |
1416 | void | |
1417 | mf_get(const struct mf_field *mf, const struct cls_rule *rule, | |
1418 | union mf_value *value, union mf_value *mask) | |
1419 | { | |
1420 | mf_get_value(mf, &rule->flow, value); | |
1421 | mf_get_mask(mf, &rule->wc, mask); | |
1422 | } | |
1423 | ||
1424 | /* Assigns a random value for field 'mf' to 'value'. */ | |
1425 | void | |
1426 | mf_random_value(const struct mf_field *mf, union mf_value *value) | |
1427 | { | |
1428 | random_bytes(value, mf->n_bytes); | |
1429 | ||
1430 | switch (mf->id) { | |
1431 | case MFF_TUN_ID: | |
1432 | case MFF_IN_PORT: | |
1433 | #if FLOW_N_REGS > 0 | |
1434 | case MFF_REG0: | |
1435 | #endif | |
1436 | #if FLOW_N_REGS > 1 | |
1437 | case MFF_REG1: | |
1438 | #endif | |
1439 | #if FLOW_N_REGS > 2 | |
1440 | case MFF_REG2: | |
1441 | #endif | |
1442 | #if FLOW_N_REGS > 3 | |
1443 | case MFF_REG3: | |
1444 | #endif | |
1445 | #if FLOW_N_REGS > 4 | |
d2c0fed9 JP |
1446 | case MFF_REG4: |
1447 | #endif | |
1448 | #if FLOW_N_REGS > 5 | |
6a885fd0 BP |
1449 | #error |
1450 | #endif | |
1451 | case MFF_ETH_SRC: | |
1452 | case MFF_ETH_DST: | |
1453 | case MFF_ETH_TYPE: | |
1454 | case MFF_VLAN_TCI: | |
1455 | case MFF_IPV4_SRC: | |
1456 | case MFF_IPV4_DST: | |
1457 | case MFF_IPV6_SRC: | |
1458 | case MFF_IPV6_DST: | |
1459 | case MFF_IP_PROTO: | |
a61680c6 | 1460 | case MFF_IP_TTL: |
6a885fd0 BP |
1461 | case MFF_ARP_SPA: |
1462 | case MFF_ARP_TPA: | |
1463 | case MFF_ARP_SHA: | |
1464 | case MFF_ARP_THA: | |
1465 | case MFF_TCP_SRC: | |
1466 | case MFF_TCP_DST: | |
1467 | case MFF_UDP_SRC: | |
1468 | case MFF_UDP_DST: | |
1469 | case MFF_ICMP_TYPE: | |
1470 | case MFF_ICMP_CODE: | |
1471 | case MFF_ND_TARGET: | |
1472 | case MFF_ND_SLL: | |
1473 | case MFF_ND_TLL: | |
1474 | break; | |
1475 | ||
fa8223b7 JP |
1476 | case MFF_IPV6_LABEL: |
1477 | value->be32 &= ~htonl(IPV6_LABEL_MASK); | |
1478 | break; | |
1479 | ||
530180fd JP |
1480 | case MFF_IP_DSCP: |
1481 | value->u8 &= IP_DSCP_MASK; | |
1482 | break; | |
1483 | ||
1484 | case MFF_IP_ECN: | |
1485 | value->u8 &= IP_ECN_MASK; | |
6a885fd0 BP |
1486 | break; |
1487 | ||
7257b535 BP |
1488 | case MFF_IP_FRAG: |
1489 | value->u8 &= FLOW_FRAG_MASK; | |
1490 | break; | |
1491 | ||
6a885fd0 BP |
1492 | case MFF_ARP_OP: |
1493 | value->be16 &= htons(0xff); | |
1494 | break; | |
1495 | ||
1496 | case MFF_VLAN_VID: | |
1497 | value->be16 &= htons(VLAN_VID_MASK); | |
1498 | break; | |
1499 | ||
1500 | case MFF_VLAN_PCP: | |
1501 | value->u8 &= 0x07; | |
1502 | break; | |
1503 | ||
1504 | case MFF_N_IDS: | |
1505 | default: | |
1506 | NOT_REACHED(); | |
1507 | } | |
1508 | } | |
1509 | ||
1510 | static char * | |
1511 | mf_from_integer_string(const struct mf_field *mf, const char *s, | |
1512 | uint8_t *valuep, uint8_t *maskp) | |
1513 | { | |
1514 | unsigned long long int integer, mask; | |
1515 | char *tail; | |
1516 | int i; | |
1517 | ||
1518 | errno = 0; | |
1519 | integer = strtoull(s, &tail, 0); | |
1520 | if (errno || (*tail != '\0' && *tail != '/')) { | |
1521 | goto syntax_error; | |
1522 | } | |
1523 | ||
1524 | if (*tail == '/') { | |
1525 | mask = strtoull(tail + 1, &tail, 0); | |
1526 | if (errno || *tail != '\0') { | |
1527 | goto syntax_error; | |
1528 | } | |
1529 | } else { | |
1530 | mask = ULLONG_MAX; | |
1531 | } | |
1532 | ||
1533 | for (i = mf->n_bytes - 1; i >= 0; i--) { | |
1534 | valuep[i] = integer; | |
1535 | maskp[i] = mask; | |
1536 | integer >>= 8; | |
1537 | mask >>= 8; | |
1538 | } | |
1539 | if (integer) { | |
1540 | return xasprintf("%s: value too large for %u-byte field %s", | |
1541 | s, mf->n_bytes, mf->name); | |
1542 | } | |
1543 | return NULL; | |
1544 | ||
1545 | syntax_error: | |
1546 | return xasprintf("%s: bad syntax for %s", s, mf->name); | |
1547 | } | |
1548 | ||
1549 | static char * | |
1550 | mf_from_ethernet_string(const struct mf_field *mf, const char *s, | |
1551 | uint8_t mac[ETH_ADDR_LEN], | |
1552 | uint8_t mask[ETH_ADDR_LEN]) | |
1553 | { | |
1554 | assert(mf->n_bytes == ETH_ADDR_LEN); | |
1555 | ||
1556 | switch (sscanf(s, ETH_ADDR_SCAN_FMT"/"ETH_ADDR_SCAN_FMT, | |
1557 | ETH_ADDR_SCAN_ARGS(mac), ETH_ADDR_SCAN_ARGS(mask))){ | |
1558 | case ETH_ADDR_SCAN_COUNT * 2: | |
1559 | return NULL; | |
1560 | ||
1561 | case ETH_ADDR_SCAN_COUNT: | |
1562 | memset(mask, 0xff, ETH_ADDR_LEN); | |
1563 | return NULL; | |
1564 | ||
1565 | default: | |
1566 | return xasprintf("%s: invalid Ethernet address", s); | |
1567 | } | |
1568 | } | |
1569 | ||
1570 | static char * | |
1571 | mf_from_ipv4_string(const struct mf_field *mf, const char *s, | |
1572 | ovs_be32 *ip, ovs_be32 *mask) | |
1573 | { | |
1574 | int prefix; | |
1575 | ||
1576 | assert(mf->n_bytes == sizeof *ip); | |
1577 | ||
1578 | if (sscanf(s, IP_SCAN_FMT"/"IP_SCAN_FMT, | |
1579 | IP_SCAN_ARGS(ip), IP_SCAN_ARGS(mask)) == IP_SCAN_COUNT * 2) { | |
1580 | /* OK. */ | |
1581 | } else if (sscanf(s, IP_SCAN_FMT"/%d", | |
1582 | IP_SCAN_ARGS(ip), &prefix) == IP_SCAN_COUNT + 1) { | |
1583 | if (prefix <= 0 || prefix > 32) { | |
1584 | return xasprintf("%s: network prefix bits not between 1 and " | |
1585 | "32", s); | |
1586 | } else if (prefix == 32) { | |
1587 | *mask = htonl(UINT32_MAX); | |
1588 | } else { | |
1589 | *mask = htonl(((1u << prefix) - 1) << (32 - prefix)); | |
1590 | } | |
1591 | } else if (sscanf(s, IP_SCAN_FMT, IP_SCAN_ARGS(ip)) == IP_SCAN_COUNT) { | |
1592 | *mask = htonl(UINT32_MAX); | |
1593 | } else { | |
1594 | return xasprintf("%s: invalid IP address", s); | |
1595 | } | |
1596 | return NULL; | |
1597 | } | |
1598 | ||
1599 | static char * | |
1600 | mf_from_ipv6_string(const struct mf_field *mf, const char *s, | |
1601 | struct in6_addr *value, struct in6_addr *mask) | |
1602 | { | |
1603 | char *str = xstrdup(s); | |
1604 | char *save_ptr = NULL; | |
1605 | const char *name, *netmask; | |
1606 | int retval; | |
1607 | ||
1608 | assert(mf->n_bytes == sizeof *value); | |
1609 | ||
1610 | name = strtok_r(str, "/", &save_ptr); | |
1611 | retval = name ? lookup_ipv6(name, value) : EINVAL; | |
1612 | if (retval) { | |
1613 | char *err; | |
1614 | ||
1615 | err = xasprintf("%s: could not convert to IPv6 address", str); | |
1616 | free(str); | |
1617 | ||
1618 | return err; | |
1619 | } | |
1620 | ||
1621 | netmask = strtok_r(NULL, "/", &save_ptr); | |
1622 | if (netmask) { | |
1623 | int prefix = atoi(netmask); | |
1624 | if (prefix <= 0 || prefix > 128) { | |
1625 | free(str); | |
1626 | return xasprintf("%s: prefix bits not between 1 and 128", s); | |
1627 | } else { | |
1628 | *mask = ipv6_create_mask(prefix); | |
1629 | } | |
1630 | } else { | |
1631 | *mask = in6addr_exact; | |
1632 | } | |
1633 | free(str); | |
1634 | ||
1635 | return NULL; | |
1636 | } | |
1637 | ||
1638 | static char * | |
1639 | mf_from_ofp_port_string(const struct mf_field *mf, const char *s, | |
1640 | ovs_be16 *valuep, ovs_be16 *maskp) | |
1641 | { | |
1642 | uint16_t port; | |
1643 | ||
1644 | assert(mf->n_bytes == sizeof(ovs_be16)); | |
1645 | if (ofputil_port_from_string(s, &port)) { | |
1646 | *valuep = htons(port); | |
1647 | *maskp = htons(UINT16_MAX); | |
1648 | return NULL; | |
1649 | } else { | |
1650 | return mf_from_integer_string(mf, s, | |
1651 | (uint8_t *) valuep, (uint8_t *) maskp); | |
1652 | } | |
1653 | } | |
1654 | ||
7257b535 BP |
1655 | struct frag_handling { |
1656 | const char *name; | |
1657 | uint8_t mask; | |
1658 | uint8_t value; | |
1659 | }; | |
1660 | ||
1661 | static const struct frag_handling all_frags[] = { | |
1662 | #define A FLOW_FRAG_ANY | |
1663 | #define L FLOW_FRAG_LATER | |
1664 | /* name mask value */ | |
1665 | ||
1666 | { "no", A|L, 0 }, | |
1667 | { "first", A|L, A }, | |
1668 | { "later", A|L, A|L }, | |
1669 | ||
1670 | { "no", A, 0 }, | |
1671 | { "yes", A, A }, | |
1672 | ||
1673 | { "not_later", L, 0 }, | |
1674 | { "later", L, L }, | |
1675 | #undef A | |
1676 | #undef L | |
1677 | }; | |
1678 | ||
1679 | static char * | |
1680 | mf_from_frag_string(const char *s, uint8_t *valuep, uint8_t *maskp) | |
1681 | { | |
1682 | const struct frag_handling *h; | |
1683 | ||
1684 | for (h = all_frags; h < &all_frags[ARRAY_SIZE(all_frags)]; h++) { | |
1685 | if (!strcasecmp(s, h->name)) { | |
1686 | /* We force the upper bits of the mask on to make mf_parse_value() | |
1687 | * happy (otherwise it will never think it's an exact match.) */ | |
1688 | *maskp = h->mask | ~FLOW_FRAG_MASK; | |
1689 | *valuep = h->value; | |
1690 | return NULL; | |
1691 | } | |
1692 | } | |
1693 | ||
1694 | return xasprintf("%s: unknown fragment type (valid types are \"no\", " | |
1695 | "\"yes\", \"first\", \"later\", \"not_first\"", s); | |
1696 | } | |
1697 | ||
6a885fd0 BP |
1698 | /* Parses 's', a string value for field 'mf', into 'value' and 'mask'. Returns |
1699 | * NULL if successful, otherwise a malloc()'d string describing the error. */ | |
1700 | char * | |
1701 | mf_parse(const struct mf_field *mf, const char *s, | |
1702 | union mf_value *value, union mf_value *mask) | |
1703 | { | |
1704 | if (!strcasecmp(s, "any") || !strcmp(s, "*")) { | |
1705 | memset(value, 0, mf->n_bytes); | |
1706 | memset(mask, 0, mf->n_bytes); | |
1707 | return NULL; | |
1708 | } | |
1709 | ||
1710 | switch (mf->string) { | |
1711 | case MFS_DECIMAL: | |
1712 | case MFS_HEXADECIMAL: | |
1713 | return mf_from_integer_string(mf, s, | |
1714 | (uint8_t *) value, (uint8_t *) mask); | |
1715 | ||
1716 | case MFS_ETHERNET: | |
1717 | return mf_from_ethernet_string(mf, s, value->mac, mask->mac); | |
1718 | ||
1719 | case MFS_IPV4: | |
1720 | return mf_from_ipv4_string(mf, s, &value->be32, &mask->be32); | |
1721 | ||
1722 | case MFS_IPV6: | |
1723 | return mf_from_ipv6_string(mf, s, &value->ipv6, &mask->ipv6); | |
1724 | ||
1725 | case MFS_OFP_PORT: | |
1726 | return mf_from_ofp_port_string(mf, s, &value->be16, &mask->be16); | |
7257b535 BP |
1727 | |
1728 | case MFS_FRAG: | |
1729 | return mf_from_frag_string(s, &value->u8, &mask->u8); | |
6a885fd0 BP |
1730 | } |
1731 | NOT_REACHED(); | |
1732 | } | |
1733 | ||
1734 | /* Parses 's', a string value for field 'mf', into 'value'. Returns NULL if | |
1735 | * successful, otherwise a malloc()'d string describing the error. */ | |
1736 | char * | |
1737 | mf_parse_value(const struct mf_field *mf, const char *s, union mf_value *value) | |
1738 | { | |
1739 | union mf_value mask; | |
1740 | char *error; | |
1741 | ||
1742 | error = mf_parse(mf, s, value, &mask); | |
1743 | if (error) { | |
1744 | return error; | |
1745 | } | |
1746 | ||
1747 | if (!is_all_ones((const uint8_t *) &mask, mf->n_bytes)) { | |
1748 | return xasprintf("%s: wildcards not allowed here", s); | |
1749 | } | |
1750 | return NULL; | |
1751 | } | |
1752 | ||
1753 | static void | |
1754 | mf_format_integer_string(const struct mf_field *mf, const uint8_t *valuep, | |
1755 | const uint8_t *maskp, struct ds *s) | |
1756 | { | |
1757 | unsigned long long int integer; | |
1758 | int i; | |
1759 | ||
1760 | assert(mf->n_bytes <= 8); | |
1761 | ||
1762 | integer = 0; | |
1763 | for (i = 0; i < mf->n_bytes; i++) { | |
1764 | integer = (integer << 8) | valuep[i]; | |
1765 | } | |
1766 | if (mf->string == MFS_HEXADECIMAL) { | |
1767 | ds_put_format(s, "%#llx", integer); | |
1768 | } else { | |
1769 | ds_put_format(s, "%lld", integer); | |
1770 | } | |
1771 | ||
1772 | if (maskp) { | |
1773 | unsigned long long int mask; | |
1774 | ||
1775 | mask = 0; | |
1776 | for (i = 0; i < mf->n_bytes; i++) { | |
1777 | mask = (mask << 8) | maskp[i]; | |
1778 | } | |
1779 | ||
1780 | /* I guess we could write the mask in decimal for MFS_DECIMAL but I'm | |
1781 | * not sure that that a bit-mask written in decimal is ever easier to | |
1782 | * understand than the same bit-mask written in hexadecimal. */ | |
1783 | ds_put_format(s, "/%#llx", mask); | |
1784 | } | |
1785 | } | |
1786 | ||
7257b535 BP |
1787 | static void |
1788 | mf_format_frag_string(const uint8_t *valuep, const uint8_t *maskp, | |
1789 | struct ds *s) | |
1790 | { | |
1791 | const struct frag_handling *h; | |
1792 | uint8_t value = *valuep; | |
1793 | uint8_t mask = *maskp; | |
1794 | ||
1795 | value &= mask; | |
1796 | mask &= FLOW_FRAG_MASK; | |
1797 | ||
1798 | for (h = all_frags; h < &all_frags[ARRAY_SIZE(all_frags)]; h++) { | |
1799 | if (value == h->value && mask == h->mask) { | |
1800 | ds_put_cstr(s, h->name); | |
1801 | return; | |
1802 | } | |
1803 | } | |
1804 | ds_put_cstr(s, "<error>"); | |
1805 | } | |
1806 | ||
6a885fd0 BP |
1807 | /* Appends to 's' a string representation of field 'mf' whose value is in |
1808 | * 'value' and 'mask'. 'mask' may be NULL to indicate an exact match. */ | |
1809 | void | |
1810 | mf_format(const struct mf_field *mf, | |
1811 | const union mf_value *value, const union mf_value *mask, | |
1812 | struct ds *s) | |
1813 | { | |
1814 | if (mask) { | |
1815 | if (is_all_zeros((const uint8_t *) mask, mf->n_bytes)) { | |
1816 | ds_put_cstr(s, "ANY"); | |
1817 | return; | |
1818 | } else if (is_all_ones((const uint8_t *) mask, mf->n_bytes)) { | |
1819 | mask = NULL; | |
1820 | } | |
1821 | } | |
1822 | ||
1823 | switch (mf->string) { | |
1824 | case MFS_OFP_PORT: | |
1825 | if (!mask) { | |
1826 | ofputil_format_port(ntohs(value->be16), s); | |
1827 | break; | |
1828 | } | |
1829 | /* fall through */ | |
1830 | case MFS_DECIMAL: | |
1831 | case MFS_HEXADECIMAL: | |
1832 | mf_format_integer_string(mf, (uint8_t *) value, (uint8_t *) mask, s); | |
1833 | break; | |
1834 | ||
1835 | case MFS_ETHERNET: | |
1836 | ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(value->mac)); | |
1837 | if (mask) { | |
1838 | ds_put_format(s, "/"ETH_ADDR_FMT, ETH_ADDR_ARGS(mask->mac)); | |
1839 | } | |
1840 | break; | |
1841 | ||
1842 | case MFS_IPV4: | |
1843 | ip_format_masked(value->be32, mask ? mask->be32 : htonl(UINT32_MAX), | |
1844 | s); | |
1845 | break; | |
1846 | ||
1847 | case MFS_IPV6: | |
1848 | print_ipv6_masked(s, &value->ipv6, mask ? &mask->ipv6 : NULL); | |
1849 | break; | |
1850 | ||
7257b535 BP |
1851 | case MFS_FRAG: |
1852 | mf_format_frag_string(&value->u8, &mask->u8, s); | |
1853 | break; | |
1854 | ||
6a885fd0 BP |
1855 | default: |
1856 | NOT_REACHED(); | |
1857 | } | |
1858 | } |