]> git.proxmox.com Git - ovs.git/blame - lib/nx-match.c
ofp-actions: Support OF1.5 (draft) masked Set-Field, merge with reg_load.
[ovs.git] / lib / nx-match.c
CommitLineData
09246b99 1/*
f6e984d7 2 * Copyright (c) 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
09246b99
BP
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 "nx-match.h"
20
685a51a5
JP
21#include <netinet/icmp6.h>
22
09246b99
BP
23#include "classifier.h"
24#include "dynamic-string.h"
178742f9 25#include "hmap.h"
6a885fd0 26#include "meta-flow.h"
f25d0cf3 27#include "ofp-actions.h"
90bf1e07 28#include "ofp-errors.h"
09246b99
BP
29#include "ofp-util.h"
30#include "ofpbuf.h"
31#include "openflow/nicira-ext.h"
32#include "packets.h"
178742f9 33#include "shash.h"
09246b99 34#include "unaligned.h"
ddc4f8e2 35#include "util.h"
09246b99
BP
36#include "vlog.h"
37
38VLOG_DEFINE_THIS_MODULE(nx_match);
39
178742f9
BP
40/*
41 * OXM Class IDs.
42 * The high order bit differentiate reserved classes from member classes.
43 * Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
44 * Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
45 */
46enum ofp12_oxm_class {
47 OFPXMC12_NXM_0 = 0x0000, /* Backward compatibility with NXM */
48 OFPXMC12_NXM_1 = 0x0001, /* Backward compatibility with NXM */
49 OFPXMC12_OPENFLOW_BASIC = 0x8000, /* Basic class for OpenFlow */
50 OFPXMC15_PACKET_REGS = 0x8001, /* Packet registers (pipeline fields). */
51 OFPXMC12_EXPERIMENTER = 0xffff, /* Experimenter class */
52};
53
54/* Functions for extracting fields from OXM/NXM headers. */
55static int nxm_vendor(uint32_t header) { return header >> 16; }
56static int nxm_field(uint32_t header) { return (header >> 9) & 0x7f; }
57static bool nxm_hasmask(uint32_t header) { return (header & 0x100) != 0; }
58static int nxm_length(uint32_t header) { return header & 0xff; }
59
60/* Returns true if 'header' is a legacy NXM header, false if it is an OXM
61 * header.*/
62static bool
63is_nxm_header(uint32_t header)
64{
65 return nxm_vendor(header) <= 1;
66}
67
68#define NXM_HEADER(VENDOR, FIELD, HASMASK, LENGTH) \
69 (((VENDOR) << 16) | ((FIELD) << 9) | ((HASMASK) << 8) | (LENGTH))
70
71#define NXM_HEADER_FMT "%d:%d:%d:%d"
72#define NXM_HEADER_ARGS(HEADER) \
73 nxm_vendor(HEADER), nxm_field(HEADER), \
74 nxm_hasmask(HEADER), nxm_length(HEADER)
75
76/* Functions for turning the "hasmask" bit on or off. (This also requires
77 * adjusting the length.) */
78static uint32_t
79nxm_make_exact_header(uint32_t header)
80{
81 return NXM_HEADER(nxm_vendor(header), nxm_field(header), 0,
82 nxm_length(header) / 2);
83}
84static uint32_t
85nxm_make_wild_header(uint32_t header)
86{
87 return NXM_HEADER(nxm_vendor(header), nxm_field(header), 1,
88 nxm_length(header) * 2);
89}
90
91/* Flow cookie.
92 *
93 * This may be used to gain the OpenFlow 1.1-like ability to restrict
94 * certain NXM-based Flow Mod and Flow Stats Request messages to flows
95 * with specific cookies. See the "nx_flow_mod" and "nx_flow_stats_request"
96 * structure definitions for more details. This match is otherwise not
97 * allowed. */
98#define NXM_NX_COOKIE NXM_HEADER (0x0001, 30, 0, 8)
99#define NXM_NX_COOKIE_W nxm_make_wild_header(NXM_NX_COOKIE)
100
101struct nxm_field {
102 uint32_t header;
103 enum ofp_version version;
104 const char *name; /* e.g. "NXM_OF_IN_PORT". */
105
106 enum mf_field_id id;
107};
108
109static const struct nxm_field *nxm_field_by_header(uint32_t header);
110static const struct nxm_field *nxm_field_by_name(const char *name, size_t len);
111static const struct nxm_field *nxm_field_by_mf_id(enum mf_field_id);
112static const struct nxm_field *oxm_field_by_mf_id(enum mf_field_id);
113
09246b99
BP
114/* Rate limit for nx_match parse errors. These always indicate a bug in the
115 * peer and so there's not much point in showing a lot of them. */
116static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
117
178742f9
BP
118static const struct nxm_field *
119mf_parse_subfield_name(const char *name, int name_len, bool *wild);
120
121static const struct nxm_field *
122nxm_field_from_mf_field(enum mf_field_id id, enum ofp_version version)
123{
124 const struct nxm_field *oxm = oxm_field_by_mf_id(id);
125 const struct nxm_field *nxm = nxm_field_by_mf_id(id);
126 return oxm && (version >= oxm->version || !nxm) ? oxm : nxm;
127}
128
129/* Returns the preferred OXM header to use for field 'id' in OpenFlow version
130 * 'version'. Specify 0 for 'version' if an NXM legacy header should be
131 * preferred over any standardized OXM header. Returns 0 if field 'id' cannot
132 * be expressed in NXM or OXM. */
133uint32_t
134mf_oxm_header(enum mf_field_id id, enum ofp_version version)
135{
136 const struct nxm_field *f = nxm_field_from_mf_field(id, version);
137 return f ? f->header : 0;
138}
139
140/* Returns the "struct mf_field" that corresponds to NXM or OXM header
141 * 'header', or NULL if 'header' doesn't correspond to any known field. */
142const struct mf_field *
143mf_from_nxm_header(uint32_t header)
144{
145 const struct nxm_field *f = nxm_field_by_header(header);
146 return f ? mf_from_id(f->id) : NULL;
147}
148
09246b99
BP
149/* Returns the width of the data for a field with the given 'header', in
150 * bytes. */
178742f9 151static int
09246b99
BP
152nxm_field_bytes(uint32_t header)
153{
178742f9
BP
154 unsigned int length = nxm_length(header);
155 return nxm_hasmask(header) ? length / 2 : length;
09246b99 156}
b6c9e612 157
178742f9
BP
158/* Returns the earliest version of OpenFlow that standardized an OXM header for
159 * field 'id', or UINT8_MAX if no version of OpenFlow does. */
160static enum ofp_version
161mf_oxm_version(enum mf_field_id id)
b6c9e612 162{
178742f9
BP
163 const struct nxm_field *oxm = oxm_field_by_mf_id(id);
164 return oxm ? oxm->version : UINT8_MAX;
b6c9e612 165}
178742f9 166 \f
6a885fd0 167/* nx_pull_match() and helpers. */
09246b99 168
178742f9
BP
169/* Given NXM/OXM value 'value' and mask 'mask' associated with 'header', checks
170 * for any 1-bit in the value where there is a 0-bit in the mask. Returns 0 if
171 * none, otherwise an error code. */
172static bool
173is_mask_consistent(uint32_t header, const uint8_t *value, const uint8_t *mask)
09246b99 174{
178742f9
BP
175 unsigned int width = nxm_field_bytes(header);
176 unsigned int i;
09246b99 177
178742f9
BP
178 for (i = 0; i < width; i++) {
179 if (value[i] & ~mask[i]) {
180 if (!VLOG_DROP_WARN(&rl)) {
181 VLOG_WARN_RL(&rl, "Rejecting NXM/OXM entry "NXM_HEADER_FMT " "
182 "with 1-bits in value for bits wildcarded by the "
183 "mask.", NXM_HEADER_ARGS(header));
184 }
185 return false;
09246b99 186 }
09246b99 187 }
178742f9
BP
188 return true;
189}
09246b99 190
178742f9
BP
191static bool
192is_cookie_pseudoheader(uint32_t header)
193{
194 return header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W;
195}
196
197static enum ofperr
198nx_pull_header__(struct ofpbuf *b, bool allow_cookie, uint32_t *header,
199 const struct mf_field **field)
200{
201 if (ofpbuf_size(b) < 4) {
202 VLOG_DBG_RL(&rl, "encountered partial (%"PRIu32"-byte) OXM entry",
203 ofpbuf_size(b));
204 goto error;
09246b99 205 }
178742f9
BP
206 *header = ntohl(get_unaligned_be32(ofpbuf_pull(b, 4)));
207 if (nxm_length(*header) == 0) {
208 VLOG_WARN_RL(&rl, "OXM header "NXM_HEADER_FMT" has zero length",
209 NXM_HEADER_ARGS(*header));
210 goto error;
211 }
212 if (field) {
213 *field = mf_from_nxm_header(*header);
214 if (!*field && !(allow_cookie && is_cookie_pseudoheader(*header))) {
215 VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" is unknown",
216 NXM_HEADER_ARGS(*header));
217 return OFPERR_OFPBMC_BAD_FIELD;
218 }
09246b99
BP
219 }
220
178742f9
BP
221 return 0;
222
223error:
224 *header = 0;
225 *field = NULL;
226 return OFPERR_OFPBMC_BAD_LEN;
09246b99
BP
227}
228
3947cc76 229static enum ofperr
178742f9
BP
230nx_pull_entry__(struct ofpbuf *b, bool allow_cookie, uint32_t *header,
231 const struct mf_field **field,
232 union mf_value *value, union mf_value *mask)
e1cfc4e4 233{
178742f9
BP
234 enum ofperr header_error;
235 unsigned int payload_len;
236 const uint8_t *payload;
237 int width;
e1cfc4e4 238
178742f9
BP
239 header_error = nx_pull_header__(b, allow_cookie, header, field);
240 if (header_error && header_error != OFPERR_OFPBMC_BAD_FIELD) {
241 return header_error;
242 }
243
244 payload_len = nxm_length(*header);
245 payload = ofpbuf_try_pull(b, payload_len);
246 if (!payload) {
247 VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" calls for %u-byte "
248 "payload but only %"PRIu32" bytes follow OXM header",
249 NXM_HEADER_ARGS(*header), payload_len, ofpbuf_size(b));
250 return OFPERR_OFPBMC_BAD_LEN;
251 }
252
253 width = nxm_field_bytes(*header);
254 if (nxm_hasmask(*header)
255 && !is_mask_consistent(*header, payload, payload + width)) {
256 return OFPERR_OFPBMC_BAD_WILDCARDS;
257 }
258
259 memcpy(value, payload, MIN(width, sizeof *value));
260 if (mask) {
261 if (nxm_hasmask(*header)) {
262 memcpy(mask, payload + width, MIN(width, sizeof *mask));
263 } else {
264 memset(mask, 0xff, MIN(width, sizeof *mask));
265 }
266 } else if (nxm_hasmask(*header)) {
267 VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" includes mask but "
268 "masked OXMs are not allowed here",
269 NXM_HEADER_ARGS(*header));
270 return OFPERR_OFPBMC_BAD_MASK;
271 }
272
273 return header_error;
274}
275
276/* Attempts to pull an NXM or OXM header, value, and mask (if present) from the
277 * beginning of 'b'. If successful, stores a pointer to the "struct mf_field"
278 * corresponding to the pulled header in '*field', the value into '*value',
279 * and the mask into '*mask', and returns 0. On error, returns an OpenFlow
280 * error; in this case, some bytes might have been pulled off 'b' anyhow, and
281 * the output parameters might have been modified.
282 *
283 * If a NULL 'mask' is supplied, masked OXM or NXM entries are treated as
284 * errors (with OFPERR_OFPBMC_BAD_MASK).
285 */
286enum ofperr
287nx_pull_entry(struct ofpbuf *b, const struct mf_field **field,
288 union mf_value *value, union mf_value *mask)
289{
290 uint32_t header;
291
292 return nx_pull_entry__(b, false, &header, field, value, mask);
293}
294
295/* Attempts to pull an NXM or OXM header from the beginning of 'b'. If
296 * successful, stores a pointer to the "struct mf_field" corresponding to the
297 * pulled header in '*field', stores the header's hasmask bit in '*masked'
298 * (true if hasmask=1, false if hasmask=0), and returns 0. On error, returns
299 * an OpenFlow error; in this case, some bytes might have been pulled off 'b'
300 * anyhow, and the output parameters might have been modified.
301 *
302 * If NULL 'masked' is supplied, masked OXM or NXM headers are treated as
303 * errors (with OFPERR_OFPBMC_BAD_MASK).
304 */
305enum ofperr
306nx_pull_header(struct ofpbuf *b, const struct mf_field **field, bool *masked)
307{
308 enum ofperr error;
309 uint32_t header;
310
311 error = nx_pull_header__(b, false, &header, field);
312 if (masked) {
313 *masked = !error && nxm_hasmask(header);
314 } else if (!error && nxm_hasmask(header)) {
315 error = OFPERR_OFPBMC_BAD_MASK;
316 }
317 return error;
318}
319
320static enum ofperr
321nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
322 const struct mf_field **field,
323 union mf_value *value, union mf_value *mask)
324{
325 enum ofperr error;
326 uint32_t header;
327
328 error = nx_pull_entry__(b, allow_cookie, &header, field, value, mask);
329 if (error) {
330 return error;
331 }
332 if (field && *field) {
333 if (!mf_is_mask_valid(*field, mask)) {
334 VLOG_DBG_RL(&rl, "bad mask for field %s", (*field)->name);
335 return OFPERR_OFPBMC_BAD_MASK;
336 }
337 if (!mf_is_value_valid(*field, value)) {
338 VLOG_DBG_RL(&rl, "bad value for field %s", (*field)->name);
339 return OFPERR_OFPBMC_BAD_VALUE;
e1cfc4e4
BP
340 }
341 }
3947cc76 342 return 0;
e1cfc4e4
BP
343}
344
90bf1e07 345static enum ofperr
7623f4dd 346nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
81a76618 347 struct match *match, ovs_be64 *cookie, ovs_be64 *cookie_mask)
09246b99 348{
178742f9 349 struct ofpbuf b;
09246b99 350
cb22974d 351 ovs_assert((cookie != NULL) == (cookie_mask != NULL));
e729e793 352
81a76618 353 match_init_catchall(match);
a3a0c29e
BP
354 if (cookie) {
355 *cookie = *cookie_mask = htonll(0);
356 }
a3a0c29e 357
178742f9
BP
358 ofpbuf_use_const(&b, p, match_len);
359 while (ofpbuf_size(&b)) {
360 const uint8_t *pos = ofpbuf_data(&b);
361 const struct mf_field *field;
362 union mf_value value;
363 union mf_value mask;
90bf1e07 364 enum ofperr error;
09246b99 365
178742f9
BP
366 error = nx_pull_match_entry(&b, cookie != NULL, &field, &value, &mask);
367 if (error) {
368 if (error == OFPERR_OFPBMC_BAD_FIELD && !strict) {
369 continue;
370 }
371 } else if (!field) {
372 if (!cookie) {
2e0525bc 373 error = OFPERR_OFPBMC_BAD_FIELD;
178742f9
BP
374 } else if (*cookie_mask) {
375 error = OFPERR_OFPBMC_DUP_FIELD;
102ce766 376 } else {
178742f9
BP
377 *cookie = value.be64;
378 *cookie_mask = mask.be64;
102ce766 379 }
178742f9 380 } else if (!mf_are_prereqs_ok(field, &match->flow)) {
2e0525bc 381 error = OFPERR_OFPBMC_BAD_PREREQ;
178742f9 382 } else if (!mf_is_all_wild(field, &match->wc)) {
2e0525bc 383 error = OFPERR_OFPBMC_DUP_FIELD;
72333065 384 } else {
178742f9 385 mf_set(field, &value, &mask, match);
e729e793
JP
386 }
387
09246b99 388 if (error) {
178742f9
BP
389 VLOG_DBG_RL(&rl, "error parsing OXM at offset %"PRIdPTR" "
390 "within match (%s)", pos -
391 p, ofperr_to_string(error));
09246b99
BP
392 return error;
393 }
09246b99
BP
394 }
395
178742f9 396 return 0;
09246b99 397}
102ce766 398
7623f4dd
SH
399static enum ofperr
400nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
81a76618 401 struct match *match,
7623f4dd
SH
402 ovs_be64 *cookie, ovs_be64 *cookie_mask)
403{
404 uint8_t *p = NULL;
405
406 if (match_len) {
407 p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
408 if (!p) {
409 VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
410 "multiple of 8, is longer than space in message (max "
1f317cb5 411 "length %"PRIu32")", match_len, ofpbuf_size(b));
7623f4dd
SH
412 return OFPERR_OFPBMC_BAD_LEN;
413 }
414 }
415
81a76618 416 return nx_pull_raw(p, match_len, strict, match, cookie, cookie_mask);
7623f4dd
SH
417}
418
102ce766 419/* Parses the nx_match formatted match description in 'b' with length
81a76618
BP
420 * 'match_len'. Stores the results in 'match'. If 'cookie' and 'cookie_mask'
421 * are valid pointers, then stores the cookie and mask in them if 'b' contains
422 * a "NXM_NX_COOKIE*" match. Otherwise, stores 0 in both.
102ce766 423 *
81a76618 424 * Fails with an error upon encountering an unknown NXM header.
102ce766
EJ
425 *
426 * Returns 0 if successful, otherwise an OpenFlow error code. */
90bf1e07 427enum ofperr
81a76618 428nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
102ce766
EJ
429 ovs_be64 *cookie, ovs_be64 *cookie_mask)
430{
81a76618 431 return nx_pull_match__(b, match_len, true, match, cookie, cookie_mask);
102ce766
EJ
432}
433
81a76618
BP
434/* Behaves the same as nx_pull_match(), but skips over unknown NXM headers,
435 * instead of failing with an error. */
90bf1e07 436enum ofperr
102ce766 437nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
81a76618 438 struct match *match,
102ce766
EJ
439 ovs_be64 *cookie, ovs_be64 *cookie_mask)
440{
81a76618 441 return nx_pull_match__(b, match_len, false, match, cookie, cookie_mask);
102ce766 442}
7623f4dd
SH
443
444static enum ofperr
81a76618 445oxm_pull_match__(struct ofpbuf *b, bool strict, struct match *match)
7623f4dd 446{
1f317cb5 447 struct ofp11_match_header *omh = ofpbuf_data(b);
7623f4dd
SH
448 uint8_t *p;
449 uint16_t match_len;
450
1f317cb5 451 if (ofpbuf_size(b) < sizeof *omh) {
7623f4dd
SH
452 return OFPERR_OFPBMC_BAD_LEN;
453 }
454
455 match_len = ntohs(omh->length);
456 if (match_len < sizeof *omh) {
457 return OFPERR_OFPBMC_BAD_LEN;
458 }
459
460 if (omh->type != htons(OFPMT_OXM)) {
461 return OFPERR_OFPBMC_BAD_TYPE;
462 }
463
464 p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
465 if (!p) {
466 VLOG_DBG_RL(&rl, "oxm length %u, rounded up to a "
467 "multiple of 8, is longer than space in message (max "
1f317cb5 468 "length %"PRIu32")", match_len, ofpbuf_size(b));
7623f4dd
SH
469 return OFPERR_OFPBMC_BAD_LEN;
470 }
471
472 return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh,
81a76618 473 strict, match, NULL, NULL);
7623f4dd
SH
474}
475
aa0667bc
YT
476/* Parses the oxm formatted match description preceded by a struct
477 * ofp11_match_header in 'b'. Stores the result in 'match'.
7623f4dd
SH
478 *
479 * Fails with an error when encountering unknown OXM headers.
480 *
481 * Returns 0 if successful, otherwise an OpenFlow error code. */
482enum ofperr
81a76618 483oxm_pull_match(struct ofpbuf *b, struct match *match)
7623f4dd 484{
81a76618 485 return oxm_pull_match__(b, true, match);
7623f4dd
SH
486}
487
488/* Behaves the same as oxm_pull_match() with one exception. Skips over unknown
aa0667bc 489 * OXM headers instead of failing with an error when they are encountered. */
7623f4dd 490enum ofperr
81a76618 491oxm_pull_match_loose(struct ofpbuf *b, struct match *match)
7623f4dd 492{
81a76618 493 return oxm_pull_match__(b, false, match);
7623f4dd 494}
09246b99
BP
495\f
496/* nx_put_match() and helpers.
497 *
498 * 'put' functions whose names end in 'w' add a wildcarded field.
499 * 'put' functions whose names end in 'm' add a field that might be wildcarded.
500 * Other 'put' functions add exact-match fields.
501 */
502
503static void
504nxm_put_header(struct ofpbuf *b, uint32_t header)
505{
506 ovs_be32 n_header = htonl(header);
507 ofpbuf_put(b, &n_header, sizeof n_header);
508}
509
510static void
511nxm_put_8(struct ofpbuf *b, uint32_t header, uint8_t value)
512{
513 nxm_put_header(b, header);
514 ofpbuf_put(b, &value, sizeof value);
515}
516
7257b535
BP
517static void
518nxm_put_8m(struct ofpbuf *b, uint32_t header, uint8_t value, uint8_t mask)
519{
520 switch (mask) {
521 case 0:
522 break;
523
524 case UINT8_MAX:
525 nxm_put_8(b, header, value);
526 break;
527
528 default:
178742f9 529 nxm_put_header(b, nxm_make_wild_header(header));
7257b535
BP
530 ofpbuf_put(b, &value, sizeof value);
531 ofpbuf_put(b, &mask, sizeof mask);
532 }
533}
534
09246b99
BP
535static void
536nxm_put_16(struct ofpbuf *b, uint32_t header, ovs_be16 value)
537{
538 nxm_put_header(b, header);
539 ofpbuf_put(b, &value, sizeof value);
540}
541
542static void
543nxm_put_16w(struct ofpbuf *b, uint32_t header, ovs_be16 value, ovs_be16 mask)
544{
545 nxm_put_header(b, header);
546 ofpbuf_put(b, &value, sizeof value);
547 ofpbuf_put(b, &mask, sizeof mask);
548}
549
66642cb4
BP
550static void
551nxm_put_16m(struct ofpbuf *b, uint32_t header, ovs_be16 value, ovs_be16 mask)
552{
553 switch (mask) {
554 case 0:
555 break;
556
b8266395 557 case OVS_BE16_MAX:
66642cb4
BP
558 nxm_put_16(b, header, value);
559 break;
560
561 default:
178742f9 562 nxm_put_16w(b, nxm_make_wild_header(header), value, mask);
66642cb4
BP
563 break;
564 }
565}
566
09246b99
BP
567static void
568nxm_put_32(struct ofpbuf *b, uint32_t header, ovs_be32 value)
569{
570 nxm_put_header(b, header);
571 ofpbuf_put(b, &value, sizeof value);
572}
573
574static void
575nxm_put_32w(struct ofpbuf *b, uint32_t header, ovs_be32 value, ovs_be32 mask)
576{
577 nxm_put_header(b, header);
578 ofpbuf_put(b, &value, sizeof value);
579 ofpbuf_put(b, &mask, sizeof mask);
580}
581
582static void
583nxm_put_32m(struct ofpbuf *b, uint32_t header, ovs_be32 value, ovs_be32 mask)
584{
585 switch (mask) {
586 case 0:
587 break;
588
b8266395 589 case OVS_BE32_MAX:
09246b99
BP
590 nxm_put_32(b, header, value);
591 break;
592
593 default:
178742f9 594 nxm_put_32w(b, nxm_make_wild_header(header), value, mask);
09246b99
BP
595 break;
596 }
597}
598
599static void
600nxm_put_64(struct ofpbuf *b, uint32_t header, ovs_be64 value)
601{
602 nxm_put_header(b, header);
603 ofpbuf_put(b, &value, sizeof value);
604}
605
8368c090
BP
606static void
607nxm_put_64w(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask)
608{
609 nxm_put_header(b, header);
610 ofpbuf_put(b, &value, sizeof value);
611 ofpbuf_put(b, &mask, sizeof mask);
612}
613
614static void
615nxm_put_64m(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask)
616{
617 switch (mask) {
618 case 0:
619 break;
620
b8266395 621 case OVS_BE64_MAX:
8368c090
BP
622 nxm_put_64(b, header, value);
623 break;
624
625 default:
178742f9 626 nxm_put_64w(b, nxm_make_wild_header(header), value, mask);
8368c090
BP
627 break;
628 }
629}
630
09246b99
BP
631static void
632nxm_put_eth(struct ofpbuf *b, uint32_t header,
633 const uint8_t value[ETH_ADDR_LEN])
634{
635 nxm_put_header(b, header);
636 ofpbuf_put(b, value, ETH_ADDR_LEN);
637}
638
1e37a2d7 639static void
73c0ce34
JS
640nxm_put_eth_masked(struct ofpbuf *b, uint32_t header,
641 const uint8_t value[ETH_ADDR_LEN],
642 const uint8_t mask[ETH_ADDR_LEN])
1e37a2d7 643{
73c0ce34
JS
644 if (!eth_addr_is_zero(mask)) {
645 if (eth_mask_is_exact(mask)) {
646 nxm_put_eth(b, header, value);
647 } else {
178742f9 648 nxm_put_header(b, nxm_make_wild_header(header));
73c0ce34
JS
649 ofpbuf_put(b, value, ETH_ADDR_LEN);
650 ofpbuf_put(b, mask, ETH_ADDR_LEN);
651 }
1e37a2d7
BP
652 }
653}
654
d31f1109
JP
655static void
656nxm_put_ipv6(struct ofpbuf *b, uint32_t header,
657 const struct in6_addr *value, const struct in6_addr *mask)
658{
659 if (ipv6_mask_is_any(mask)) {
660 return;
661 } else if (ipv6_mask_is_exact(mask)) {
662 nxm_put_header(b, header);
663 ofpbuf_put(b, value, sizeof *value);
664 } else {
178742f9 665 nxm_put_header(b, nxm_make_wild_header(header));
d31f1109
JP
666 ofpbuf_put(b, value, sizeof *value);
667 ofpbuf_put(b, mask, sizeof *mask);
668 }
669}
670
7257b535 671static void
21119b3e 672nxm_put_frag(struct ofpbuf *b, const struct match *match, enum ofp_version oxm)
7257b535 673{
21119b3e 674 uint32_t header = mf_oxm_header(MFF_IP_FRAG, oxm);
81a76618
BP
675 uint8_t nw_frag = match->flow.nw_frag;
676 uint8_t nw_frag_mask = match->wc.masks.nw_frag;
7257b535 677
eadef313 678 switch (nw_frag_mask) {
7257b535
BP
679 case 0:
680 break;
681
eadef313 682 case FLOW_NW_FRAG_MASK:
21119b3e 683 nxm_put_8(b, header, nw_frag);
7257b535
BP
684 break;
685
686 default:
21119b3e 687 nxm_put_8m(b, header, nw_frag, nw_frag_mask & FLOW_NW_FRAG_MASK);
7257b535
BP
688 break;
689 }
690}
691
5e10215d
BP
692/* Appends to 'b' a set of OXM or NXM matches for the IPv4 or IPv6 fields in
693 * 'match'. */
8e7082b0 694static void
9d84066c 695nxm_put_ip(struct ofpbuf *b, const struct match *match, enum ofp_version oxm)
8e7082b0 696{
81a76618 697 const struct flow *flow = &match->flow;
8e7082b0 698
5e10215d 699 if (flow->dl_type == htons(ETH_TYPE_IP)) {
9d84066c 700 nxm_put_32m(b, mf_oxm_header(MFF_IPV4_SRC, oxm),
5e10215d 701 flow->nw_src, match->wc.masks.nw_src);
9d84066c 702 nxm_put_32m(b, mf_oxm_header(MFF_IPV4_DST, oxm),
5e10215d
BP
703 flow->nw_dst, match->wc.masks.nw_dst);
704 } else {
9d84066c 705 nxm_put_ipv6(b, mf_oxm_header(MFF_IPV6_SRC, oxm),
5e10215d 706 &flow->ipv6_src, &match->wc.masks.ipv6_src);
9d84066c 707 nxm_put_ipv6(b, mf_oxm_header(MFF_IPV6_DST, oxm),
5e10215d
BP
708 &flow->ipv6_dst, &match->wc.masks.ipv6_dst);
709 }
710
21119b3e 711 nxm_put_frag(b, match, oxm);
8e7082b0 712
81a76618 713 if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
1638b906 714 if (oxm) {
9d84066c
BP
715 nxm_put_8(b, mf_oxm_header(MFF_IP_DSCP_SHIFTED, oxm),
716 flow->nw_tos >> 2);
1638b906 717 } else {
9d84066c
BP
718 nxm_put_8(b, mf_oxm_header(MFF_IP_DSCP, oxm),
719 flow->nw_tos & IP_DSCP_MASK);
1638b906 720 }
8e7082b0
BP
721 }
722
81a76618 723 if (match->wc.masks.nw_tos & IP_ECN_MASK) {
9d84066c 724 nxm_put_8(b, mf_oxm_header(MFF_IP_ECN, oxm),
b5ae8913 725 flow->nw_tos & IP_ECN_MASK);
8e7082b0
BP
726 }
727
81a76618 728 if (!oxm && match->wc.masks.nw_ttl) {
9d84066c 729 nxm_put_8(b, mf_oxm_header(MFF_IP_TTL, oxm), flow->nw_ttl);
8e7082b0
BP
730 }
731
9d84066c 732 nxm_put_32m(b, mf_oxm_header(MFF_IPV6_LABEL, oxm),
5e10215d
BP
733 flow->ipv6_label, match->wc.masks.ipv6_label);
734
81a76618 735 if (match->wc.masks.nw_proto) {
9d84066c 736 nxm_put_8(b, mf_oxm_header(MFF_IP_PROTO, oxm), flow->nw_proto);
8e7082b0
BP
737
738 if (flow->nw_proto == IPPROTO_TCP) {
9d84066c 739 nxm_put_16m(b, mf_oxm_header(MFF_TCP_SRC, oxm),
81a76618 740 flow->tp_src, match->wc.masks.tp_src);
9d84066c 741 nxm_put_16m(b, mf_oxm_header(MFF_TCP_DST, oxm),
81a76618 742 flow->tp_dst, match->wc.masks.tp_dst);
9d84066c 743 nxm_put_16m(b, mf_oxm_header(MFF_TCP_FLAGS, oxm),
dc235f7f 744 flow->tcp_flags, match->wc.masks.tcp_flags);
8e7082b0 745 } else if (flow->nw_proto == IPPROTO_UDP) {
9d84066c 746 nxm_put_16m(b, mf_oxm_header(MFF_UDP_SRC, oxm),
81a76618 747 flow->tp_src, match->wc.masks.tp_src);
9d84066c 748 nxm_put_16m(b, mf_oxm_header(MFF_UDP_DST, oxm),
81a76618 749 flow->tp_dst, match->wc.masks.tp_dst);
0d56eaf2 750 } else if (flow->nw_proto == IPPROTO_SCTP) {
9d84066c 751 nxm_put_16m(b, mf_oxm_header(MFF_SCTP_SRC, oxm), flow->tp_src,
0d56eaf2 752 match->wc.masks.tp_src);
9d84066c 753 nxm_put_16m(b, mf_oxm_header(MFF_SCTP_DST, oxm), flow->tp_dst,
0d56eaf2 754 match->wc.masks.tp_dst);
5e10215d
BP
755 } else if (is_icmpv4(flow)) {
756 if (match->wc.masks.tp_src) {
9d84066c 757 nxm_put_8(b, mf_oxm_header(MFF_ICMPV4_TYPE, oxm),
5e10215d
BP
758 ntohs(flow->tp_src));
759 }
760 if (match->wc.masks.tp_dst) {
9d84066c 761 nxm_put_8(b, mf_oxm_header(MFF_ICMPV4_CODE, oxm),
5e10215d
BP
762 ntohs(flow->tp_dst));
763 }
764 } else if (is_icmpv6(flow)) {
81a76618 765 if (match->wc.masks.tp_src) {
9d84066c 766 nxm_put_8(b, mf_oxm_header(MFF_ICMPV6_TYPE, oxm),
5e10215d 767 ntohs(flow->tp_src));
8e7082b0 768 }
81a76618 769 if (match->wc.masks.tp_dst) {
9d84066c 770 nxm_put_8(b, mf_oxm_header(MFF_ICMPV6_CODE, oxm),
5e10215d
BP
771 ntohs(flow->tp_dst));
772 }
773 if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
774 flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
9d84066c 775 nxm_put_ipv6(b, mf_oxm_header(MFF_ND_TARGET, oxm),
5e10215d
BP
776 &flow->nd_target, &match->wc.masks.nd_target);
777 if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
9d84066c 778 nxm_put_eth_masked(b, mf_oxm_header(MFF_ND_SLL, oxm),
5e10215d
BP
779 flow->arp_sha, match->wc.masks.arp_sha);
780 }
781 if (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
9d84066c 782 nxm_put_eth_masked(b, mf_oxm_header(MFF_ND_TLL, oxm),
5e10215d
BP
783 flow->arp_tha, match->wc.masks.arp_tha);
784 }
8e7082b0
BP
785 }
786 }
787 }
788}
789
81a76618 790/* Appends to 'b' the nx_match format that expresses 'match'. For Flow Mod and
7623f4dd
SH
791 * Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
792 * Otherwise, 'cookie_mask' should be zero.
4d0ed519 793 *
9d84066c
BP
794 * Specify 'oxm' as 0 to express the match in NXM format; otherwise, specify
795 * 'oxm' as the OpenFlow version number for the OXM format to use.
796 *
4d0ed519
BP
797 * This function can cause 'b''s data to be reallocated.
798 *
799 * Returns the number of bytes appended to 'b', excluding padding.
800 *
81a76618 801 * If 'match' is a catch-all rule that matches every packet, then this function
4d0ed519 802 * appends nothing to 'b' and returns 0. */
7623f4dd 803static int
9d84066c 804nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
7623f4dd 805 ovs_be64 cookie, ovs_be64 cookie_mask)
09246b99 806{
81a76618 807 const struct flow *flow = &match->flow;
1f317cb5 808 const size_t start_len = ofpbuf_size(b);
09246b99 809 int match_len;
b6c9e612 810 int i;
09246b99 811
0e612675 812 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 27);
a877206f 813
09246b99 814 /* Metadata. */
a79f29f2 815 if (match->wc.masks.dp_hash) {
447b6582
BP
816 nxm_put_32m(b, mf_oxm_header(MFF_DP_HASH, oxm),
817 htonl(flow->dp_hash), htonl(match->wc.masks.dp_hash));
a79f29f2
AZ
818 }
819
820 if (match->wc.masks.recirc_id) {
447b6582
BP
821 nxm_put_32(b, mf_oxm_header(MFF_RECIRC_ID, oxm),
822 htonl(flow->recirc_id));
a79f29f2
AZ
823 }
824
4e022ec0
AW
825 if (match->wc.masks.in_port.ofp_port) {
826 ofp_port_t in_port = flow->in_port.ofp_port;
b5ae8913 827 if (oxm) {
9d84066c
BP
828 nxm_put_32(b, mf_oxm_header(MFF_IN_PORT_OXM, oxm),
829 ofputil_port_to_ofp11(in_port));
b5ae8913 830 } else {
9d84066c
BP
831 nxm_put_16(b, mf_oxm_header(MFF_IN_PORT, oxm),
832 htons(ofp_to_u16(in_port)));
b5ae8913 833 }
09246b99
BP
834 }
835
836 /* Ethernet. */
9d84066c 837 nxm_put_eth_masked(b, mf_oxm_header(MFF_ETH_SRC, oxm),
81a76618 838 flow->dl_src, match->wc.masks.dl_src);
9d84066c 839 nxm_put_eth_masked(b, mf_oxm_header(MFF_ETH_DST, oxm),
81a76618 840 flow->dl_dst, match->wc.masks.dl_dst);
9d84066c 841 nxm_put_16m(b, mf_oxm_header(MFF_ETH_TYPE, oxm),
e2170cff 842 ofputil_dl_type_to_openflow(flow->dl_type),
81a76618 843 match->wc.masks.dl_type);
09246b99 844
95f61ba8
SH
845 /* 802.1Q. */
846 if (oxm) {
26720e24
BP
847 ovs_be16 VID_CFI_MASK = htons(VLAN_VID_MASK | VLAN_CFI);
848 ovs_be16 vid = flow->vlan_tci & VID_CFI_MASK;
81a76618 849 ovs_be16 mask = match->wc.masks.vlan_tci & VID_CFI_MASK;
95f61ba8
SH
850
851 if (mask == htons(VLAN_VID_MASK | VLAN_CFI)) {
9d84066c 852 nxm_put_16(b, mf_oxm_header(MFF_VLAN_VID, oxm), vid);
95f61ba8 853 } else if (mask) {
9d84066c 854 nxm_put_16m(b, mf_oxm_header(MFF_VLAN_VID, oxm), vid, mask);
95f61ba8
SH
855 }
856
81a76618 857 if (vid && vlan_tci_to_pcp(match->wc.masks.vlan_tci)) {
9d84066c
BP
858 nxm_put_8(b, mf_oxm_header(MFF_VLAN_PCP, oxm),
859 vlan_tci_to_pcp(flow->vlan_tci));
95f61ba8
SH
860 }
861
862 } else {
9d84066c 863 nxm_put_16m(b, mf_oxm_header(MFF_VLAN_TCI, oxm), flow->vlan_tci,
81a76618 864 match->wc.masks.vlan_tci);
95f61ba8 865 }
09246b99 866
b02475c5
SH
867 /* MPLS. */
868 if (eth_type_mpls(flow->dl_type)) {
8bfd0fda 869 if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) {
9d84066c
BP
870 nxm_put_8(b, mf_oxm_header(MFF_MPLS_TC, oxm),
871 mpls_lse_to_tc(flow->mpls_lse[0]));
b02475c5
SH
872 }
873
8bfd0fda 874 if (match->wc.masks.mpls_lse[0] & htonl(MPLS_BOS_MASK)) {
9d84066c
BP
875 nxm_put_8(b, mf_oxm_header(MFF_MPLS_BOS, oxm),
876 mpls_lse_to_bos(flow->mpls_lse[0]));
b02475c5
SH
877 }
878
8bfd0fda 879 if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
9d84066c 880 nxm_put_32(b, mf_oxm_header(MFF_MPLS_LABEL, oxm),
8bfd0fda 881 htonl(mpls_lse_to_label(flow->mpls_lse[0])));
b02475c5
SH
882 }
883 }
884
66642cb4 885 /* L3. */
5e10215d
BP
886 if (is_ip_any(flow)) {
887 nxm_put_ip(b, match, oxm);
8087f5ff
MM
888 } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
889 flow->dl_type == htons(ETH_TYPE_RARP)) {
09246b99 890 /* ARP. */
81a76618 891 if (match->wc.masks.nw_proto) {
9d84066c 892 nxm_put_16(b, mf_oxm_header(MFF_ARP_OP, oxm),
b5ae8913 893 htons(flow->nw_proto));
09246b99 894 }
9d84066c 895 nxm_put_32m(b, mf_oxm_header(MFF_ARP_SPA, oxm),
81a76618 896 flow->nw_src, match->wc.masks.nw_src);
9d84066c 897 nxm_put_32m(b, mf_oxm_header(MFF_ARP_TPA, oxm),
81a76618 898 flow->nw_dst, match->wc.masks.nw_dst);
9d84066c 899 nxm_put_eth_masked(b, mf_oxm_header(MFF_ARP_SHA, oxm),
81a76618 900 flow->arp_sha, match->wc.masks.arp_sha);
9d84066c 901 nxm_put_eth_masked(b, mf_oxm_header(MFF_ARP_THA, oxm),
81a76618 902 flow->arp_tha, match->wc.masks.arp_tha);
09246b99
BP
903 }
904
905 /* Tunnel ID. */
9d84066c 906 nxm_put_64m(b, mf_oxm_header(MFF_TUN_ID, oxm),
0ad90c84
JR
907 flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
908
909 /* Other tunnel metadata. */
9d84066c 910 nxm_put_32m(b, mf_oxm_header(MFF_TUN_SRC, oxm),
0ad90c84 911 flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
9d84066c 912 nxm_put_32m(b, mf_oxm_header(MFF_TUN_DST, oxm),
0ad90c84 913 flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst);
09246b99 914
b6c9e612 915 /* Registers. */
a678b23e
BP
916 if (oxm < OFP15_VERSION) {
917 for (i = 0; i < FLOW_N_REGS; i++) {
918 nxm_put_32m(b, mf_oxm_header(MFF_REG0 + i, oxm),
919 htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
920 }
921 } else {
922 for (i = 0; i < FLOW_N_XREGS; i++) {
923 nxm_put_64m(b, mf_oxm_header(MFF_XREG0 + i, oxm),
924 htonll(flow_get_xreg(flow, i)),
925 htonll(flow_get_xreg(&match->wc.masks, i)));
926 }
b6c9e612
BP
927 }
928
ac923e91 929 /* Mark. */
9d84066c 930 nxm_put_32m(b, mf_oxm_header(MFF_PKT_MARK, oxm), htonl(flow->pkt_mark),
ac923e91
JG
931 htonl(match->wc.masks.pkt_mark));
932
969fc56c 933 /* OpenFlow 1.1+ Metadata. */
9d84066c
BP
934 nxm_put_64m(b, mf_oxm_header(MFF_METADATA, oxm),
935 flow->metadata, match->wc.masks.metadata);
969fc56c 936
e729e793 937 /* Cookie. */
ba5cc068 938 nxm_put_64m(b, NXM_NX_COOKIE, cookie & cookie_mask, cookie_mask);
e729e793 939
1f317cb5 940 match_len = ofpbuf_size(b) - start_len;
7623f4dd
SH
941 return match_len;
942}
943
81a76618 944/* Appends to 'b' the nx_match format that expresses 'match', plus enough zero
7623f4dd
SH
945 * bytes to pad the nx_match out to a multiple of 8. For Flow Mod and Flow
946 * Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
947 * Otherwise, 'cookie_mask' should be zero.
948 *
949 * This function can cause 'b''s data to be reallocated.
950 *
951 * Returns the number of bytes appended to 'b', excluding padding. The return
952 * value can be zero if it appended nothing at all to 'b' (which happens if
953 * 'cr' is a catch-all rule that matches every packet). */
954int
81a76618 955nx_put_match(struct ofpbuf *b, const struct match *match,
7623f4dd
SH
956 ovs_be64 cookie, ovs_be64 cookie_mask)
957{
9d84066c 958 int match_len = nx_put_raw(b, 0, match, cookie, cookie_mask);
7623f4dd 959
f6e984d7 960 ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
7623f4dd
SH
961 return match_len;
962}
963
9d84066c 964/* Appends to 'b' an struct ofp11_match_header followed by the OXM format that
81a76618
BP
965 * expresses 'cr', plus enough zero bytes to pad the data appended out to a
966 * multiple of 8.
7623f4dd 967 *
9d84066c
BP
968 * OXM differs slightly among versions of OpenFlow. Specify the OpenFlow
969 * version in use as 'version'.
970 *
7623f4dd
SH
971 * This function can cause 'b''s data to be reallocated.
972 *
973 * Returns the number of bytes appended to 'b', excluding the padding. Never
974 * returns zero. */
975int
9d84066c
BP
976oxm_put_match(struct ofpbuf *b, const struct match *match,
977 enum ofp_version version)
7623f4dd
SH
978{
979 int match_len;
980 struct ofp11_match_header *omh;
1f317cb5 981 size_t start_len = ofpbuf_size(b);
7623f4dd
SH
982 ovs_be64 cookie = htonll(0), cookie_mask = htonll(0);
983
984 ofpbuf_put_uninit(b, sizeof *omh);
9d84066c
BP
985 match_len = (nx_put_raw(b, version, match, cookie, cookie_mask)
986 + sizeof *omh);
f6e984d7 987 ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
7623f4dd 988
db5a1019 989 omh = ofpbuf_at(b, start_len, sizeof *omh);
7623f4dd
SH
990 omh->type = htons(OFPMT_OXM);
991 omh->length = htons(match_len);
992
09246b99
BP
993 return match_len;
994}
178742f9
BP
995
996void
997nx_put_header(struct ofpbuf *b, enum mf_field_id field,
998 enum ofp_version version, bool masked)
999{
1000 uint32_t header = mf_oxm_header(field, version);
1001 nxm_put_header(b, masked ? nxm_make_wild_header(header) : header);
1002}
1003
1004void
1005nx_put_entry(struct ofpbuf *b,
1006 enum mf_field_id field, enum ofp_version version,
1007 const union mf_value *value, const union mf_value *mask)
1008{
1009 int n_bytes = mf_from_id(field)->n_bytes;
1010 bool masked = mask && !is_all_ones(mask, n_bytes);
1011
1012 nx_put_header(b, field, version, masked);
1013 ofpbuf_put(b, value, n_bytes);
1014 if (masked) {
1015 ofpbuf_put(b, mask, n_bytes);
1016 }
1017}
09246b99
BP
1018\f
1019/* nx_match_to_string() and helpers. */
1020
f393f81e
BP
1021static void format_nxm_field_name(struct ds *, uint32_t header);
1022
09246b99
BP
1023char *
1024nx_match_to_string(const uint8_t *p, unsigned int match_len)
1025{
178742f9 1026 struct ofpbuf b;
09246b99
BP
1027 struct ds s;
1028
1029 if (!match_len) {
1030 return xstrdup("<any>");
1031 }
1032
178742f9 1033 ofpbuf_use_const(&b, p, match_len);
09246b99 1034 ds_init(&s);
178742f9
BP
1035 while (ofpbuf_size(&b)) {
1036 union mf_value value;
1037 union mf_value mask;
1038 enum ofperr error;
1039 uint32_t header;
1040 int value_len;
1041
1042 error = nx_pull_entry__(&b, true, &header, NULL, &value, &mask);
1043 if (error) {
1044 break;
1045 }
1046 value_len = MIN(sizeof value, nxm_field_bytes(header));
09246b99
BP
1047
1048 if (s.length) {
1049 ds_put_cstr(&s, ", ");
1050 }
1051
f393f81e 1052 format_nxm_field_name(&s, header);
09246b99
BP
1053 ds_put_char(&s, '(');
1054
178742f9
BP
1055 for (int i = 0; i < value_len; i++) {
1056 ds_put_format(&s, "%02x", ((const uint8_t *) &value)[i]);
09246b99 1057 }
178742f9 1058 if (nxm_hasmask(header)) {
09246b99 1059 ds_put_char(&s, '/');
178742f9
BP
1060 for (int i = 0; i < value_len; i++) {
1061 ds_put_format(&s, "%02x", ((const uint8_t *) &mask)[i]);
09246b99
BP
1062 }
1063 }
1064 ds_put_char(&s, ')');
09246b99
BP
1065 }
1066
178742f9 1067 if (ofpbuf_size(&b)) {
09246b99
BP
1068 if (s.length) {
1069 ds_put_cstr(&s, ", ");
1070 }
1071
178742f9 1072 ds_put_format(&s, "<%u invalid bytes>", ofpbuf_size(&b));
09246b99
BP
1073 }
1074
1075 return ds_steal_cstr(&s);
1076}
1077
7623f4dd 1078char *
db5a1019 1079oxm_match_to_string(const struct ofpbuf *p, unsigned int match_len)
7623f4dd 1080{
1f317cb5 1081 const struct ofp11_match_header *omh = ofpbuf_data(p);
7623f4dd
SH
1082 uint16_t match_len_;
1083 struct ds s;
1084
1085 ds_init(&s);
1086
1087 if (match_len < sizeof *omh) {
1088 ds_put_format(&s, "<match too short: %u>", match_len);
1089 goto err;
1090 }
1091
1092 if (omh->type != htons(OFPMT_OXM)) {
1093 ds_put_format(&s, "<bad match type field: %u>", ntohs(omh->type));
1094 goto err;
1095 }
1096
1097 match_len_ = ntohs(omh->length);
1098 if (match_len_ < sizeof *omh) {
1099 ds_put_format(&s, "<match length field too short: %u>", match_len_);
1100 goto err;
1101 }
1102
1103 if (match_len_ != match_len) {
1104 ds_put_format(&s, "<match length field incorrect: %u != %u>",
1105 match_len_, match_len);
1106 goto err;
1107 }
1108
db5a1019
AW
1109 return nx_match_to_string(ofpbuf_at(p, sizeof *omh, 0),
1110 match_len - sizeof *omh);
7623f4dd
SH
1111
1112err:
1113 return ds_steal_cstr(&s);
1114}
1115
178742f9
BP
1116void
1117nx_format_field_name(enum mf_field_id id, enum ofp_version version,
1118 struct ds *s)
1119{
1120 format_nxm_field_name(s, mf_oxm_header(id, version));
1121}
1122
f393f81e
BP
1123static void
1124format_nxm_field_name(struct ds *s, uint32_t header)
1125{
178742f9
BP
1126 const struct nxm_field *f = nxm_field_by_header(header);
1127 if (f) {
1128 ds_put_cstr(s, f->name);
1129 if (nxm_hasmask(header)) {
28da1f8f
BP
1130 ds_put_cstr(s, "_W");
1131 }
e729e793
JP
1132 } else if (header == NXM_NX_COOKIE) {
1133 ds_put_cstr(s, "NXM_NX_COOKIE");
1134 } else if (header == NXM_NX_COOKIE_W) {
1135 ds_put_cstr(s, "NXM_NX_COOKIE_W");
f393f81e 1136 } else {
178742f9 1137 ds_put_format(s, "%d:%d", nxm_vendor(header), nxm_field(header));
f393f81e
BP
1138 }
1139}
1140
178742f9
BP
1141static bool
1142streq_len(const char *a, size_t a_len, const char *b)
1143{
1144 return strlen(b) == a_len && !memcmp(a, b, a_len);
1145}
1146
558d80cb
BP
1147static uint32_t
1148parse_nxm_field_name(const char *name, int name_len)
09246b99 1149{
178742f9 1150 const struct nxm_field *f;
28da1f8f 1151 bool wild;
28da1f8f 1152
178742f9
BP
1153 f = mf_parse_subfield_name(name, name_len, &wild);
1154 if (f) {
b5ae8913 1155 if (!wild) {
178742f9
BP
1156 return f->header;
1157 } else if (mf_from_id(f->id)->maskable != MFM_NONE) {
1158 return nxm_make_wild_header(f->header);
09246b99
BP
1159 }
1160 }
1161
178742f9
BP
1162 if (streq_len(name, name_len, "NXM_NX_COOKIE")) {
1163 return NXM_NX_COOKIE;
1164 } else if (streq_len(name, name_len, "NXM_NX_COOKIE_W")) {
1165 return NXM_NX_COOKIE_W;
e729e793
JP
1166 }
1167
558d80cb
BP
1168 /* Check whether it's a 32-bit field header value as hex.
1169 * (This isn't ordinarily useful except for testing error behavior.) */
1170 if (name_len == 8) {
1171 uint32_t header = hexits_value(name, name_len, NULL);
1172 if (header != UINT_MAX) {
1173 return header;
1174 }
1175 }
1176
1177 return 0;
09246b99 1178}
09246b99
BP
1179\f
1180/* nx_match_from_string(). */
1181
7623f4dd
SH
1182static int
1183nx_match_from_string_raw(const char *s, struct ofpbuf *b)
09246b99
BP
1184{
1185 const char *full_s = s;
1f317cb5 1186 const size_t start_len = ofpbuf_size(b);
09246b99
BP
1187
1188 if (!strcmp(s, "<any>")) {
1f317cb5 1189 /* Ensure that 'ofpbuf_data(b)' isn't actually null. */
09246b99
BP
1190 ofpbuf_prealloc_tailroom(b, 1);
1191 return 0;
1192 }
1193
1194 for (s += strspn(s, ", "); *s; s += strspn(s, ", ")) {
558d80cb
BP
1195 const char *name;
1196 uint32_t header;
09246b99 1197 int name_len;
78090f63 1198 size_t n;
09246b99 1199
558d80cb 1200 name = s;
09246b99
BP
1201 name_len = strcspn(s, "(");
1202 if (s[name_len] != '(') {
1203 ovs_fatal(0, "%s: missing ( at end of nx_match", full_s);
1204 }
1205
558d80cb
BP
1206 header = parse_nxm_field_name(name, name_len);
1207 if (!header) {
09246b99
BP
1208 ovs_fatal(0, "%s: unknown field `%.*s'", full_s, name_len, s);
1209 }
1210
1211 s += name_len + 1;
1212
558d80cb 1213 nxm_put_header(b, header);
78090f63
BP
1214 s = ofpbuf_put_hex(b, s, &n);
1215 if (n != nxm_field_bytes(header)) {
1216 ovs_fatal(0, "%.2s: hex digits expected", s);
1217 }
178742f9 1218 if (nxm_hasmask(header)) {
09246b99
BP
1219 s += strspn(s, " ");
1220 if (*s != '/') {
558d80cb
BP
1221 ovs_fatal(0, "%s: missing / in masked field %.*s",
1222 full_s, name_len, name);
09246b99 1223 }
78090f63
BP
1224 s = ofpbuf_put_hex(b, s + 1, &n);
1225 if (n != nxm_field_bytes(header)) {
1226 ovs_fatal(0, "%.2s: hex digits expected", s);
1227 }
09246b99
BP
1228 }
1229
1230 s += strspn(s, " ");
1231 if (*s != ')') {
558d80cb
BP
1232 ovs_fatal(0, "%s: missing ) following field %.*s",
1233 full_s, name_len, name);
09246b99
BP
1234 }
1235 s++;
1236 }
1237
1f317cb5 1238 return ofpbuf_size(b) - start_len;
7623f4dd
SH
1239}
1240
1241int
1242nx_match_from_string(const char *s, struct ofpbuf *b)
1243{
1244 int match_len = nx_match_from_string_raw(s, b);
f6e984d7 1245 ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
7623f4dd
SH
1246 return match_len;
1247}
1248
1249int
1250oxm_match_from_string(const char *s, struct ofpbuf *b)
1251{
1252 int match_len;
1253 struct ofp11_match_header *omh;
1f317cb5 1254 size_t start_len = ofpbuf_size(b);
7623f4dd
SH
1255
1256 ofpbuf_put_uninit(b, sizeof *omh);
1257 match_len = nx_match_from_string_raw(s, b) + sizeof *omh;
f6e984d7 1258 ofpbuf_put_zeros(b, PAD_SIZE(match_len, 8));
7623f4dd 1259
db5a1019 1260 omh = ofpbuf_at(b, start_len, sizeof *omh);
7623f4dd
SH
1261 omh->type = htons(OFPMT_OXM);
1262 omh->length = htons(match_len);
1263
09246b99
BP
1264 return match_len;
1265}
b6c9e612 1266\f
bdda5aca
BP
1267/* Parses 's' as a "move" action, in the form described in ovs-ofctl(8), into
1268 * '*move'.
1269 *
1270 * Returns NULL if successful, otherwise a malloc()'d string describing the
1271 * error. The caller is responsible for freeing the returned string. */
1272char * WARN_UNUSED_RESULT
f25d0cf3 1273nxm_parse_reg_move(struct ofpact_reg_move *move, const char *s)
f393f81e
BP
1274{
1275 const char *full_s = s;
bdda5aca 1276 char *error;
f393f81e 1277
bdda5aca
BP
1278 error = mf_parse_subfield__(&move->src, &s);
1279 if (error) {
1280 return error;
1281 }
f393f81e 1282 if (strncmp(s, "->", 2)) {
bdda5aca 1283 return xasprintf("%s: missing `->' following source", full_s);
f393f81e
BP
1284 }
1285 s += 2;
bdda5aca
BP
1286 error = mf_parse_subfield(&move->dst, s);
1287 if (error) {
1288 return error;
f393f81e
BP
1289 }
1290
f25d0cf3 1291 if (move->src.n_bits != move->dst.n_bits) {
bdda5aca
BP
1292 return xasprintf("%s: source field is %d bits wide but destination is "
1293 "%d bits wide", full_s,
1294 move->src.n_bits, move->dst.n_bits);
f393f81e 1295 }
bdda5aca 1296 return NULL;
f393f81e 1297}
f393f81e 1298\f
7eb4b1f1 1299/* nxm_format_reg_move(). */
f393f81e 1300
f393f81e 1301void
f25d0cf3 1302nxm_format_reg_move(const struct ofpact_reg_move *move, struct ds *s)
f393f81e 1303{
f393f81e 1304 ds_put_format(s, "move:");
f25d0cf3 1305 mf_format_subfield(&move->src, s);
f393f81e 1306 ds_put_cstr(s, "->");
f25d0cf3 1307 mf_format_subfield(&move->dst, s);
f393f81e
BP
1308}
1309
f25d0cf3
BP
1310\f
1311enum ofperr
f25d0cf3 1312nxm_reg_move_check(const struct ofpact_reg_move *move, const struct flow *flow)
43edca57 1313{
90bf1e07 1314 enum ofperr error;
43edca57 1315
f25d0cf3 1316 error = mf_check_src(&move->src, flow);
43edca57
EJ
1317 if (error) {
1318 return error;
b6c9e612
BP
1319 }
1320
f25d0cf3
BP
1321 return mf_check_dst(&move->dst, NULL);
1322}
f25d0cf3 1323\f
7eb4b1f1 1324/* nxm_execute_reg_move(). */
b6c9e612
BP
1325
1326void
f25d0cf3 1327nxm_execute_reg_move(const struct ofpact_reg_move *move,
bcd2633a 1328 struct flow *flow, struct flow_wildcards *wc)
b6c9e612 1329{
f25d0cf3
BP
1330 union mf_value src_value;
1331 union mf_value dst_value;
816fd533 1332
f47ea021
JR
1333 mf_mask_field_and_prereqs(move->dst.field, &wc->masks);
1334 mf_mask_field_and_prereqs(move->src.field, &wc->masks);
bcd2633a 1335
f25d0cf3
BP
1336 mf_get_value(move->dst.field, flow, &dst_value);
1337 mf_get_value(move->src.field, flow, &src_value);
1338 bitwise_copy(&src_value, move->src.field->n_bytes, move->src.ofs,
1339 &dst_value, move->dst.field->n_bytes, move->dst.ofs,
1340 move->src.n_bits);
1341 mf_set_flow_value(move->dst.field, &dst_value, flow);
43edca57 1342}
b6c9e612 1343
816fd533 1344void
f25d0cf3 1345nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data,
f74e7df7 1346 struct flow *flow, struct flow_wildcards *wc)
816fd533 1347{
9bab681f 1348 union mf_subvalue src_subvalue;
f74e7df7 1349 union mf_subvalue mask_value;
9bab681f 1350 ovs_be64 src_data_be = htonll(src_data);
f25d0cf3 1351
f74e7df7
JP
1352 memset(&mask_value, 0xff, sizeof mask_value);
1353 mf_write_subfield_flow(dst, &mask_value, &wc->masks);
1354
9bab681f
IY
1355 bitwise_copy(&src_data_be, sizeof src_data_be, 0,
1356 &src_subvalue, sizeof src_subvalue, 0,
1357 sizeof src_data_be * 8);
1358 mf_write_subfield_flow(dst, &src_subvalue, flow);
b6c9e612 1359}
bd85dac1
AZ
1360\f
1361/* nxm_parse_stack_action, works for both push() and pop(). */
bdda5aca
BP
1362
1363/* Parses 's' as a "push" or "pop" action, in the form described in
1364 * ovs-ofctl(8), into '*stack_action'.
1365 *
1366 * Returns NULL if successful, otherwise a malloc()'d string describing the
1367 * error. The caller is responsible for freeing the returned string. */
1368char * WARN_UNUSED_RESULT
bd85dac1
AZ
1369nxm_parse_stack_action(struct ofpact_stack *stack_action, const char *s)
1370{
bdda5aca
BP
1371 char *error;
1372
1373 error = mf_parse_subfield__(&stack_action->subfield, &s);
1374 if (error) {
1375 return error;
1376 }
1377
bd85dac1 1378 if (*s != '\0') {
bdda5aca 1379 return xasprintf("%s: trailing garbage following push or pop", s);
bd85dac1 1380 }
bdda5aca
BP
1381
1382 return NULL;
bd85dac1
AZ
1383}
1384
1385void
1386nxm_format_stack_push(const struct ofpact_stack *push, struct ds *s)
1387{
1388 ds_put_cstr(s, "push:");
1389 mf_format_subfield(&push->subfield, s);
1390}
1391
1392void
1393nxm_format_stack_pop(const struct ofpact_stack *pop, struct ds *s)
1394{
1395 ds_put_cstr(s, "pop:");
1396 mf_format_subfield(&pop->subfield, s);
1397}
1398
bd85dac1
AZ
1399enum ofperr
1400nxm_stack_push_check(const struct ofpact_stack *push,
1401 const struct flow *flow)
1402{
1403 return mf_check_src(&push->subfield, flow);
1404}
1405
1406enum ofperr
1407nxm_stack_pop_check(const struct ofpact_stack *pop,
1408 const struct flow *flow)
1409{
1410 return mf_check_dst(&pop->subfield, flow);
1411}
1412
bd85dac1
AZ
1413/* nxm_execute_stack_push(), nxm_execute_stack_pop(). */
1414static void
1415nx_stack_push(struct ofpbuf *stack, union mf_subvalue *v)
1416{
1417 ofpbuf_put(stack, v, sizeof *v);
1418}
1419
1420static union mf_subvalue *
1421nx_stack_pop(struct ofpbuf *stack)
1422{
1423 union mf_subvalue *v = NULL;
1424
1f317cb5
PS
1425 if (ofpbuf_size(stack)) {
1426
1427 ofpbuf_set_size(stack, ofpbuf_size(stack) - sizeof *v);
bd85dac1
AZ
1428 v = (union mf_subvalue *) ofpbuf_tail(stack);
1429 }
1430
1431 return v;
1432}
1433
1434void
1435nxm_execute_stack_push(const struct ofpact_stack *push,
bcd2633a
JP
1436 const struct flow *flow, struct flow_wildcards *wc,
1437 struct ofpbuf *stack)
bd85dac1 1438{
bcd2633a 1439 union mf_subvalue mask_value;
bd85dac1
AZ
1440 union mf_subvalue dst_value;
1441
bcd2633a
JP
1442 memset(&mask_value, 0xff, sizeof mask_value);
1443 mf_write_subfield_flow(&push->subfield, &mask_value, &wc->masks);
1444
bd85dac1
AZ
1445 mf_read_subfield(&push->subfield, flow, &dst_value);
1446 nx_stack_push(stack, &dst_value);
1447}
1448
1449void
1450nxm_execute_stack_pop(const struct ofpact_stack *pop,
f74e7df7
JP
1451 struct flow *flow, struct flow_wildcards *wc,
1452 struct ofpbuf *stack)
bd85dac1
AZ
1453{
1454 union mf_subvalue *src_value;
1455
1456 src_value = nx_stack_pop(stack);
1457
1458 /* Only pop if stack is not empty. Otherwise, give warning. */
1459 if (src_value) {
f74e7df7
JP
1460 union mf_subvalue mask_value;
1461
1462 memset(&mask_value, 0xff, sizeof mask_value);
1463 mf_write_subfield_flow(&pop->subfield, &mask_value, &wc->masks);
bd85dac1
AZ
1464 mf_write_subfield_flow(&pop->subfield, src_value, flow);
1465 } else {
1466 if (!VLOG_DROP_WARN(&rl)) {
1467 char *flow_str = flow_to_string(flow);
1468 VLOG_WARN_RL(&rl, "Failed to pop from an empty stack. On flow \n"
1469 " %s", flow_str);
1470 free(flow_str);
1471 }
1472 }
1473}
178742f9
BP
1474\f
1475/* Formats 'sf' into 's' in a format normally acceptable to
1476 * mf_parse_subfield(). (It won't be acceptable if sf->field is NULL or if
1477 * sf->field has no NXM name.) */
1478void
1479mf_format_subfield(const struct mf_subfield *sf, struct ds *s)
1480{
1481 if (!sf->field) {
1482 ds_put_cstr(s, "<unknown>");
1483 } else {
1484 const struct nxm_field *f = nxm_field_from_mf_field(sf->field->id, 0);
1485 ds_put_cstr(s, f ? f->name : sf->field->name);
1486 }
1487
1488 if (sf->field && sf->ofs == 0 && sf->n_bits == sf->field->n_bits) {
1489 ds_put_cstr(s, "[]");
1490 } else if (sf->n_bits == 1) {
1491 ds_put_format(s, "[%d]", sf->ofs);
1492 } else {
1493 ds_put_format(s, "[%d..%d]", sf->ofs, sf->ofs + sf->n_bits - 1);
1494 }
1495}
1496
1497static const struct nxm_field *
1498mf_parse_subfield_name(const char *name, int name_len, bool *wild)
1499{
1500 *wild = name_len > 2 && !memcmp(&name[name_len - 2], "_W", 2);
1501 if (*wild) {
1502 name_len -= 2;
1503 }
1504
1505 return nxm_field_by_name(name, name_len);
1506}
1507
1508/* Parses a subfield from the beginning of '*sp' into 'sf'. If successful,
1509 * returns NULL and advances '*sp' to the first byte following the parsed
1510 * string. On failure, returns a malloc()'d error message, does not modify
1511 * '*sp', and does not properly initialize 'sf'.
1512 *
1513 * The syntax parsed from '*sp' takes the form "header[start..end]" where
1514 * 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
1515 * bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
1516 * may both be omitted (the [] are still required) to indicate an entire
1517 * field. */
1518char * WARN_UNUSED_RESULT
1519mf_parse_subfield__(struct mf_subfield *sf, const char **sp)
1520{
1521 const struct mf_field *field;
1522 const struct nxm_field *f;
1523 const char *name;
1524 int start, end;
1525 const char *s;
1526 int name_len;
1527 bool wild;
1528
1529 s = *sp;
1530 name = s;
1531 name_len = strcspn(s, "[");
1532 if (s[name_len] != '[') {
1533 return xasprintf("%s: missing [ looking for field name", *sp);
1534 }
1535
1536 f = mf_parse_subfield_name(name, name_len, &wild);
1537 if (!f) {
1538 return xasprintf("%s: unknown field `%.*s'", *sp, name_len, s);
1539 }
1540 field = mf_from_id(f->id);
1541
1542 s += name_len;
1543 if (ovs_scan(s, "[%d..%d]", &start, &end)) {
1544 /* Nothing to do. */
1545 } else if (ovs_scan(s, "[%d]", &start)) {
1546 end = start;
1547 } else if (!strncmp(s, "[]", 2)) {
1548 start = 0;
1549 end = field->n_bits - 1;
1550 } else {
1551 return xasprintf("%s: syntax error expecting [] or [<bit>] or "
1552 "[<start>..<end>]", *sp);
1553 }
1554 s = strchr(s, ']') + 1;
1555
1556 if (start > end) {
1557 return xasprintf("%s: starting bit %d is after ending bit %d",
1558 *sp, start, end);
1559 } else if (start >= field->n_bits) {
1560 return xasprintf("%s: starting bit %d is not valid because field is "
1561 "only %d bits wide", *sp, start, field->n_bits);
1562 } else if (end >= field->n_bits){
1563 return xasprintf("%s: ending bit %d is not valid because field is "
1564 "only %d bits wide", *sp, end, field->n_bits);
1565 }
1566
1567 sf->field = field;
1568 sf->ofs = start;
1569 sf->n_bits = end - start + 1;
1570
1571 *sp = s;
1572 return NULL;
1573}
1574
1575/* Parses a subfield from the entirety of 's' into 'sf'. Returns NULL if
1576 * successful, otherwise a malloc()'d string describing the error. The caller
1577 * is responsible for freeing the returned string.
1578 *
1579 * The syntax parsed from 's' takes the form "header[start..end]" where
1580 * 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
1581 * bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
1582 * may both be omitted (the [] are still required) to indicate an entire
1583 * field. */
1584char * WARN_UNUSED_RESULT
1585mf_parse_subfield(struct mf_subfield *sf, const char *s)
1586{
1587 char *error = mf_parse_subfield__(sf, &s);
1588 if (!error && s[0]) {
1589 error = xstrdup("unexpected input following field syntax");
1590 }
1591 return error;
1592}
1593\f
1594/* Returns an bitmap in which each bit corresponds to the like-numbered field
1595 * in the OFPXMC12_OPENFLOW_BASIC OXM class, in which the bit values are taken
1596 * from the 'fields' bitmap. Only fields defined in OpenFlow 'version' are
1597 * considered.
1598 *
1599 * This is useful for encoding OpenFlow 1.2 table stats messages. */
1600ovs_be64
1601oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *fields,
1602 enum ofp_version version)
1603{
1604 uint64_t oxm_bitmap = 0;
1605 int i;
1606
1607 BITMAP_FOR_EACH_1 (i, MFF_N_IDS, fields->bm) {
1608 uint32_t oxm = mf_oxm_header(i, version);
1609 uint32_t vendor = nxm_vendor(oxm);
1610 int field = nxm_field(oxm);
1611
1612 if (vendor == OFPXMC12_OPENFLOW_BASIC && field < 64) {
1613 oxm_bitmap |= UINT64_C(1) << field;
1614 }
1615 }
1616 return htonll(oxm_bitmap);
1617}
1618
1619/* Opposite conversion from oxm_bitmap_from_mf_bitmap().
1620 *
1621 * This is useful for decoding OpenFlow 1.2 table stats messages. */
1622struct mf_bitmap
1623oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, enum ofp_version version)
1624{
1625 struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
1626
1627 for (enum mf_field_id id = 0; id < MFF_N_IDS; id++) {
1628 if (version >= mf_oxm_version(id)) {
1629 uint32_t oxm = mf_oxm_header(id, version);
1630 uint32_t vendor = nxm_vendor(oxm);
1631 int field = nxm_field(oxm);
1632
1633 if (vendor == OFPXMC12_OPENFLOW_BASIC
1634 && field < 64
1635 && oxm_bitmap & htonll(UINT64_C(1) << field)) {
1636 bitmap_set1(fields.bm, id);
1637 }
1638 }
1639 }
1640 return fields;
1641}
1642
1643/* Returns a bitmap of fields that can be encoded in OXM and that can be
1644 * modified with a "set_field" action. */
1645struct mf_bitmap
1646oxm_writable_fields(void)
1647{
1648 struct mf_bitmap b = MF_BITMAP_INITIALIZER;
1649 int i;
1650
1651 for (i = 0; i < MFF_N_IDS; i++) {
1652 if (mf_oxm_header(i, 0) && mf_from_id(i)->writable) {
1653 bitmap_set1(b.bm, i);
1654 }
1655 }
1656 return b;
1657}
1658
1659/* Returns a bitmap of fields that can be encoded in OXM and that can be
1660 * matched in a flow table. */
1661struct mf_bitmap
1662oxm_matchable_fields(void)
1663{
1664 struct mf_bitmap b = MF_BITMAP_INITIALIZER;
1665 int i;
1666
1667 for (i = 0; i < MFF_N_IDS; i++) {
1668 if (mf_oxm_header(i, 0)) {
1669 bitmap_set1(b.bm, i);
1670 }
1671 }
1672 return b;
1673}
1674
1675/* Returns a bitmap of fields that can be encoded in OXM and that can be
1676 * matched in a flow table with an arbitrary bitmask. */
1677struct mf_bitmap
1678oxm_maskable_fields(void)
1679{
1680 struct mf_bitmap b = MF_BITMAP_INITIALIZER;
1681 int i;
1682
1683 for (i = 0; i < MFF_N_IDS; i++) {
1684 if (mf_oxm_header(i, 0) && mf_from_id(i)->maskable == MFM_FULLY) {
1685 bitmap_set1(b.bm, i);
1686 }
1687 }
1688 return b;
1689}
1690\f
1691struct nxm_field_index {
1692 struct hmap_node header_node;
1693 struct hmap_node name_node;
1694 struct nxm_field nf;
1695};
1696
1697#include "nx-match.inc"
1698
1699static struct hmap nxm_header_map;
1700static struct hmap nxm_name_map;
1701static struct nxm_field *nxm_fields[MFF_N_IDS];
1702static struct nxm_field *oxm_fields[MFF_N_IDS];
1703
1704static void
1705nxm_init(void)
1706{
1707 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
1708 if (ovsthread_once_start(&once)) {
1709 hmap_init(&nxm_header_map);
1710 hmap_init(&nxm_name_map);
1711 for (struct nxm_field_index *nfi = all_nxm_fields;
1712 nfi < &all_nxm_fields[ARRAY_SIZE(all_nxm_fields)]; nfi++) {
1713 hmap_insert(&nxm_header_map, &nfi->header_node,
1714 hash_int(nfi->nf.header, 0));
1715 hmap_insert(&nxm_name_map, &nfi->name_node,
1716 hash_string(nfi->nf.name, 0));
1717 if (is_nxm_header(nfi->nf.header)) {
1718 nxm_fields[nfi->nf.id] = &nfi->nf;
1719 } else {
1720 oxm_fields[nfi->nf.id] = &nfi->nf;
1721 }
1722 }
1723 ovsthread_once_done(&once);
1724 }
1725}
1726
1727static const struct nxm_field *
1728nxm_field_by_header(uint32_t header)
1729{
1730 const struct nxm_field_index *nfi;
1731
1732 nxm_init();
1733 if (nxm_hasmask(header)) {
1734 header = nxm_make_exact_header(header);
1735 }
1736
1737 HMAP_FOR_EACH_IN_BUCKET (nfi, header_node, hash_int(header, 0),
1738 &nxm_header_map) {
1739 if (header == nfi->nf.header) {
1740 return &nfi->nf;
1741 }
1742 }
1743 return NULL;
1744}
1745
1746static const struct nxm_field *
1747nxm_field_by_name(const char *name, size_t len)
1748{
1749 const struct nxm_field_index *nfi;
1750
1751 nxm_init();
1752 HMAP_FOR_EACH_WITH_HASH (nfi, name_node, hash_bytes(name, len, 0),
1753 &nxm_name_map) {
1754 if (strlen(nfi->nf.name) == len && !memcmp(nfi->nf.name, name, len)) {
1755 return &nfi->nf;
1756 }
1757 }
1758 return NULL;
1759}
1760
1761static const struct nxm_field *
1762nxm_field_by_mf_id(enum mf_field_id id)
1763{
1764 nxm_init();
1765 return nxm_fields[id];
1766}
1767
1768static const struct nxm_field *
1769oxm_field_by_mf_id(enum mf_field_id id)
1770{
1771 nxm_init();
1772 return oxm_fields[id];
1773}
1774