]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-protocol.c
cirrus: Use FreeBSD 12.2.
[mirror_ovs.git] / lib / ofp-protocol.c
CommitLineData
0d71302e
BP
1/*
2 * Copyright (c) 2008-2017 Nicira, Inc.
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#include "openvswitch/ofp-protocol.h"
19#include <ctype.h>
20#include "openvswitch/dynamic-string.h"
21#include "openvswitch/ofp-flow.h"
225c33ba
BP
22#include "openvswitch/ofp-msgs.h"
23#include "openvswitch/ofpbuf.h"
0d71302e
BP
24#include "openvswitch/vlog.h"
25#include "util.h"
26
27VLOG_DEFINE_THIS_MODULE(ofp_protocol);
28
225c33ba
BP
29static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
30
0d71302e
BP
31/* Protocols. */
32
33struct proto_abbrev {
34 enum ofputil_protocol protocol;
35 const char *name;
36};
37
38/* Most users really don't care about some of the differences between
39 * protocols. These abbreviations help with that. */
40static const struct proto_abbrev proto_abbrevs[] = {
41 { OFPUTIL_P_ANY, "any" },
42 { OFPUTIL_P_OF10_STD_ANY, "OpenFlow10" },
43 { OFPUTIL_P_OF10_NXM_ANY, "NXM" },
44 { OFPUTIL_P_ANY_OXM, "OXM" },
45};
46#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
47
48enum ofputil_protocol ofputil_flow_dump_protocols[] = {
0d71302e
BP
49 OFPUTIL_P_OF15_OXM,
50 OFPUTIL_P_OF14_OXM,
51 OFPUTIL_P_OF13_OXM,
52 OFPUTIL_P_OF12_OXM,
53 OFPUTIL_P_OF11_STD,
54 OFPUTIL_P_OF10_NXM,
55 OFPUTIL_P_OF10_STD,
56};
57size_t ofputil_n_flow_dump_protocols = ARRAY_SIZE(ofputil_flow_dump_protocols);
58
59/* Returns the set of ofputil_protocols that are supported with the given
60 * OpenFlow 'version'. 'version' should normally be an 8-bit OpenFlow version
61 * identifier (e.g. 0x01 for OpenFlow 1.0, 0x02 for OpenFlow 1.1). Returns 0
62 * if 'version' is not supported or outside the valid range. */
63enum ofputil_protocol
64ofputil_protocols_from_ofp_version(enum ofp_version version)
65{
66 switch (version) {
67 case OFP10_VERSION:
68 return OFPUTIL_P_OF10_STD_ANY | OFPUTIL_P_OF10_NXM_ANY;
69 case OFP11_VERSION:
70 return OFPUTIL_P_OF11_STD;
71 case OFP12_VERSION:
72 return OFPUTIL_P_OF12_OXM;
73 case OFP13_VERSION:
74 return OFPUTIL_P_OF13_OXM;
75 case OFP14_VERSION:
76 return OFPUTIL_P_OF14_OXM;
77 case OFP15_VERSION:
78 return OFPUTIL_P_OF15_OXM;
0d71302e
BP
79 default:
80 return 0;
81 }
82}
83
84/* Returns the ofputil_protocol that is initially in effect on an OpenFlow
85 * connection that has negotiated the given 'version'. 'version' should
86 * normally be an 8-bit OpenFlow version identifier (e.g. 0x01 for OpenFlow
87 * 1.0, 0x02 for OpenFlow 1.1). Returns 0 if 'version' is not supported or
88 * outside the valid range. */
89enum ofputil_protocol
90ofputil_protocol_from_ofp_version(enum ofp_version version)
91{
92 return rightmost_1bit(ofputil_protocols_from_ofp_version(version));
93}
94
95/* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
96 * etc.) that corresponds to 'protocol'. */
97enum ofp_version
98ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
99{
100 switch (protocol) {
101 case OFPUTIL_P_OF10_STD:
102 case OFPUTIL_P_OF10_STD_TID:
103 case OFPUTIL_P_OF10_NXM:
104 case OFPUTIL_P_OF10_NXM_TID:
105 return OFP10_VERSION;
106 case OFPUTIL_P_OF11_STD:
107 return OFP11_VERSION;
108 case OFPUTIL_P_OF12_OXM:
109 return OFP12_VERSION;
110 case OFPUTIL_P_OF13_OXM:
111 return OFP13_VERSION;
112 case OFPUTIL_P_OF14_OXM:
113 return OFP14_VERSION;
114 case OFPUTIL_P_OF15_OXM:
115 return OFP15_VERSION;
0d71302e
BP
116 }
117
118 OVS_NOT_REACHED();
119}
120
121/* Returns a bitmap of OpenFlow versions that are supported by at
122 * least one of the 'protocols'. */
123uint32_t
124ofputil_protocols_to_version_bitmap(enum ofputil_protocol protocols)
125{
126 uint32_t bitmap = 0;
127
128 for (; protocols; protocols = zero_rightmost_1bit(protocols)) {
129 enum ofputil_protocol protocol = rightmost_1bit(protocols);
130
131 bitmap |= 1u << ofputil_protocol_to_ofp_version(protocol);
132 }
133
134 return bitmap;
135}
136
137/* Returns the set of protocols that are supported on top of the
138 * OpenFlow versions included in 'bitmap'. */
139enum ofputil_protocol
140ofputil_protocols_from_version_bitmap(uint32_t bitmap)
141{
142 enum ofputil_protocol protocols = 0;
143
144 for (; bitmap; bitmap = zero_rightmost_1bit(bitmap)) {
145 enum ofp_version version = rightmost_1bit_idx(bitmap);
146
147 protocols |= ofputil_protocols_from_ofp_version(version);
148 }
149
150 return protocols;
151}
152
153/* Returns true if 'protocol' is a single OFPUTIL_P_* value, false
154 * otherwise. */
155bool
156ofputil_protocol_is_valid(enum ofputil_protocol protocol)
157{
158 return protocol & OFPUTIL_P_ANY && is_pow2(protocol);
159}
160
161/* Returns the equivalent of 'protocol' with the Nicira flow_mod_table_id
162 * extension turned on or off if 'enable' is true or false, respectively.
163 *
164 * This extension is only useful for protocols whose "standard" version does
165 * not allow specific tables to be modified. In particular, this is true of
166 * OpenFlow 1.0. In later versions of OpenFlow, a flow_mod request always
167 * specifies a table ID and so there is no need for such an extension. When
168 * 'protocol' is such a protocol that doesn't need a flow_mod_table_id
169 * extension, this function just returns its 'protocol' argument unchanged
170 * regardless of the value of 'enable'. */
171enum ofputil_protocol
172ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
173{
174 switch (protocol) {
175 case OFPUTIL_P_OF10_STD:
176 case OFPUTIL_P_OF10_STD_TID:
177 return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD;
178
179 case OFPUTIL_P_OF10_NXM:
180 case OFPUTIL_P_OF10_NXM_TID:
181 return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM;
182
183 case OFPUTIL_P_OF11_STD:
184 return OFPUTIL_P_OF11_STD;
185
186 case OFPUTIL_P_OF12_OXM:
187 return OFPUTIL_P_OF12_OXM;
188
189 case OFPUTIL_P_OF13_OXM:
190 return OFPUTIL_P_OF13_OXM;
191
192 case OFPUTIL_P_OF14_OXM:
193 return OFPUTIL_P_OF14_OXM;
194
195 case OFPUTIL_P_OF15_OXM:
196 return OFPUTIL_P_OF15_OXM;
197
0d71302e
BP
198 default:
199 OVS_NOT_REACHED();
200 }
201}
202
203/* Returns the "base" version of 'protocol'. That is, if 'protocol' includes
204 * some extension to a standard protocol version, the return value is the
205 * standard version of that protocol without any extension. If 'protocol' is a
206 * standard protocol version, returns 'protocol' unchanged. */
207enum ofputil_protocol
208ofputil_protocol_to_base(enum ofputil_protocol protocol)
209{
210 return ofputil_protocol_set_tid(protocol, false);
211}
212
213/* Returns 'new_base' with any extensions taken from 'cur'. */
214enum ofputil_protocol
215ofputil_protocol_set_base(enum ofputil_protocol cur,
216 enum ofputil_protocol new_base)
217{
218 bool tid = (cur & OFPUTIL_P_TID) != 0;
219
220 switch (new_base) {
221 case OFPUTIL_P_OF10_STD:
222 case OFPUTIL_P_OF10_STD_TID:
223 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid);
224
225 case OFPUTIL_P_OF10_NXM:
226 case OFPUTIL_P_OF10_NXM_TID:
227 return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid);
228
229 case OFPUTIL_P_OF11_STD:
230 return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid);
231
232 case OFPUTIL_P_OF12_OXM:
233 return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
234
235 case OFPUTIL_P_OF13_OXM:
236 return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);
237
238 case OFPUTIL_P_OF14_OXM:
239 return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid);
240
241 case OFPUTIL_P_OF15_OXM:
242 return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid);
243
0d71302e
BP
244 default:
245 OVS_NOT_REACHED();
246 }
247}
248
249/* Returns a string form of 'protocol', if a simple form exists (that is, if
250 * 'protocol' is either a single protocol or it is a combination of protocols
251 * that have a single abbreviation). Otherwise, returns NULL. */
252const char *
253ofputil_protocol_to_string(enum ofputil_protocol protocol)
254{
255 const struct proto_abbrev *p;
256
257 /* Use a "switch" statement for single-bit names so that we get a compiler
258 * warning if we forget any. */
259 switch (protocol) {
260 case OFPUTIL_P_OF10_NXM:
261 return "NXM-table_id";
262
263 case OFPUTIL_P_OF10_NXM_TID:
264 return "NXM+table_id";
265
266 case OFPUTIL_P_OF10_STD:
267 return "OpenFlow10-table_id";
268
269 case OFPUTIL_P_OF10_STD_TID:
270 return "OpenFlow10+table_id";
271
272 case OFPUTIL_P_OF11_STD:
273 return "OpenFlow11";
274
275 case OFPUTIL_P_OF12_OXM:
276 return "OXM-OpenFlow12";
277
278 case OFPUTIL_P_OF13_OXM:
279 return "OXM-OpenFlow13";
280
281 case OFPUTIL_P_OF14_OXM:
282 return "OXM-OpenFlow14";
283
284 case OFPUTIL_P_OF15_OXM:
285 return "OXM-OpenFlow15";
0d71302e
BP
286 }
287
288 /* Check abbreviations. */
289 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
290 if (protocol == p->protocol) {
291 return p->name;
292 }
293 }
294
295 return NULL;
296}
297
298/* Returns a string that represents 'protocols'. The return value might be a
299 * comma-separated list if 'protocols' doesn't have a simple name. The return
300 * value is "none" if 'protocols' is 0.
301 *
302 * The caller must free the returned string (with free()). */
303char *
304ofputil_protocols_to_string(enum ofputil_protocol protocols)
305{
306 struct ds s;
307
308 ovs_assert(!(protocols & ~OFPUTIL_P_ANY));
309 if (protocols == 0) {
310 return xstrdup("none");
311 }
312
313 ds_init(&s);
314 while (protocols) {
315 const struct proto_abbrev *p;
316 int i;
317
318 if (s.length) {
319 ds_put_char(&s, ',');
320 }
321
322 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
323 if ((protocols & p->protocol) == p->protocol) {
324 ds_put_cstr(&s, p->name);
325 protocols &= ~p->protocol;
326 goto match;
327 }
328 }
329
330 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
331 enum ofputil_protocol bit = 1u << i;
332
333 if (protocols & bit) {
334 ds_put_cstr(&s, ofputil_protocol_to_string(bit));
335 protocols &= ~bit;
336 goto match;
337 }
338 }
339 OVS_NOT_REACHED();
340
341 match: ;
342 }
343 return ds_steal_cstr(&s);
344}
345
346static enum ofputil_protocol
347ofputil_protocol_from_string__(const char *s, size_t n)
348{
349 const struct proto_abbrev *p;
350 int i;
351
352 for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) {
353 enum ofputil_protocol bit = 1u << i;
354 const char *name = ofputil_protocol_to_string(bit);
355
356 if (name && n == strlen(name) && !strncasecmp(s, name, n)) {
357 return bit;
358 }
359 }
360
361 for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) {
362 if (n == strlen(p->name) && !strncasecmp(s, p->name, n)) {
363 return p->protocol;
364 }
365 }
366
367 return 0;
368}
369
370/* Returns the nonempty set of protocols represented by 's', which can be a
371 * single protocol name or abbreviation or a comma-separated list of them.
372 *
373 * Aborts the program with an error message if 's' is invalid. */
374enum ofputil_protocol
375ofputil_protocols_from_string(const char *s)
376{
377 const char *orig_s = s;
378 enum ofputil_protocol protocols;
379
380 protocols = 0;
381 while (*s) {
382 enum ofputil_protocol p;
383 size_t n;
384
385 n = strcspn(s, ",");
386 if (n == 0) {
387 s++;
388 continue;
389 }
390
391 p = ofputil_protocol_from_string__(s, n);
392 if (!p) {
393 ovs_fatal(0, "%.*s: unknown flow protocol", (int) n, s);
394 }
395 protocols |= p;
396
397 s += n;
398 }
399
400 if (!protocols) {
401 ovs_fatal(0, "%s: no flow protocol specified", orig_s);
402 }
403 return protocols;
404}
405
406enum ofp_version
407ofputil_version_from_string(const char *s)
408{
409 if (!strcasecmp(s, "OpenFlow10")) {
410 return OFP10_VERSION;
411 }
412 if (!strcasecmp(s, "OpenFlow11")) {
413 return OFP11_VERSION;
414 }
415 if (!strcasecmp(s, "OpenFlow12")) {
416 return OFP12_VERSION;
417 }
418 if (!strcasecmp(s, "OpenFlow13")) {
419 return OFP13_VERSION;
420 }
421 if (!strcasecmp(s, "OpenFlow14")) {
422 return OFP14_VERSION;
423 }
424 if (!strcasecmp(s, "OpenFlow15")) {
425 return OFP15_VERSION;
426 }
0d71302e
BP
427 return 0;
428}
429
430static bool
431is_delimiter(unsigned char c)
432{
433 return isspace(c) || c == ',';
434}
435
436uint32_t
437ofputil_versions_from_string(const char *s)
438{
439 size_t i = 0;
440 uint32_t bitmap = 0;
441
442 while (s[i]) {
443 size_t j;
444 int version;
445 char *key;
446
447 if (is_delimiter(s[i])) {
448 i++;
449 continue;
450 }
451 j = 0;
452 while (s[i + j] && !is_delimiter(s[i + j])) {
453 j++;
454 }
455 key = xmemdup0(s + i, j);
456 version = ofputil_version_from_string(key);
457 if (!version) {
458 VLOG_FATAL("Unknown OpenFlow version: \"%s\"", key);
459 }
460 free(key);
461 bitmap |= 1u << version;
462 i += j;
463 }
464
465 return bitmap;
466}
467
468uint32_t
469ofputil_versions_from_strings(char ** const s, size_t count)
470{
471 uint32_t bitmap = 0;
472
473 while (count--) {
474 int version = ofputil_version_from_string(s[count]);
475 if (!version) {
476 VLOG_WARN("Unknown OpenFlow version: \"%s\"", s[count]);
477 } else {
478 bitmap |= 1u << version;
479 }
480 }
481
482 return bitmap;
483}
484
485const char *
486ofputil_version_to_string(enum ofp_version ofp_version)
487{
488 switch (ofp_version) {
489 case OFP10_VERSION:
490 return "OpenFlow10";
491 case OFP11_VERSION:
492 return "OpenFlow11";
493 case OFP12_VERSION:
494 return "OpenFlow12";
495 case OFP13_VERSION:
496 return "OpenFlow13";
497 case OFP14_VERSION:
498 return "OpenFlow14";
499 case OFP15_VERSION:
500 return "OpenFlow15";
0d71302e
BP
501 default:
502 OVS_NOT_REACHED();
503 }
504}
505
506void
507ofputil_format_version(struct ds *msg, enum ofp_version version)
508{
509 ds_put_format(msg, "0x%02x", version);
510}
511
512void
513ofputil_format_version_name(struct ds *msg, enum ofp_version version)
514{
515 ds_put_cstr(msg, ofputil_version_to_string(version));
516}
517
518static void
519ofputil_format_version_bitmap__(struct ds *msg, uint32_t bitmap,
520 void (*format_version)(struct ds *msg,
521 enum ofp_version))
522{
523 while (bitmap) {
524 format_version(msg, raw_ctz(bitmap));
525 bitmap = zero_rightmost_1bit(bitmap);
526 if (bitmap) {
527 ds_put_cstr(msg, ", ");
528 }
529 }
530}
531
532void
533ofputil_format_version_bitmap(struct ds *msg, uint32_t bitmap)
534{
535 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version);
536}
537
538void
539ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap)
540{
541 ofputil_format_version_bitmap__(msg, bitmap, ofputil_format_version_name);
542}
225c33ba 543\f
0d71302e
BP
544/* Returns an OpenFlow message that, sent on an OpenFlow connection whose
545 * protocol is 'current', at least partly transitions the protocol to 'want'.
546 * Stores in '*next' the protocol that will be in effect on the OpenFlow
547 * connection if the switch processes the returned message correctly. (If
548 * '*next != want' then the caller will have to iterate.)
549 *
550 * If 'current == want', or if it is not possible to transition from 'current'
551 * to 'want' (because, for example, 'current' and 'want' use different OpenFlow
552 * protocol versions), returns NULL and stores 'current' in '*next'. */
553struct ofpbuf *
554ofputil_encode_set_protocol(enum ofputil_protocol current,
555 enum ofputil_protocol want,
556 enum ofputil_protocol *next)
557{
558 enum ofp_version cur_version, want_version;
559 enum ofputil_protocol cur_base, want_base;
560 bool cur_tid, want_tid;
561
562 cur_version = ofputil_protocol_to_ofp_version(current);
563 want_version = ofputil_protocol_to_ofp_version(want);
564 if (cur_version != want_version) {
565 *next = current;
566 return NULL;
567 }
568
569 cur_base = ofputil_protocol_to_base(current);
570 want_base = ofputil_protocol_to_base(want);
571 if (cur_base != want_base) {
572 *next = ofputil_protocol_set_base(current, want_base);
0d71302e
BP
573 switch (want_base) {
574 case OFPUTIL_P_OF10_NXM:
0d71302e 575 case OFPUTIL_P_OF10_STD:
225c33ba 576 return ofputil_encode_nx_set_flow_format(want_base);
0d71302e
BP
577
578 case OFPUTIL_P_OF11_STD:
579 case OFPUTIL_P_OF12_OXM:
580 case OFPUTIL_P_OF13_OXM:
581 case OFPUTIL_P_OF14_OXM:
582 case OFPUTIL_P_OF15_OXM:
0d71302e
BP
583 /* There is only one variant of each OpenFlow 1.1+ protocol, and we
584 * verified above that we're not trying to change versions. */
585 OVS_NOT_REACHED();
586
587 case OFPUTIL_P_OF10_STD_TID:
588 case OFPUTIL_P_OF10_NXM_TID:
589 OVS_NOT_REACHED();
590 }
591 }
592
593 cur_tid = (current & OFPUTIL_P_TID) != 0;
594 want_tid = (want & OFPUTIL_P_TID) != 0;
595 if (cur_tid != want_tid) {
596 *next = ofputil_protocol_set_tid(current, want_tid);
225c33ba 597 return ofputil_encode_nx_flow_mod_table_id(want_tid);
0d71302e
BP
598 }
599
600 ovs_assert(current == want);
601
602 *next = current;
603 return NULL;
604}
225c33ba
BP
605\f
606enum nx_flow_format {
607 NXFF_OPENFLOW10 = 0, /* Standard OpenFlow 1.0 compatible. */
608 NXFF_NXM = 2 /* Nicira extended match. */
609};
610
611/* Returns an NXT_SET_FLOW_FORMAT message that can be used to set the flow
612 * format to 'protocol'. */
613struct ofpbuf *
614ofputil_encode_nx_set_flow_format(enum ofputil_protocol protocol)
615{
616 struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT,
617 OFP10_VERSION, 0);
618 ovs_be32 *nxff = ofpbuf_put_uninit(msg, sizeof *nxff);
619 if (protocol == OFPUTIL_P_OF10_STD) {
620 *nxff = htonl(NXFF_OPENFLOW10);
621 } else if (protocol == OFPUTIL_P_OF10_NXM) {
622 *nxff = htonl(NXFF_NXM);
623 } else {
624 OVS_NOT_REACHED();
625 }
626
627 return msg;
628}
629
630/* Returns the protocol specified in the NXT_SET_FLOW_FORMAT message at 'oh'
631 * (either OFPUTIL_P_OF10_STD or OFPUTIL_P_OF10_NXM) or 0 if the message is
632 * invalid. */
633enum ofputil_protocol
634ofputil_decode_nx_set_flow_format(const struct ofp_header *oh)
635{
636 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
637 ovs_assert(ofpraw_pull_assert(&b) == OFPRAW_NXT_SET_FLOW_FORMAT);
638
639 ovs_be32 *flow_formatp = ofpbuf_pull(&b, sizeof *flow_formatp);
640 uint32_t flow_format = ntohl(*flow_formatp);
641 switch (flow_format) {
642 case NXFF_OPENFLOW10:
643 return OFPUTIL_P_OF10_STD;
644
645 case NXFF_NXM:
646 return OFPUTIL_P_OF10_NXM;
647
648 default:
649 VLOG_WARN_RL(&rl, "NXT_SET_FLOW_FORMAT message specified invalid "
650 "flow format %"PRIu32, flow_format);
651 return 0;
652 }
653}
654\f
655/* These functions work with the Open vSwitch extension feature called
656 * "flow_mod_table_id", which allows a controller to specify the OpenFlow table
657 * to which a flow should be added, instead of having the switch decide which
658 * table is most appropriate as required by OpenFlow 1.0. Because NXM was
659 * designed as an extension to OpenFlow 1.0, the extension applies equally to
660 * ofp10_flow_mod and nx_flow_mod. By default, the extension is disabled.
661 *
662 * When this feature is enabled, Open vSwitch treats struct ofp10_flow_mod's
663 * and struct nx_flow_mod's 16-bit 'command' member as two separate fields.
664 * The upper 8 bits are used as the table ID, the lower 8 bits specify the
665 * command as usual. A table ID of 0xff is treated like a wildcarded table ID.
666 *
667 * The specific treatment of the table ID depends on the type of flow mod:
668 *
669 * - OFPFC_ADD: Given a specific table ID, the flow is always placed in that
670 * table. If an identical flow already exists in that table only, then it
671 * is replaced. If the flow cannot be placed in the specified table,
672 * either because the table is full or because the table cannot support
673 * flows of the given type, the switch replies with an OFPFMFC_TABLE_FULL
674 * error. (A controller can distinguish these cases by comparing the
675 * current and maximum number of entries reported in ofp_table_stats.)
676 *
677 * If the table ID is wildcarded, the switch picks an appropriate table
678 * itself. If an identical flow already exist in the selected flow table,
679 * then it is replaced. The choice of table might depend on the flows
680 * that are already in the switch; for example, if one table fills up then
681 * the switch might fall back to another one.
682 *
683 * - OFPFC_MODIFY, OFPFC_DELETE: Given a specific table ID, only flows
684 * within that table are matched and modified or deleted. If the table ID
685 * is wildcarded, flows within any table may be matched and modified or
686 * deleted.
687 *
688 * - OFPFC_MODIFY_STRICT, OFPFC_DELETE_STRICT: Given a specific table ID,
689 * only a flow within that table may be matched and modified or deleted.
690 * If the table ID is wildcarded and exactly one flow within any table
691 * matches, then it is modified or deleted; if flows in more than one
692 * table match, then none is modified or deleted.
693 */
694
695/* Returns an OpenFlow message that can be used to turn the flow_mod_table_id
696 * extension on or off (according to 'enable'). */
697struct ofpbuf *
698ofputil_encode_nx_flow_mod_table_id(bool enable)
699{
700 struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MOD_TABLE_ID,
701 OFP10_VERSION, 0);
702 uint8_t *p = ofpbuf_put_zeros(msg, 8);
703 *p = enable;
704 return msg;
705}
706
707/* Decodes the NXT_FLOW_MOD_TABLE_ID message at 'oh'. Returns the message's
708 * argument, that is, whether the flow_mod_table_id feature should be
709 * enabled. */
710bool
711ofputil_decode_nx_flow_mod_table_id(const struct ofp_header *oh)
712{
713 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
714 ovs_assert(ofpraw_pull_assert(&b) == OFPRAW_NXT_FLOW_MOD_TABLE_ID);
715 uint8_t *enable = ofpbuf_pull(&b, 8);
716 return *enable != 0;
717}