]> git.proxmox.com Git - ovs.git/blame - lib/nx-match.c
meta-flow: Accept NXM and OXM field names, support NXM and OXM for output.
[ovs.git] / lib / nx-match.c
CommitLineData
09246b99 1/*
e0edde6f 2 * Copyright (c) 2010, 2011, 2012 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"
6a885fd0 25#include "meta-flow.h"
90bf1e07 26#include "ofp-errors.h"
09246b99
BP
27#include "ofp-util.h"
28#include "ofpbuf.h"
29#include "openflow/nicira-ext.h"
30#include "packets.h"
31#include "unaligned.h"
ddc4f8e2 32#include "util.h"
09246b99
BP
33#include "vlog.h"
34
35VLOG_DEFINE_THIS_MODULE(nx_match);
36
37/* Rate limit for nx_match parse errors. These always indicate a bug in the
38 * peer and so there's not much point in showing a lot of them. */
39static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
40
09246b99
BP
41/* Returns the width of the data for a field with the given 'header', in
42 * bytes. */
4291acd2 43int
09246b99
BP
44nxm_field_bytes(uint32_t header)
45{
46 unsigned int length = NXM_LENGTH(header);
47 return NXM_HASMASK(header) ? length / 2 : length;
48}
b6c9e612
BP
49
50/* Returns the width of the data for a field with the given 'header', in
51 * bits. */
4291acd2 52int
b6c9e612
BP
53nxm_field_bits(uint32_t header)
54{
55 return nxm_field_bytes(header) * 8;
56}
6a885fd0
BP
57\f
58/* nx_pull_match() and helpers. */
09246b99
BP
59
60static uint32_t
61nx_entry_ok(const void *p, unsigned int match_len)
62{
63 unsigned int payload_len;
64 ovs_be32 header_be;
65 uint32_t header;
66
67 if (match_len < 4) {
68 if (match_len) {
69 VLOG_DBG_RL(&rl, "nx_match ends with partial nxm_header");
70 }
71 return 0;
72 }
73 memcpy(&header_be, p, 4);
74 header = ntohl(header_be);
75
76 payload_len = NXM_LENGTH(header);
77 if (!payload_len) {
78 VLOG_DBG_RL(&rl, "nxm_entry %08"PRIx32" has invalid payload "
79 "length 0", header);
80 return 0;
81 }
82 if (match_len < payload_len + 4) {
83 VLOG_DBG_RL(&rl, "%"PRIu32"-byte nxm_entry but only "
84 "%u bytes left in nx_match", payload_len + 4, match_len);
85 return 0;
86 }
87
88 return header;
89}
90
90bf1e07 91static enum ofperr
102ce766
EJ
92nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
93 uint16_t priority, struct cls_rule *rule,
94 ovs_be64 *cookie, ovs_be64 *cookie_mask)
09246b99
BP
95{
96 uint32_t header;
97 uint8_t *p;
98
e729e793
JP
99 assert((cookie != NULL) == (cookie_mask != NULL));
100
09246b99
BP
101 p = ofpbuf_try_pull(b, ROUND_UP(match_len, 8));
102 if (!p) {
e5fccb40 103 VLOG_DBG_RL(&rl, "nx_match length %u, rounded up to a "
09246b99
BP
104 "multiple of 8, is longer than space in message (max "
105 "length %zu)", match_len, b->size);
2e0525bc 106 return OFPERR_OFPBMC_BAD_LEN;
09246b99
BP
107 }
108
109 cls_rule_init_catchall(rule, priority);
e729e793
JP
110 if (cookie) {
111 *cookie = *cookie_mask = htonll(0);
112 }
102ce766
EJ
113 for (;
114 (header = nx_entry_ok(p, match_len)) != 0;
115 p += 4 + NXM_LENGTH(header), match_len -= 4 + NXM_LENGTH(header)) {
28da1f8f 116 const struct mf_field *mf;
90bf1e07 117 enum ofperr error;
09246b99 118
28da1f8f
BP
119 mf = mf_from_nxm_header(header);
120 if (!mf) {
102ce766 121 if (strict) {
2e0525bc 122 error = OFPERR_OFPBMC_BAD_FIELD;
102ce766
EJ
123 } else {
124 continue;
125 }
28da1f8f 126 } else if (!mf_are_prereqs_ok(mf, &rule->flow)) {
2e0525bc 127 error = OFPERR_OFPBMC_BAD_PREREQ;
28da1f8f 128 } else if (!mf_is_all_wild(mf, &rule->wc)) {
2e0525bc 129 error = OFPERR_OFPBMC_DUP_FIELD;
b5ae8913 130 } else if (header != OXM_OF_IN_PORT) {
28da1f8f 131 unsigned int width = mf->n_bytes;
6a885fd0
BP
132 union mf_value value;
133
134 memcpy(&value, p + 4, width);
28da1f8f 135 if (!mf_is_value_valid(mf, &value)) {
2e0525bc 136 error = OFPERR_OFPBMC_BAD_VALUE;
6a885fd0
BP
137 } else if (!NXM_HASMASK(header)) {
138 error = 0;
28da1f8f 139 mf_set_value(mf, &value, rule);
6a885fd0
BP
140 } else {
141 union mf_value mask;
142
143 memcpy(&mask, p + 4 + width, width);
28da1f8f 144 if (!mf_is_mask_valid(mf, &mask)) {
2e0525bc 145 error = OFPERR_OFPBMC_BAD_MASK;
6a885fd0
BP
146 } else {
147 error = 0;
28da1f8f 148 mf_set(mf, &value, &mask, rule);
6a885fd0
BP
149 }
150 }
b5ae8913
SH
151 } else {
152 /* Special case for 32bit ports when using OXM,
153 * ports are 16 bits wide otherwise. */
154 ovs_be32 port_of11;
155 uint16_t port;
156
157 memcpy(&port_of11, p + 4, sizeof port_of11);
158 error = ofputil_port_from_ofp11(port_of11, &port);
159 if (!error) {
160 cls_rule_set_in_port(rule, port);
161 }
09246b99 162 }
6a885fd0 163
e729e793
JP
164 /* Check if the match is for a cookie rather than a classifier rule. */
165 if ((header == NXM_NX_COOKIE || header == NXM_NX_COOKIE_W) && cookie) {
166 if (*cookie_mask) {
2e0525bc 167 error = OFPERR_OFPBMC_DUP_FIELD;
e729e793
JP
168 } else {
169 unsigned int width = sizeof *cookie;
170
171 memcpy(cookie, p + 4, width);
172 if (NXM_HASMASK(header)) {
173 memcpy(cookie_mask, p + 4 + width, width);
174 } else {
175 *cookie_mask = htonll(UINT64_MAX);
176 }
177 error = 0;
178 }
179 }
180
09246b99 181 if (error) {
28da1f8f
BP
182 VLOG_DBG_RL(&rl, "bad nxm_entry %#08"PRIx32" (vendor=%"PRIu32", "
183 "field=%"PRIu32", hasmask=%"PRIu32", len=%"PRIu32"), "
184 "(%s)", header,
09246b99 185 NXM_VENDOR(header), NXM_FIELD(header),
28da1f8f 186 NXM_HASMASK(header), NXM_LENGTH(header),
90bf1e07 187 ofperr_to_string(error));
09246b99
BP
188 return error;
189 }
09246b99
BP
190 }
191
2e0525bc 192 return match_len ? OFPERR_OFPBMC_BAD_LEN : 0;
09246b99 193}
102ce766
EJ
194
195/* Parses the nx_match formatted match description in 'b' with length
196 * 'match_len'. The results are stored in 'rule', which is initialized with
197 * 'priority'. If 'cookie' and 'cookie_mask' contain valid pointers, then the
198 * cookie and mask will be stored in them if a "NXM_NX_COOKIE*" match is
199 * defined. Otherwise, 0 is stored in both.
200 *
201 * Fails with an error when encountering unknown NXM headers.
202 *
203 * Returns 0 if successful, otherwise an OpenFlow error code. */
90bf1e07 204enum ofperr
102ce766
EJ
205nx_pull_match(struct ofpbuf *b, unsigned int match_len,
206 uint16_t priority, struct cls_rule *rule,
207 ovs_be64 *cookie, ovs_be64 *cookie_mask)
208{
209 return nx_pull_match__(b, match_len, true, priority, rule, cookie,
210 cookie_mask);
211}
212
213/* Behaves the same as nx_pull_match() with one exception. Skips over unknown
214 * NXM headers instead of failing with an error when they are encountered. */
90bf1e07 215enum ofperr
102ce766
EJ
216nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
217 uint16_t priority, struct cls_rule *rule,
218 ovs_be64 *cookie, ovs_be64 *cookie_mask)
219{
220 return nx_pull_match__(b, match_len, false, priority, rule, cookie,
221 cookie_mask);
222}
09246b99
BP
223\f
224/* nx_put_match() and helpers.
225 *
226 * 'put' functions whose names end in 'w' add a wildcarded field.
227 * 'put' functions whose names end in 'm' add a field that might be wildcarded.
228 * Other 'put' functions add exact-match fields.
229 */
230
231static void
232nxm_put_header(struct ofpbuf *b, uint32_t header)
233{
234 ovs_be32 n_header = htonl(header);
235 ofpbuf_put(b, &n_header, sizeof n_header);
236}
237
238static void
239nxm_put_8(struct ofpbuf *b, uint32_t header, uint8_t value)
240{
241 nxm_put_header(b, header);
242 ofpbuf_put(b, &value, sizeof value);
243}
244
7257b535
BP
245static void
246nxm_put_8m(struct ofpbuf *b, uint32_t header, uint8_t value, uint8_t mask)
247{
248 switch (mask) {
249 case 0:
250 break;
251
252 case UINT8_MAX:
253 nxm_put_8(b, header, value);
254 break;
255
256 default:
257 nxm_put_header(b, NXM_MAKE_WILD_HEADER(header));
258 ofpbuf_put(b, &value, sizeof value);
259 ofpbuf_put(b, &mask, sizeof mask);
260 }
261}
262
09246b99
BP
263static void
264nxm_put_16(struct ofpbuf *b, uint32_t header, ovs_be16 value)
265{
266 nxm_put_header(b, header);
267 ofpbuf_put(b, &value, sizeof value);
268}
269
270static void
271nxm_put_16w(struct ofpbuf *b, uint32_t header, ovs_be16 value, ovs_be16 mask)
272{
273 nxm_put_header(b, header);
274 ofpbuf_put(b, &value, sizeof value);
275 ofpbuf_put(b, &mask, sizeof mask);
276}
277
66642cb4
BP
278static void
279nxm_put_16m(struct ofpbuf *b, uint32_t header, ovs_be16 value, ovs_be16 mask)
280{
281 switch (mask) {
282 case 0:
283 break;
284
285 case CONSTANT_HTONS(UINT16_MAX):
286 nxm_put_16(b, header, value);
287 break;
288
289 default:
290 nxm_put_16w(b, NXM_MAKE_WILD_HEADER(header), value, mask);
291 break;
292 }
293}
294
09246b99
BP
295static void
296nxm_put_32(struct ofpbuf *b, uint32_t header, ovs_be32 value)
297{
298 nxm_put_header(b, header);
299 ofpbuf_put(b, &value, sizeof value);
300}
301
302static void
303nxm_put_32w(struct ofpbuf *b, uint32_t header, ovs_be32 value, ovs_be32 mask)
304{
305 nxm_put_header(b, header);
306 ofpbuf_put(b, &value, sizeof value);
307 ofpbuf_put(b, &mask, sizeof mask);
308}
309
310static void
311nxm_put_32m(struct ofpbuf *b, uint32_t header, ovs_be32 value, ovs_be32 mask)
312{
313 switch (mask) {
314 case 0:
315 break;
316
66642cb4 317 case CONSTANT_HTONL(UINT32_MAX):
09246b99
BP
318 nxm_put_32(b, header, value);
319 break;
320
321 default:
322 nxm_put_32w(b, NXM_MAKE_WILD_HEADER(header), value, mask);
323 break;
324 }
325}
326
327static void
328nxm_put_64(struct ofpbuf *b, uint32_t header, ovs_be64 value)
329{
330 nxm_put_header(b, header);
331 ofpbuf_put(b, &value, sizeof value);
332}
333
8368c090
BP
334static void
335nxm_put_64w(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask)
336{
337 nxm_put_header(b, header);
338 ofpbuf_put(b, &value, sizeof value);
339 ofpbuf_put(b, &mask, sizeof mask);
340}
341
342static void
343nxm_put_64m(struct ofpbuf *b, uint32_t header, ovs_be64 value, ovs_be64 mask)
344{
345 switch (mask) {
346 case 0:
347 break;
348
349 case CONSTANT_HTONLL(UINT64_MAX):
350 nxm_put_64(b, header, value);
351 break;
352
353 default:
354 nxm_put_64w(b, NXM_MAKE_WILD_HEADER(header), value, mask);
355 break;
356 }
357}
358
09246b99
BP
359static void
360nxm_put_eth(struct ofpbuf *b, uint32_t header,
361 const uint8_t value[ETH_ADDR_LEN])
362{
363 nxm_put_header(b, header);
364 ofpbuf_put(b, value, ETH_ADDR_LEN);
365}
366
1e37a2d7 367static void
73c0ce34
JS
368nxm_put_eth_masked(struct ofpbuf *b, uint32_t header,
369 const uint8_t value[ETH_ADDR_LEN],
370 const uint8_t mask[ETH_ADDR_LEN])
1e37a2d7 371{
73c0ce34
JS
372 if (!eth_addr_is_zero(mask)) {
373 if (eth_mask_is_exact(mask)) {
374 nxm_put_eth(b, header, value);
375 } else {
376 nxm_put_header(b, NXM_MAKE_WILD_HEADER(header));
377 ofpbuf_put(b, value, ETH_ADDR_LEN);
378 ofpbuf_put(b, mask, ETH_ADDR_LEN);
379 }
1e37a2d7
BP
380 }
381}
382
d31f1109
JP
383static void
384nxm_put_ipv6(struct ofpbuf *b, uint32_t header,
385 const struct in6_addr *value, const struct in6_addr *mask)
386{
387 if (ipv6_mask_is_any(mask)) {
388 return;
389 } else if (ipv6_mask_is_exact(mask)) {
390 nxm_put_header(b, header);
391 ofpbuf_put(b, value, sizeof *value);
392 } else {
393 nxm_put_header(b, NXM_MAKE_WILD_HEADER(header));
394 ofpbuf_put(b, value, sizeof *value);
395 ofpbuf_put(b, mask, sizeof *mask);
396 }
397}
398
7257b535 399static void
9e44d715 400nxm_put_frag(struct ofpbuf *b, const struct cls_rule *cr)
7257b535 401{
eadef313
JP
402 uint8_t nw_frag = cr->flow.nw_frag;
403 uint8_t nw_frag_mask = cr->wc.nw_frag_mask;
7257b535 404
eadef313 405 switch (nw_frag_mask) {
7257b535
BP
406 case 0:
407 break;
408
eadef313
JP
409 case FLOW_NW_FRAG_MASK:
410 nxm_put_8(b, NXM_NX_IP_FRAG, nw_frag);
7257b535
BP
411 break;
412
413 default:
eadef313
JP
414 nxm_put_8m(b, NXM_NX_IP_FRAG, nw_frag,
415 nw_frag_mask & FLOW_NW_FRAG_MASK);
7257b535
BP
416 break;
417 }
418}
419
8e7082b0
BP
420static void
421nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr,
b5ae8913
SH
422 uint8_t icmp_proto, uint32_t icmp_type, uint32_t icmp_code,
423 bool oxm)
8e7082b0
BP
424{
425 const flow_wildcards_t wc = cr->wc.wildcards;
426 const struct flow *flow = &cr->flow;
427
428 nxm_put_frag(b, cr);
429
430 if (!(wc & FWW_NW_DSCP)) {
b5ae8913
SH
431 nxm_put_8(b, oxm ? OXM_OF_IP_DSCP : NXM_OF_IP_TOS,
432 flow->nw_tos & IP_DSCP_MASK);
8e7082b0
BP
433 }
434
435 if (!(wc & FWW_NW_ECN)) {
b5ae8913
SH
436 nxm_put_8(b, oxm ? OXM_OF_IP_ECN : NXM_NX_IP_ECN,
437 flow->nw_tos & IP_ECN_MASK);
8e7082b0
BP
438 }
439
b5ae8913 440 if (!oxm && !(wc & FWW_NW_TTL)) {
8e7082b0
BP
441 nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
442 }
443
444 if (!(wc & FWW_NW_PROTO)) {
b5ae8913 445 nxm_put_8(b, oxm ? OXM_OF_IP_PROTO : NXM_OF_IP_PROTO, flow->nw_proto);
8e7082b0
BP
446
447 if (flow->nw_proto == IPPROTO_TCP) {
b5ae8913
SH
448 nxm_put_16m(b, oxm ? OXM_OF_TCP_SRC : NXM_OF_TCP_SRC,
449 flow->tp_src, cr->wc.tp_src_mask);
450 nxm_put_16m(b, oxm ? OXM_OF_TCP_DST : NXM_OF_TCP_DST,
451 flow->tp_dst, cr->wc.tp_dst_mask);
8e7082b0 452 } else if (flow->nw_proto == IPPROTO_UDP) {
b5ae8913
SH
453 nxm_put_16m(b, oxm ? OXM_OF_UDP_SRC : NXM_OF_UDP_SRC,
454 flow->tp_src, cr->wc.tp_src_mask);
455 nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST,
456 flow->tp_dst, cr->wc.tp_dst_mask);
8e7082b0 457 } else if (flow->nw_proto == icmp_proto) {
73f33563 458 if (cr->wc.tp_src_mask) {
8e7082b0
BP
459 nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
460 }
73f33563 461 if (cr->wc.tp_dst_mask) {
8e7082b0
BP
462 nxm_put_8(b, icmp_code, ntohs(flow->tp_dst));
463 }
464 }
465 }
466}
467
4d0ed519
BP
468/* Appends to 'b' the nx_match format that expresses 'cr' (except for
469 * 'cr->priority', because priority is not part of nx_match), plus enough
e729e793
JP
470 * zero bytes to pad the nx_match out to a multiple of 8. For Flow Mod
471 * and Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be
472 * supplied. Otherwise, 'cookie_mask' should be zero.
4d0ed519
BP
473 *
474 * This function can cause 'b''s data to be reallocated.
475 *
476 * Returns the number of bytes appended to 'b', excluding padding.
477 *
478 * If 'cr' is a catch-all rule that matches every packet, then this function
479 * appends nothing to 'b' and returns 0. */
09246b99 480int
b5ae8913 481nx_put_match(struct ofpbuf *b, bool oxm, const struct cls_rule *cr,
e729e793 482 ovs_be64 cookie, ovs_be64 cookie_mask)
09246b99 483{
d8ae4d67 484 const flow_wildcards_t wc = cr->wc.wildcards;
09246b99
BP
485 const struct flow *flow = &cr->flow;
486 const size_t start_len = b->size;
09246b99 487 int match_len;
b6c9e612 488 int i;
09246b99 489
73c0ce34 490 BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
a877206f 491
09246b99 492 /* Metadata. */
d8ae4d67 493 if (!(wc & FWW_IN_PORT)) {
09246b99 494 uint16_t in_port = flow->in_port;
b5ae8913
SH
495 if (oxm) {
496 nxm_put_32(b, OXM_OF_IN_PORT, ofputil_port_to_ofp11(in_port));
497 } else {
498 nxm_put_16(b, NXM_OF_IN_PORT, htons(in_port));
499 }
09246b99
BP
500 }
501
502 /* Ethernet. */
b5ae8913
SH
503 nxm_put_eth_masked(b, oxm ? OXM_OF_ETH_SRC : NXM_OF_ETH_SRC,
504 flow->dl_src, cr->wc.dl_src_mask);
505 nxm_put_eth_masked(b, oxm ? OXM_OF_ETH_DST : NXM_OF_ETH_DST,
506 flow->dl_dst, cr->wc.dl_dst_mask);
d8ae4d67 507 if (!(wc & FWW_DL_TYPE)) {
b5ae8913 508 nxm_put_16(b, oxm ? OXM_OF_ETH_TYPE : NXM_OF_ETH_TYPE,
36956a7d 509 ofputil_dl_type_to_openflow(flow->dl_type));
09246b99
BP
510 }
511
b5ae8913
SH
512 /* 802.1Q.
513 *
514 * XXX missing OXM support */
66642cb4 515 nxm_put_16m(b, NXM_OF_VLAN_TCI, flow->vlan_tci, cr->wc.vlan_tci_mask);
09246b99 516
66642cb4 517 /* L3. */
d8ae4d67 518 if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IP)) {
09246b99 519 /* IP. */
b5ae8913
SH
520 nxm_put_32m(b, oxm ? OXM_OF_IPV4_SRC : NXM_OF_IP_SRC,
521 flow->nw_src, cr->wc.nw_src_mask);
522 nxm_put_32m(b, oxm ? OXM_OF_IPV4_DST : NXM_OF_IP_DST,
523 flow->nw_dst, cr->wc.nw_dst_mask);
524 nxm_put_ip(b, cr, IPPROTO_ICMP,
525 oxm ? OXM_OF_ICMPV4_TYPE : NXM_OF_ICMP_TYPE,
526 oxm ? OXM_OF_ICMPV4_CODE : NXM_OF_ICMP_CODE, oxm);
d31f1109
JP
527 } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IPV6)) {
528 /* IPv6. */
b5ae8913
SH
529 nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_SRC : NXM_NX_IPV6_SRC,
530 &flow->ipv6_src, &cr->wc.ipv6_src_mask);
531 nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_DST : NXM_NX_IPV6_DST,
532 &flow->ipv6_dst, &cr->wc.ipv6_dst_mask);
533 nxm_put_ip(b, cr, IPPROTO_ICMPV6,
534 oxm ? OXM_OF_ICMPV6_TYPE : NXM_NX_ICMPV6_TYPE,
535 oxm ? OXM_OF_ICMPV6_CODE : NXM_NX_ICMPV6_CODE, oxm);
9e44d715 536
fa8223b7 537 if (!(wc & FWW_IPV6_LABEL)) {
b5ae8913
SH
538 nxm_put_32(b, oxm ? OXM_OF_IPV6_FLABEL : NXM_NX_IPV6_LABEL,
539 flow->ipv6_label);
fa8223b7 540 }
d31f1109 541
8e7082b0
BP
542 if (flow->nw_proto == IPPROTO_ICMPV6
543 && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
544 flow->tp_src == htons(ND_NEIGHBOR_ADVERT))) {
b5ae8913
SH
545 nxm_put_ipv6(b, oxm ? OXM_OF_IPV6_ND_TARGET : NXM_NX_ND_TARGET,
546 &flow->nd_target, &cr->wc.nd_target_mask);
8e7082b0
BP
547 if (!(wc & FWW_ARP_SHA)
548 && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
b5ae8913
SH
549 nxm_put_eth(b, oxm ? OXM_OF_IPV6_ND_SLL : NXM_NX_ND_SLL,
550 flow->arp_sha);
8e7082b0
BP
551 }
552 if (!(wc & FWW_ARP_THA)
553 && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
b5ae8913
SH
554 nxm_put_eth(b, oxm ? OXM_OF_IPV6_ND_TLL : NXM_NX_ND_TLL,
555 flow->arp_tha);
d31f1109
JP
556 }
557 }
d8ae4d67 558 } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_ARP)) {
09246b99 559 /* ARP. */
d8ae4d67 560 if (!(wc & FWW_NW_PROTO)) {
b5ae8913
SH
561 nxm_put_16(b, oxm ? OXM_OF_ARP_OP : NXM_OF_ARP_OP,
562 htons(flow->nw_proto));
09246b99 563 }
b5ae8913
SH
564 nxm_put_32m(b, oxm ? OXM_OF_ARP_SPA : NXM_OF_ARP_SPA,
565 flow->nw_src, cr->wc.nw_src_mask);
566 nxm_put_32m(b, oxm ? OXM_OF_ARP_TPA : NXM_OF_ARP_TPA,
567 flow->nw_dst, cr->wc.nw_dst_mask);
bad68a99 568 if (!(wc & FWW_ARP_SHA)) {
b5ae8913
SH
569 nxm_put_eth(b, oxm ? OXM_OF_ARP_SHA : NXM_NX_ARP_SHA,
570 flow->arp_sha);
bad68a99
JP
571 }
572 if (!(wc & FWW_ARP_THA)) {
b5ae8913
SH
573 nxm_put_eth(b, oxm ? OXM_OF_ARP_THA : NXM_NX_ARP_THA,
574 flow->arp_tha);
bad68a99 575 }
09246b99
BP
576 }
577
578 /* Tunnel ID. */
8368c090 579 nxm_put_64m(b, NXM_NX_TUN_ID, flow->tun_id, cr->wc.tun_id_mask);
09246b99 580
b6c9e612
BP
581 /* Registers. */
582 for (i = 0; i < FLOW_N_REGS; i++) {
583 nxm_put_32m(b, NXM_NX_REG(i),
584 htonl(flow->regs[i]), htonl(cr->wc.reg_masks[i]));
585 }
586
e729e793
JP
587 /* Cookie. */
588 nxm_put_64m(b, NXM_NX_COOKIE, cookie, cookie_mask);
589
09246b99
BP
590 match_len = b->size - start_len;
591 ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
592 return match_len;
593}
594\f
595/* nx_match_to_string() and helpers. */
596
f393f81e
BP
597static void format_nxm_field_name(struct ds *, uint32_t header);
598
09246b99
BP
599char *
600nx_match_to_string(const uint8_t *p, unsigned int match_len)
601{
602 uint32_t header;
603 struct ds s;
604
605 if (!match_len) {
606 return xstrdup("<any>");
607 }
608
609 ds_init(&s);
610 while ((header = nx_entry_ok(p, match_len)) != 0) {
611 unsigned int length = NXM_LENGTH(header);
612 unsigned int value_len = nxm_field_bytes(header);
613 const uint8_t *value = p + 4;
614 const uint8_t *mask = value + value_len;
09246b99
BP
615 unsigned int i;
616
617 if (s.length) {
618 ds_put_cstr(&s, ", ");
619 }
620
f393f81e 621 format_nxm_field_name(&s, header);
09246b99
BP
622 ds_put_char(&s, '(');
623
624 for (i = 0; i < value_len; i++) {
625 ds_put_format(&s, "%02x", value[i]);
626 }
627 if (NXM_HASMASK(header)) {
628 ds_put_char(&s, '/');
629 for (i = 0; i < value_len; i++) {
630 ds_put_format(&s, "%02x", mask[i]);
631 }
632 }
633 ds_put_char(&s, ')');
634
635 p += 4 + length;
636 match_len -= 4 + length;
637 }
638
639 if (match_len) {
640 if (s.length) {
641 ds_put_cstr(&s, ", ");
642 }
643
644 ds_put_format(&s, "<%u invalid bytes>", match_len);
645 }
646
647 return ds_steal_cstr(&s);
648}
649
f393f81e
BP
650static void
651format_nxm_field_name(struct ds *s, uint32_t header)
652{
28da1f8f
BP
653 const struct mf_field *mf = mf_from_nxm_header(header);
654 if (mf) {
b5ae8913 655 ds_put_cstr(s, IS_OXM_HEADER(header) ? mf->oxm_name : mf->nxm_name);
28da1f8f
BP
656 if (NXM_HASMASK(header)) {
657 ds_put_cstr(s, "_W");
658 }
e729e793
JP
659 } else if (header == NXM_NX_COOKIE) {
660 ds_put_cstr(s, "NXM_NX_COOKIE");
661 } else if (header == NXM_NX_COOKIE_W) {
662 ds_put_cstr(s, "NXM_NX_COOKIE_W");
f393f81e
BP
663 } else {
664 ds_put_format(s, "%d:%d", NXM_VENDOR(header), NXM_FIELD(header));
665 }
666}
667
558d80cb
BP
668static uint32_t
669parse_nxm_field_name(const char *name, int name_len)
09246b99 670{
28da1f8f
BP
671 bool wild;
672 int i;
09246b99 673
558d80cb 674 /* Check whether it's a field name. */
28da1f8f
BP
675 wild = name_len > 2 && !memcmp(&name[name_len - 2], "_W", 2);
676 if (wild) {
677 name_len -= 2;
678 }
e729e793 679
28da1f8f
BP
680 for (i = 0; i < MFF_N_IDS; i++) {
681 const struct mf_field *mf = mf_from_id(i);
b5ae8913
SH
682 uint32_t header;
683
684 if (mf->nxm_name &&
685 !strncmp(mf->nxm_name, name, name_len) &&
686 mf->nxm_name[name_len] == '\0') {
687 header = mf->nxm_header;
688 } else if (mf->oxm_name &&
689 !strncmp(mf->oxm_name, name, name_len) &&
690 mf->oxm_name[name_len] == '\0') {
691 header = mf->oxm_header;
692 } else {
693 continue;
694 }
28da1f8f 695
b5ae8913
SH
696 if (!wild) {
697 return header;
698 } else if (mf->maskable != MFM_NONE) {
699 return NXM_MAKE_WILD_HEADER(header);
09246b99
BP
700 }
701 }
702
b5ae8913
SH
703 if (!strncmp("NXM_NX_COOKIE", name, name_len) &&
704 (name_len == strlen("NXM_NX_COOKIE"))) {
e729e793
JP
705 if (!wild) {
706 return NXM_NX_COOKIE;
707 } else {
708 return NXM_NX_COOKIE_W;
709 }
710 }
711
558d80cb
BP
712 /* Check whether it's a 32-bit field header value as hex.
713 * (This isn't ordinarily useful except for testing error behavior.) */
714 if (name_len == 8) {
715 uint32_t header = hexits_value(name, name_len, NULL);
716 if (header != UINT_MAX) {
717 return header;
718 }
719 }
720
721 return 0;
09246b99 722}
09246b99
BP
723\f
724/* nx_match_from_string(). */
725
726int
727nx_match_from_string(const char *s, struct ofpbuf *b)
728{
729 const char *full_s = s;
730 const size_t start_len = b->size;
731 int match_len;
732
733 if (!strcmp(s, "<any>")) {
734 /* Ensure that 'b->data' isn't actually null. */
735 ofpbuf_prealloc_tailroom(b, 1);
736 return 0;
737 }
738
739 for (s += strspn(s, ", "); *s; s += strspn(s, ", ")) {
558d80cb
BP
740 const char *name;
741 uint32_t header;
09246b99 742 int name_len;
78090f63 743 size_t n;
09246b99 744
558d80cb 745 name = s;
09246b99
BP
746 name_len = strcspn(s, "(");
747 if (s[name_len] != '(') {
748 ovs_fatal(0, "%s: missing ( at end of nx_match", full_s);
749 }
750
558d80cb
BP
751 header = parse_nxm_field_name(name, name_len);
752 if (!header) {
09246b99
BP
753 ovs_fatal(0, "%s: unknown field `%.*s'", full_s, name_len, s);
754 }
755
756 s += name_len + 1;
757
558d80cb 758 nxm_put_header(b, header);
78090f63
BP
759 s = ofpbuf_put_hex(b, s, &n);
760 if (n != nxm_field_bytes(header)) {
761 ovs_fatal(0, "%.2s: hex digits expected", s);
762 }
558d80cb 763 if (NXM_HASMASK(header)) {
09246b99
BP
764 s += strspn(s, " ");
765 if (*s != '/') {
558d80cb
BP
766 ovs_fatal(0, "%s: missing / in masked field %.*s",
767 full_s, name_len, name);
09246b99 768 }
78090f63
BP
769 s = ofpbuf_put_hex(b, s + 1, &n);
770 if (n != nxm_field_bytes(header)) {
771 ovs_fatal(0, "%.2s: hex digits expected", s);
772 }
09246b99
BP
773 }
774
775 s += strspn(s, " ");
776 if (*s != ')') {
558d80cb
BP
777 ovs_fatal(0, "%s: missing ) following field %.*s",
778 full_s, name_len, name);
09246b99
BP
779 }
780 s++;
781 }
782
783 match_len = b->size - start_len;
784 ofpbuf_put_zeros(b, ROUND_UP(match_len, 8) - match_len);
785 return match_len;
786}
b6c9e612 787\f
f393f81e
BP
788void
789nxm_parse_reg_move(struct nx_action_reg_move *move, const char *s)
790{
791 const char *full_s = s;
816fd533 792 struct mf_subfield src, dst;
f393f81e 793
816fd533 794 s = mf_parse_subfield(&src, s);
f393f81e
BP
795 if (strncmp(s, "->", 2)) {
796 ovs_fatal(0, "%s: missing `->' following source", full_s);
797 }
798 s += 2;
816fd533 799 s = mf_parse_subfield(&dst, s);
f393f81e
BP
800 if (*s != '\0') {
801 ovs_fatal(0, "%s: trailing garbage following destination", full_s);
802 }
803
816fd533 804 if (src.n_bits != dst.n_bits) {
f393f81e 805 ovs_fatal(0, "%s: source field is %d bits wide but destination is "
816fd533 806 "%d bits wide", full_s, src.n_bits, dst.n_bits);
f393f81e
BP
807 }
808
93996add 809 ofputil_init_NXAST_REG_MOVE(move);
816fd533
BP
810 move->n_bits = htons(src.n_bits);
811 move->src_ofs = htons(src.ofs);
812 move->dst_ofs = htons(dst.ofs);
813 move->src = htonl(src.field->nxm_header);
814 move->dst = htonl(dst.field->nxm_header);
f393f81e
BP
815}
816
817void
818nxm_parse_reg_load(struct nx_action_reg_load *load, const char *s)
819{
820 const char *full_s = s;
816fd533 821 struct mf_subfield dst;
f393f81e
BP
822 uint64_t value;
823
824 value = strtoull(s, (char **) &s, 0);
825 if (strncmp(s, "->", 2)) {
826 ovs_fatal(0, "%s: missing `->' following value", full_s);
827 }
828 s += 2;
816fd533 829 s = mf_parse_subfield(&dst, s);
f393f81e
BP
830 if (*s != '\0') {
831 ovs_fatal(0, "%s: trailing garbage following destination", full_s);
832 }
833
816fd533
BP
834 if (dst.n_bits < 64 && (value >> dst.n_bits) != 0) {
835 ovs_fatal(0, "%s: value %"PRIu64" does not fit into %u bits",
836 full_s, value, dst.n_bits);
f393f81e
BP
837 }
838
93996add 839 ofputil_init_NXAST_REG_LOAD(load);
816fd533
BP
840 load->ofs_nbits = nxm_encode_ofs_nbits(dst.ofs, dst.n_bits);
841 load->dst = htonl(dst.field->nxm_header);
f393f81e
BP
842 load->value = htonll(value);
843}
844\f
845/* nxm_format_reg_move(), nxm_format_reg_load(). */
846
f393f81e
BP
847void
848nxm_format_reg_move(const struct nx_action_reg_move *move, struct ds *s)
849{
816fd533
BP
850 struct mf_subfield src, dst;
851
852 nxm_decode_discrete(&src, move->src, move->src_ofs, move->n_bits);
853 nxm_decode_discrete(&dst, move->dst, move->dst_ofs, move->n_bits);
f393f81e
BP
854
855 ds_put_format(s, "move:");
816fd533 856 mf_format_subfield(&src, s);
f393f81e 857 ds_put_cstr(s, "->");
816fd533 858 mf_format_subfield(&dst, s);
f393f81e
BP
859}
860
861void
862nxm_format_reg_load(const struct nx_action_reg_load *load, struct ds *s)
863{
816fd533 864 struct mf_subfield dst;
f393f81e 865
816fd533
BP
866 ds_put_format(s, "load:%#"PRIx64"->", ntohll(load->value));
867
868 nxm_decode(&dst, load->dst, load->ofs_nbits);
869 mf_format_subfield(&dst, s);
f393f81e
BP
870}
871\f
b6c9e612
BP
872/* nxm_check_reg_move(), nxm_check_reg_load(). */
873
816fd533 874enum ofperr
b6c9e612
BP
875nxm_check_reg_move(const struct nx_action_reg_move *action,
876 const struct flow *flow)
877{
816fd533
BP
878 struct mf_subfield src;
879 struct mf_subfield dst;
ce523f65 880 int error;
b6c9e612 881
816fd533
BP
882 nxm_decode_discrete(&src, action->src, action->src_ofs, action->n_bits);
883 error = mf_check_src(&src, flow);
ce523f65
EJ
884 if (error) {
885 return error;
b6c9e612
BP
886 }
887
816fd533
BP
888 nxm_decode_discrete(&dst, action->dst, action->dst_ofs, action->n_bits);
889 return mf_check_dst(&dst, flow);
43edca57
EJ
890}
891
90bf1e07 892enum ofperr
43edca57
EJ
893nxm_check_reg_load(const struct nx_action_reg_load *action,
894 const struct flow *flow)
895{
816fd533 896 struct mf_subfield dst;
90bf1e07 897 enum ofperr error;
43edca57 898
816fd533
BP
899 nxm_decode(&dst, action->dst, action->ofs_nbits);
900 error = mf_check_dst(&dst, flow);
43edca57
EJ
901 if (error) {
902 return error;
b6c9e612
BP
903 }
904
905 /* Reject 'action' if a bit numbered 'n_bits' or higher is set to 1 in
906 * action->value. */
816fd533 907 if (dst.n_bits < 64 && ntohll(action->value) >> dst.n_bits) {
90bf1e07 908 return OFPERR_OFPBAC_BAD_ARGUMENT;
b6c9e612
BP
909 }
910
b6c9e612
BP
911 return 0;
912}
913\f
914/* nxm_execute_reg_move(), nxm_execute_reg_load(). */
915
b6c9e612
BP
916void
917nxm_execute_reg_move(const struct nx_action_reg_move *action,
918 struct flow *flow)
919{
816fd533 920 struct mf_subfield src, dst;
28da1f8f
BP
921 union mf_value src_value;
922 union mf_value dst_value;
923
816fd533
BP
924 nxm_decode_discrete(&src, action->src, action->src_ofs, action->n_bits);
925 nxm_decode_discrete(&dst, action->dst, action->dst_ofs, action->n_bits);
926
927 mf_get_value(dst.field, flow, &dst_value);
928 mf_get_value(src.field, flow, &src_value);
929 bitwise_copy(&src_value, src.field->n_bytes, src.ofs,
930 &dst_value, dst.field->n_bytes, dst.ofs,
931 src.n_bits);
932 mf_set_flow_value(dst.field, &dst_value, flow);
b6c9e612
BP
933}
934
935void
936nxm_execute_reg_load(const struct nx_action_reg_load *action,
937 struct flow *flow)
938{
816fd533
BP
939 struct mf_subfield dst;
940
941 nxm_decode(&dst, action->dst, action->ofs_nbits);
942 mf_set_subfield_value(&dst, ntohll(action->value), flow);
43edca57 943}
b6c9e612 944
816fd533
BP
945/* Initializes 'sf->field' with the field corresponding to the given NXM
946 * 'header' and 'sf->ofs' and 'sf->n_bits' decoded from 'ofs_nbits' with
947 * nxm_decode_ofs() and nxm_decode_n_bits(), respectively.
948 *
949 * Afterward, 'sf' might be invalid in a few different ways:
950 *
951 * - 'sf->field' will be NULL if 'header' is unknown.
952 *
953 * - 'sf->ofs' and 'sf->n_bits' might exceed the width of sf->field.
954 *
955 * The caller should call mf_check_src() or mf_check_dst() to check for these
956 * problems. */
43edca57 957void
816fd533 958nxm_decode(struct mf_subfield *sf, ovs_be32 header, ovs_be16 ofs_nbits)
43edca57 959{
816fd533
BP
960 sf->field = mf_from_nxm_header(ntohl(header));
961 sf->ofs = nxm_decode_ofs(ofs_nbits);
962 sf->n_bits = nxm_decode_n_bits(ofs_nbits);
963}
28da1f8f 964
816fd533
BP
965/* Initializes 'sf->field' with the field corresponding to the given NXM
966 * 'header' and 'sf->ofs' and 'sf->n_bits' from 'ofs' and 'n_bits',
967 * respectively.
968 *
969 * Afterward, 'sf' might be invalid in a few different ways:
970 *
971 * - 'sf->field' will be NULL if 'header' is unknown.
972 *
973 * - 'sf->ofs' and 'sf->n_bits' might exceed the width of sf->field.
974 *
975 * The caller should call mf_check_src() or mf_check_dst() to check for these
976 * problems. */
977void
978nxm_decode_discrete(struct mf_subfield *sf, ovs_be32 header,
979 ovs_be16 ofs, ovs_be16 n_bits)
980{
981 sf->field = mf_from_nxm_header(ntohl(header));
982 sf->ofs = ntohs(ofs);
983 sf->n_bits = ntohs(n_bits);
b6c9e612 984}