]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-table.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / ofp-table.c
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-table.h"
19 #include "bitmap.h"
20 #include "nx-match.h"
21 #include "openvswitch/dynamic-string.h"
22 #include "openvswitch/json.h"
23 #include "openvswitch/ofp-actions.h"
24 #include "openvswitch/ofp-msgs.h"
25 #include "openvswitch/ofp-print.h"
26 #include "openvswitch/ofp-prop.h"
27 #include "openvswitch/ofpbuf.h"
28 #include "openvswitch/vlog.h"
29 #include "util.h"
30
31 VLOG_DEFINE_THIS_MODULE(ofp_table);
32
33 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
34
35 static ovs_be32 ofputil_encode_table_config(enum ofputil_table_miss,
36 enum ofputil_table_eviction,
37 enum ofputil_table_vacancy,
38 enum ofp_version);
39 static enum ofputil_table_vacancy ofputil_decode_table_vacancy(
40 ovs_be32 config, enum ofp_version);
41 static enum ofputil_table_eviction ofputil_decode_table_eviction(
42 ovs_be32 config, enum ofp_version);
43
44 const char *
45 ofputil_table_miss_to_string(enum ofputil_table_miss miss)
46 {
47 switch (miss) {
48 case OFPUTIL_TABLE_MISS_DEFAULT: return "default";
49 case OFPUTIL_TABLE_MISS_CONTROLLER: return "controller";
50 case OFPUTIL_TABLE_MISS_CONTINUE: return "continue";
51 case OFPUTIL_TABLE_MISS_DROP: return "drop";
52 default: return "***error***";
53 }
54 }
55
56 const char *
57 ofputil_table_eviction_to_string(enum ofputil_table_eviction eviction)
58 {
59 switch (eviction) {
60 case OFPUTIL_TABLE_EVICTION_DEFAULT: return "default";
61 case OFPUTIL_TABLE_EVICTION_ON: return "on";
62 case OFPUTIL_TABLE_EVICTION_OFF: return "off";
63 default: return "***error***";
64 }
65 }
66
67 const char *
68 ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy)
69 {
70 switch (vacancy) {
71 case OFPUTIL_TABLE_VACANCY_DEFAULT: return "default";
72 case OFPUTIL_TABLE_VACANCY_ON: return "on";
73 case OFPUTIL_TABLE_VACANCY_OFF: return "off";
74 default: return "***error***";
75 }
76 }
77
78 static bool
79 ofp15_table_features_command_is_valid(enum ofp15_table_features_command cmd)
80 {
81 switch (cmd) {
82 case OFPTFC15_REPLACE:
83 case OFPTFC15_MODIFY:
84 case OFPTFC15_ENABLE:
85 case OFPTFC15_DISABLE:
86 return true;
87
88 default:
89 return false;
90 }
91 }
92
93 static const char *
94 ofp15_table_features_command_to_string(enum ofp15_table_features_command cmd)
95 {
96 switch (cmd) {
97 case OFPTFC15_REPLACE: return "replace";
98 case OFPTFC15_MODIFY: return "modify";
99 case OFPTFC15_ENABLE: return "enable";
100 case OFPTFC15_DISABLE: return "disable";
101 default: return "***bad command***";
102 }
103 }
104 \f
105 /* ofputil_table_map. */
106
107 void
108 ofputil_table_map_init(struct ofputil_table_map *map)
109 {
110 namemap_init(&map->map);
111 }
112
113 void
114 ofputil_table_map_put(struct ofputil_table_map *map,
115 uint8_t table_id, const char *name)
116 {
117 namemap_put(&map->map, table_id, name);
118 }
119
120 const char *
121 ofputil_table_map_get_name(const struct ofputil_table_map *map,
122 uint8_t table_id)
123 {
124 struct namemap_node *node
125 = map ? namemap_find_by_number(&map->map, table_id) : NULL;
126 return node && !node->duplicate ? node->name : NULL;
127 }
128
129 uint8_t
130 ofputil_table_map_get_number(const struct ofputil_table_map *map,
131 const char *name)
132 {
133 struct namemap_node *node
134 = map ? namemap_find_by_name(&map->map, name) : NULL;
135 return node && !node->duplicate ? node->number : UINT8_MAX;
136 }
137
138 void
139 ofputil_table_map_destroy(struct ofputil_table_map *map)
140 {
141 namemap_destroy(&map->map);
142 }
143 \f
144 /* Table numbers. */
145
146 /* Stores the table number represented by 's' into '*tablep'. 's' may be an
147 * integer or, if 'table_map' is nonnull, a name (quoted or unquoted).
148 *
149 * Returns true if successful, false if 's' is not a valid OpenFlow table
150 * number or name. The caller should issue an error message in this case,
151 * because this function usually does not. (This gives the caller an
152 * opportunity to look up the table name another way, e.g. by contacting the
153 * switch and listing the names of all its tables). */
154 bool
155 ofputil_table_from_string(const char *s,
156 const struct ofputil_table_map *table_map,
157 uint8_t *tablep)
158 {
159 *tablep = 0;
160 if (*s == '-') {
161 VLOG_WARN("Negative value %s is not a valid table number.", s);
162 return false;
163 }
164
165 unsigned int table;
166 if (str_to_uint(s, 10, &table)) {
167 if (table > 255) {
168 VLOG_WARN("table %u is outside the supported range 0 through 255",
169 table);
170 return false;
171 }
172 *tablep = table;
173 return true;
174 } else {
175 if (s[0] != '"') {
176 table = ofputil_table_map_get_number(table_map, s);
177 } else {
178 size_t length = strlen(s);
179 char *name = NULL;
180 if (length > 1
181 && s[length - 1] == '"'
182 && json_string_unescape(s + 1, length - 2, &name)) {
183 table = ofputil_table_map_get_number(table_map, name);
184 }
185 free(name);
186 }
187 if (table != UINT8_MAX) {
188 *tablep = table;
189 return true;
190 }
191
192 return false;
193 }
194 }
195
196 /* Appends to 's' a string representation of the OpenFlow table number 'table',
197 * either the table number or a name drawn from 'table_map'. */
198 void
199 ofputil_format_table(uint8_t table, const struct ofputil_table_map *table_map,
200 struct ds *s)
201 {
202 const char *table_name = ofputil_table_map_get_name(table_map, table);
203 if (table_name) {
204 namemap_put_name(table_name, s);
205 } else {
206 ds_put_format(s, "%"PRIu8, table);
207 }
208 }
209
210 /* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string
211 * representation of OpenFlow table number 'table', either the table's number
212 * or a name drawn from 'table_map'. */
213 void
214 ofputil_table_to_string(uint8_t table,
215 const struct ofputil_table_map *table_map,
216 char *namebuf, size_t bufsize)
217 {
218 const char *table_name = ofputil_table_map_get_name(table_map, table);
219 if (table_name) {
220 struct ds s = DS_EMPTY_INITIALIZER;
221 namemap_put_name(table_name, &s);
222 ovs_strlcpy(namebuf, ds_cstr(&s), bufsize);
223 ds_destroy(&s);
224 return;
225 }
226
227 snprintf(namebuf, bufsize, "%"PRIu8, table);
228 }
229 \f
230 /* Table features. */
231
232 static enum ofperr
233 pull_table_feature_property(struct ofpbuf *msg, struct ofpbuf *payload,
234 uint64_t *typep)
235 {
236 enum ofperr error;
237
238 error = ofpprop_pull(msg, payload, typep);
239 if (payload && !error) {
240 ofpbuf_pull(payload, (char *)payload->msg - (char *)payload->header);
241 }
242 return error;
243 }
244
245 static enum ofperr
246 parse_action_bitmap(struct ofpbuf *payload, enum ofp_version ofp_version,
247 uint64_t *ofpacts)
248 {
249 uint32_t types = 0;
250
251 while (payload->size > 0) {
252 enum ofperr error;
253 uint64_t type;
254
255 error = ofpprop_pull__(payload, NULL, 1, 0x10000, &type);
256 if (error) {
257 return error;
258 }
259 if (type < CHAR_BIT * sizeof types) {
260 types |= 1u << type;
261 }
262 }
263
264 *ofpacts = ofpact_bitmap_from_openflow(htonl(types), ofp_version);
265 return 0;
266 }
267
268 static enum ofperr
269 parse_instruction_ids(struct ofpbuf *payload, bool loose, uint32_t *insts)
270 {
271 *insts = 0;
272 while (payload->size > 0) {
273 enum ovs_instruction_type inst;
274 enum ofperr error;
275 uint64_t ofpit;
276
277 /* OF1.3 and OF1.4 aren't clear about padding in the instruction IDs.
278 * It seems clear that they aren't padded to 8 bytes, though, because
279 * both standards say that "non-experimenter instructions are 4 bytes"
280 * and do not mention any padding before the first instruction ID.
281 * (There wouldn't be any point in padding to 8 bytes if the IDs were
282 * aligned on an odd 4-byte boundary.)
283 *
284 * Anyway, we just assume they're all glommed together on byte
285 * boundaries. */
286 error = ofpprop_pull__(payload, NULL, 1, 0x10000, &ofpit);
287 if (error) {
288 return error;
289 }
290
291 error = ovs_instruction_type_from_inst_type(&inst, ofpit);
292 if (!error) {
293 *insts |= 1u << inst;
294 } else if (!loose) {
295 return error;
296 }
297 }
298 return 0;
299 }
300
301 static enum ofperr
302 parse_table_features_next_table(struct ofpbuf *payload,
303 unsigned long int *next_tables)
304 {
305 size_t i;
306
307 memset(next_tables, 0, bitmap_n_bytes(255));
308 for (i = 0; i < payload->size; i++) {
309 uint8_t id = ((const uint8_t *) payload->data)[i];
310 if (id >= 255) {
311 return OFPERR_OFPBPC_BAD_VALUE;
312 }
313 bitmap_set1(next_tables, id);
314 }
315 return 0;
316 }
317
318 static enum ofperr
319 parse_oxms(struct ofpbuf *payload, bool loose,
320 struct mf_bitmap *exactp, struct mf_bitmap *maskedp)
321 {
322 struct mf_bitmap exact = MF_BITMAP_INITIALIZER;
323 struct mf_bitmap masked = MF_BITMAP_INITIALIZER;
324
325 while (payload->size > 0) {
326 const struct mf_field *field;
327 enum ofperr error;
328 bool hasmask;
329
330 error = nx_pull_header(payload, NULL, &field, &hasmask);
331 if (!error) {
332 bitmap_set1(hasmask ? masked.bm : exact.bm, field->id);
333 } else if (error != OFPERR_OFPBMC_BAD_FIELD || !loose) {
334 return error;
335 }
336 }
337 if (exactp) {
338 *exactp = exact;
339 } else if (!bitmap_is_all_zeros(exact.bm, MFF_N_IDS)) {
340 return OFPERR_OFPBMC_BAD_MASK;
341 }
342 if (maskedp) {
343 *maskedp = masked;
344 } else if (!bitmap_is_all_zeros(masked.bm, MFF_N_IDS)) {
345 return OFPERR_OFPBMC_BAD_MASK;
346 }
347 return 0;
348 }
349
350 /* Converts an OFPMP_TABLE_FEATURES request or reply in 'msg' into an abstract
351 * ofputil_table_features in 'tf'.
352 *
353 * If 'raw_properties' is nonnull, this function ignores properties and values
354 * that it does not understand, as a controller would want to do when
355 * interpreting capabilities provided by a switch. In this mode, on success,
356 * it initializes 'raw_properties' to contain the properties that were parsed;
357 * this allows the caller to later re-serialize the same properties without
358 * change.
359 *
360 * If 'raw_properties' is null, this function treats unknown properties and
361 * values as an error, as a switch would want to do when interpreting a
362 * configuration request made by a controller.
363 *
364 * A single OpenFlow message can specify features for multiple tables. Calling
365 * this function multiple times for a single 'msg' iterates through the tables
366 * in the message. The caller must initially leave 'msg''s layer pointers null
367 * and not modify them between calls.
368 *
369 * Returns 0 if successful, EOF if no tables were left in this 'msg', otherwise
370 * a positive "enum ofperr" value. */
371 int
372 ofputil_decode_table_features(struct ofpbuf *msg,
373 struct ofputil_table_features *tf,
374 struct ofpbuf *raw_properties)
375 {
376 bool loose = raw_properties != NULL;
377
378 memset(tf, 0, sizeof *tf);
379
380 if (!msg->header) {
381 ofpraw_pull_assert(msg);
382 }
383
384 if (!msg->size) {
385 return EOF;
386 }
387
388 const struct ofp_header *oh = msg->header;
389 struct ofp13_table_features *otf = msg->data;
390 if (msg->size < sizeof *otf) {
391 return OFPERR_OFPBPC_BAD_LEN;
392 }
393
394 unsigned int len = ntohs(otf->length);
395 if (len < sizeof *otf || len % 8 || len > msg->size) {
396 return OFPERR_OFPBPC_BAD_LEN;
397 }
398
399 if (oh->version >= OFP15_VERSION) {
400 if (!ofp15_table_features_command_is_valid(otf->command)) {
401 return OFPERR_OFPTFFC_BAD_COMMAND;
402 }
403 tf->command = otf->command;
404 } else {
405 tf->command = OFPTFC15_REPLACE;
406 }
407
408 tf->table_id = otf->table_id;
409 if (tf->table_id == OFPTT_ALL) {
410 return OFPERR_OFPTFFC_BAD_TABLE;
411 }
412
413 ovs_strlcpy_arrays(tf->name, otf->name);
414 tf->metadata_match = otf->metadata_match;
415 tf->metadata_write = otf->metadata_write;
416 tf->miss_config = OFPUTIL_TABLE_MISS_DEFAULT;
417 if (oh->version >= OFP14_VERSION) {
418 uint32_t caps = ntohl(otf->capabilities);
419 tf->supports_eviction = (caps & OFPTC14_EVICTION) != 0;
420 tf->supports_vacancy_events = (caps & OFPTC14_VACANCY_EVENTS) != 0;
421 } else {
422 tf->supports_eviction = -1;
423 tf->supports_vacancy_events = -1;
424 }
425 tf->max_entries = ntohl(otf->max_entries);
426
427 struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
428 len);
429 ofpbuf_pull(&properties, sizeof *otf);
430 tf->any_properties = properties.size > 0;
431 if (raw_properties) {
432 *raw_properties = properties;
433 }
434 uint32_t seen = 0;
435 while (properties.size > 0) {
436 struct ofpbuf payload;
437 enum ofperr error;
438 uint64_t type;
439
440 error = pull_table_feature_property(&properties, &payload, &type);
441 if (error) {
442 return error;
443 }
444
445 if (type < 32) {
446 uint32_t bit = 1u << type;
447 if (seen & bit) {
448 return OFPERR_OFPTFFC_BAD_FEATURES;
449 }
450 seen |= bit;
451 }
452
453 switch ((enum ofp13_table_feature_prop_type) type) {
454 case OFPTFPT13_INSTRUCTIONS:
455 error = parse_instruction_ids(&payload, loose,
456 &tf->nonmiss.instructions);
457 break;
458 case OFPTFPT13_INSTRUCTIONS_MISS:
459 error = parse_instruction_ids(&payload, loose,
460 &tf->miss.instructions);
461 break;
462
463 case OFPTFPT13_NEXT_TABLES:
464 error = parse_table_features_next_table(&payload,
465 tf->nonmiss.next);
466 break;
467 case OFPTFPT13_NEXT_TABLES_MISS:
468 error = parse_table_features_next_table(&payload, tf->miss.next);
469 break;
470
471 case OFPTFPT13_WRITE_ACTIONS:
472 error = parse_action_bitmap(&payload, oh->version,
473 &tf->nonmiss.write.ofpacts);
474 break;
475 case OFPTFPT13_WRITE_ACTIONS_MISS:
476 error = parse_action_bitmap(&payload, oh->version,
477 &tf->miss.write.ofpacts);
478 break;
479
480 case OFPTFPT13_APPLY_ACTIONS:
481 error = parse_action_bitmap(&payload, oh->version,
482 &tf->nonmiss.apply.ofpacts);
483 break;
484 case OFPTFPT13_APPLY_ACTIONS_MISS:
485 error = parse_action_bitmap(&payload, oh->version,
486 &tf->miss.apply.ofpacts);
487 break;
488
489 case OFPTFPT13_MATCH:
490 error = parse_oxms(&payload, loose, &tf->match, &tf->mask);
491 break;
492 case OFPTFPT13_WILDCARDS:
493 error = parse_oxms(&payload, loose, &tf->wildcard, NULL);
494 break;
495
496 case OFPTFPT13_WRITE_SETFIELD:
497 error = parse_oxms(&payload, loose,
498 &tf->nonmiss.write.set_fields, NULL);
499 break;
500 case OFPTFPT13_WRITE_SETFIELD_MISS:
501 error = parse_oxms(&payload, loose,
502 &tf->miss.write.set_fields, NULL);
503 break;
504 case OFPTFPT13_APPLY_SETFIELD:
505 error = parse_oxms(&payload, loose,
506 &tf->nonmiss.apply.set_fields, NULL);
507 break;
508 case OFPTFPT13_APPLY_SETFIELD_MISS:
509 error = parse_oxms(&payload, loose,
510 &tf->miss.apply.set_fields, NULL);
511 break;
512
513 case OFPTFPT13_EXPERIMENTER:
514 case OFPTFPT13_EXPERIMENTER_MISS:
515 default:
516 error = OFPPROP_UNKNOWN(loose, "table features", type);
517 break;
518 }
519 if (error) {
520 return error;
521 }
522 }
523
524 /* OpenFlow 1.3 and 1.4 always require all of the required properties.
525 * OpenFlow 1.5 requires all of them if any property is present. */
526 if ((seen & OFPTFPT13_REQUIRED) != OFPTFPT13_REQUIRED
527 && (tf->any_properties || oh->version < OFP15_VERSION)) {
528 VLOG_WARN_RL(&rl, "table features message missing required property");
529 return OFPERR_OFPTFFC_BAD_FEATURES;
530 }
531
532 /* Copy nonmiss to miss when appropriate. */
533 if (tf->any_properties) {
534 if (!(seen & (1u << OFPTFPT13_INSTRUCTIONS_MISS))) {
535 tf->miss.instructions = tf->nonmiss.instructions;
536 }
537 if (!(seen & (1u << OFPTFPT13_NEXT_TABLES_MISS))) {
538 memcpy(tf->miss.next, tf->nonmiss.next, sizeof tf->miss.next);
539 }
540 if (!(seen & (1u << OFPTFPT13_WRITE_ACTIONS_MISS))) {
541 tf->miss.write.ofpacts = tf->nonmiss.write.ofpacts;
542 }
543 if (!(seen & (1u << OFPTFPT13_APPLY_ACTIONS_MISS))) {
544 tf->miss.apply.ofpacts = tf->nonmiss.apply.ofpacts;
545 }
546 if (!(seen & (1u << OFPTFPT13_WRITE_SETFIELD_MISS))) {
547 tf->miss.write.set_fields = tf->nonmiss.write.set_fields;
548 }
549 if (!(seen & (1u << OFPTFPT13_APPLY_SETFIELD_MISS))) {
550 tf->miss.apply.set_fields = tf->nonmiss.apply.set_fields;
551 }
552 }
553
554 /* Fix inconsistencies:
555 *
556 * - Turn on 'match' bits that are set in 'mask', because maskable
557 * fields are matchable.
558 *
559 * - Turn on 'wildcard' bits that are set in 'mask', because a field
560 * that is arbitrarily maskable can be wildcarded entirely.
561 *
562 * - Turn off 'wildcard' bits that are not in 'match', because a field
563 * must be matchable for it to be meaningfully wildcarded. */
564 bitmap_or(tf->match.bm, tf->mask.bm, MFF_N_IDS);
565 bitmap_or(tf->wildcard.bm, tf->mask.bm, MFF_N_IDS);
566 bitmap_and(tf->wildcard.bm, tf->match.bm, MFF_N_IDS);
567
568 return 0;
569 }
570
571 /* Encodes and returns a request to obtain the table features of a switch.
572 * The message is encoded for OpenFlow version 'ofp_version'. */
573 struct ofpbuf *
574 ofputil_encode_table_features_request(enum ofp_version ofp_version)
575 {
576 struct ofpbuf *request = NULL;
577
578 switch (ofp_version) {
579 case OFP10_VERSION:
580 case OFP11_VERSION:
581 case OFP12_VERSION:
582 ovs_fatal(0, "dump-table-features needs OpenFlow 1.3 or later "
583 "(\'-O OpenFlow13\')");
584 case OFP13_VERSION:
585 case OFP14_VERSION:
586 case OFP15_VERSION:
587 request = ofpraw_alloc(OFPRAW_OFPST13_TABLE_FEATURES_REQUEST,
588 ofp_version, 0);
589 break;
590 default:
591 OVS_NOT_REACHED();
592 }
593
594 return request;
595 }
596
597 static void
598 put_fields_property(struct ofpbuf *reply,
599 const struct mf_bitmap *fields,
600 const struct mf_bitmap *masks,
601 enum ofp13_table_feature_prop_type property,
602 enum ofp_version version)
603 {
604 size_t start_ofs;
605 int field;
606
607 start_ofs = ofpprop_start(reply, property);
608 BITMAP_FOR_EACH_1 (field, MFF_N_IDS, fields->bm) {
609 nx_put_header(reply, field, version,
610 masks && bitmap_is_set(masks->bm, field));
611 }
612 ofpprop_end(reply, start_ofs);
613 }
614
615 static void
616 put_table_action_features(struct ofpbuf *reply,
617 const struct ofputil_table_action_features *taf,
618 enum ofp13_table_feature_prop_type actions_type,
619 enum ofp13_table_feature_prop_type set_fields_type,
620 int miss_offset, enum ofp_version version)
621 {
622 ofpprop_put_bitmap(reply, actions_type + miss_offset,
623 ntohl(ofpact_bitmap_to_openflow(taf->ofpacts,
624 version)));
625 put_fields_property(reply, &taf->set_fields, NULL,
626 set_fields_type + miss_offset, version);
627 }
628
629 static void
630 put_table_instruction_features(
631 struct ofpbuf *reply, const struct ofputil_table_instruction_features *tif,
632 int miss_offset, enum ofp_version version)
633 {
634 size_t start_ofs;
635 uint8_t table_id;
636
637 ofpprop_put_bitmap(reply, OFPTFPT13_INSTRUCTIONS + miss_offset,
638 ntohl(ovsinst_bitmap_to_openflow(tif->instructions,
639 version)));
640
641 start_ofs = ofpprop_start(reply, OFPTFPT13_NEXT_TABLES + miss_offset);
642 BITMAP_FOR_EACH_1 (table_id, 255, tif->next) {
643 ofpbuf_put(reply, &table_id, 1);
644 }
645 ofpprop_end(reply, start_ofs);
646
647 put_table_action_features(reply, &tif->write,
648 OFPTFPT13_WRITE_ACTIONS,
649 OFPTFPT13_WRITE_SETFIELD, miss_offset, version);
650 put_table_action_features(reply, &tif->apply,
651 OFPTFPT13_APPLY_ACTIONS,
652 OFPTFPT13_APPLY_SETFIELD, miss_offset, version);
653 }
654
655 /* Appends a table features record to 'msgs', which must be a
656 * OFPT_TABLE_FEATURES request or reply. If 'raw_properties' is nonnull, then
657 * it uses its contents verbatim as the table features properties, ignoring the
658 * corresponding members of 'tf'. */
659 void
660 ofputil_append_table_features(const struct ofputil_table_features *tf,
661 const struct ofpbuf *raw_properties,
662 struct ovs_list *msgs)
663 {
664 struct ofpbuf *msg = ofpbuf_from_list(ovs_list_back(msgs));
665 enum ofp_version version = ofpmp_version(msgs);
666 size_t start_ofs = msg->size;
667 struct ofp13_table_features *otf;
668
669 otf = ofpbuf_put_zeros(msg, sizeof *otf);
670 otf->table_id = tf->table_id;
671 otf->command = version >= OFP15_VERSION ? tf->command : 0;
672 ovs_strlcpy_arrays(otf->name, tf->name);
673 otf->metadata_match = tf->metadata_match;
674 otf->metadata_write = tf->metadata_write;
675 if (version >= OFP14_VERSION) {
676 if (tf->supports_eviction) {
677 otf->capabilities |= htonl(OFPTC14_EVICTION);
678 }
679 if (tf->supports_vacancy_events) {
680 otf->capabilities |= htonl(OFPTC14_VACANCY_EVENTS);
681 }
682 }
683 otf->max_entries = htonl(tf->max_entries);
684
685 if (raw_properties) {
686 ofpbuf_put(msg, raw_properties->data, raw_properties->size);
687 } else if (tf->any_properties) {
688 put_table_instruction_features(msg, &tf->nonmiss, 0, version);
689 put_table_instruction_features(msg, &tf->miss, 1, version);
690
691 put_fields_property(msg, &tf->match, &tf->mask,
692 OFPTFPT13_MATCH, version);
693 put_fields_property(msg, &tf->wildcard, NULL,
694 OFPTFPT13_WILDCARDS, version);
695 }
696
697 otf = ofpbuf_at_assert(msg, start_ofs, sizeof *otf);
698 otf->length = htons(msg->size - start_ofs);
699 ofpmp_postappend(msgs, start_ofs);
700 }
701
702 static enum ofperr
703 parse_table_desc_vacancy_property(struct ofpbuf *property,
704 struct ofputil_table_desc *td)
705 {
706 struct ofp14_table_mod_prop_vacancy *otv = property->data;
707
708 if (property->size != sizeof *otv) {
709 return OFPERR_OFPBPC_BAD_LEN;
710 }
711
712 td->table_vacancy.vacancy_down = otv->vacancy_down;
713 td->table_vacancy.vacancy_up = otv->vacancy_up;
714 td->table_vacancy.vacancy = otv->vacancy;
715 return 0;
716 }
717
718 /* Decodes the next OpenFlow "table desc" message (of possibly several) from
719 * 'msg' into an abstract form in '*td'. Returns 0 if successful, EOF if the
720 * last "table desc" in 'msg' was already decoded, otherwise an OFPERR_*
721 * value. */
722 int
723 ofputil_decode_table_desc(struct ofpbuf *msg,
724 struct ofputil_table_desc *td,
725 enum ofp_version version)
726 {
727 memset(td, 0, sizeof *td);
728
729 if (!msg->header) {
730 ofpraw_pull_assert(msg);
731 }
732
733 if (!msg->size) {
734 return EOF;
735 }
736
737 struct ofp14_table_desc *otd = ofpbuf_try_pull(msg, sizeof *otd);
738 if (!otd) {
739 VLOG_WARN_RL(&rl, "OFP14_TABLE_DESC reply has %"PRIu32" "
740 "leftover bytes at end", msg->size);
741 return OFPERR_OFPBRC_BAD_LEN;
742 }
743
744 td->table_id = otd->table_id;
745 size_t length = ntohs(otd->length);
746 if (length < sizeof *otd || length - sizeof *otd > msg->size) {
747 VLOG_WARN_RL(&rl, "OFP14_TABLE_DESC reply claims invalid "
748 "length %"PRIuSIZE, length);
749 return OFPERR_OFPBRC_BAD_LEN;
750 }
751 length -= sizeof *otd;
752
753 td->eviction = ofputil_decode_table_eviction(otd->config, version);
754 td->vacancy = ofputil_decode_table_vacancy(otd->config, version);
755 td->eviction_flags = UINT32_MAX;
756
757 struct ofpbuf properties = ofpbuf_const_initializer(
758 ofpbuf_pull(msg, length), length);
759 while (properties.size > 0) {
760 struct ofpbuf payload;
761 enum ofperr error;
762 uint64_t type;
763
764 error = ofpprop_pull(&properties, &payload, &type);
765 if (error) {
766 return error;
767 }
768
769 switch (type) {
770 case OFPTMPT14_EVICTION:
771 error = ofpprop_parse_u32(&payload, &td->eviction_flags);
772 break;
773
774 case OFPTMPT14_VACANCY:
775 error = parse_table_desc_vacancy_property(&payload, td);
776 break;
777
778 default:
779 error = OFPPROP_UNKNOWN(true, "table_desc", type);
780 break;
781 }
782
783 if (error) {
784 return error;
785 }
786 }
787
788 return 0;
789 }
790
791 /* Encodes and returns a request to obtain description of tables of a switch.
792 * The message is encoded for OpenFlow version 'ofp_version'. */
793 struct ofpbuf *
794 ofputil_encode_table_desc_request(enum ofp_version ofp_version)
795 {
796 struct ofpbuf *request = NULL;
797
798 if (ofp_version >= OFP14_VERSION) {
799 request = ofpraw_alloc(OFPRAW_OFPST14_TABLE_DESC_REQUEST,
800 ofp_version, 0);
801 } else {
802 ovs_fatal(0, "dump-table-desc needs OpenFlow 1.4 or later "
803 "(\'-O OpenFlow14\')");
804 }
805
806 return request;
807 }
808
809 /* Function to append Table desc information in a reply list. */
810 void
811 ofputil_append_table_desc_reply(const struct ofputil_table_desc *td,
812 struct ovs_list *replies,
813 enum ofp_version version)
814 {
815 struct ofpbuf *reply = ofpbuf_from_list(ovs_list_back(replies));
816 size_t start_otd;
817 struct ofp14_table_desc *otd;
818
819 start_otd = reply->size;
820 ofpbuf_put_zeros(reply, sizeof *otd);
821 if (td->eviction_flags != UINT32_MAX) {
822 ofpprop_put_u32(reply, OFPTMPT14_EVICTION, td->eviction_flags);
823 }
824 if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
825 struct ofp14_table_mod_prop_vacancy *otv;
826
827 otv = ofpprop_put_zeros(reply, OFPTMPT14_VACANCY, sizeof *otv);
828 otv->vacancy_down = td->table_vacancy.vacancy_down;
829 otv->vacancy_up = td->table_vacancy.vacancy_up;
830 otv->vacancy = td->table_vacancy.vacancy;
831 }
832
833 otd = ofpbuf_at_assert(reply, start_otd, sizeof *otd);
834 otd->length = htons(reply->size - start_otd);
835 otd->table_id = td->table_id;
836 otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
837 td->eviction, td->vacancy,
838 version);
839 ofpmp_postappend(replies, start_otd);
840 }
841
842 static const char *
843 ofputil_eviction_flag_to_string(uint32_t bit)
844 {
845 enum ofp14_table_mod_prop_eviction_flag eviction_flag = bit;
846
847 switch (eviction_flag) {
848 case OFPTMPEF14_OTHER: return "OTHER";
849 case OFPTMPEF14_IMPORTANCE: return "IMPORTANCE";
850 case OFPTMPEF14_LIFETIME: return "LIFETIME";
851 }
852
853 return NULL;
854 }
855
856 /* Appends to 'string' a description of the bitmap of OFPTMPEF14_* values in
857 * 'eviction_flags'. */
858 static void
859 ofputil_put_eviction_flags(struct ds *string, uint32_t eviction_flags)
860 {
861 if (eviction_flags != UINT32_MAX) {
862 ofp_print_bit_names(string, eviction_flags,
863 ofputil_eviction_flag_to_string, '|');
864 } else {
865 ds_put_cstr(string, "(default)");
866 }
867 }
868
869 void
870 ofputil_table_desc_format(struct ds *s, const struct ofputil_table_desc *td,
871 const struct ofputil_table_map *table_map)
872 {
873 ds_put_format(s, "\n table ");
874 ofputil_format_table(td->table_id, table_map, s);
875 ds_put_cstr(s, ":\n");
876 ds_put_format(s, " eviction=%s eviction_flags=",
877 ofputil_table_eviction_to_string(td->eviction));
878 ofputil_put_eviction_flags(s, td->eviction_flags);
879 ds_put_char(s, '\n');
880 ds_put_format(s, " vacancy=%s",
881 ofputil_table_vacancy_to_string(td->vacancy));
882 if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
883 ds_put_format(s, " vacancy_down=%"PRIu8"%%",
884 td->table_vacancy.vacancy_down);
885 ds_put_format(s, " vacancy_up=%"PRIu8"%%",
886 td->table_vacancy.vacancy_up);
887 ds_put_format(s, " vacancy=%"PRIu8"%%",
888 td->table_vacancy.vacancy);
889 }
890 ds_put_char(s, '\n');
891 }
892
893 /* This function parses Vacancy property, and decodes the
894 * ofp14_table_mod_prop_vacancy in ofputil_table_mod.
895 * Returns OFPERR_OFPBPC_BAD_VALUE error code when vacancy_down is
896 * greater than vacancy_up and also when current vacancy has non-zero
897 * value. Returns 0 on success. */
898 static enum ofperr
899 parse_table_mod_vacancy_property(struct ofpbuf *property,
900 struct ofputil_table_mod *tm)
901 {
902 struct ofp14_table_mod_prop_vacancy *otv = property->data;
903
904 if (property->size != sizeof *otv) {
905 return OFPERR_OFPBPC_BAD_LEN;
906 }
907 tm->table_vacancy.vacancy_down = otv->vacancy_down;
908 tm->table_vacancy.vacancy_up = otv->vacancy_up;
909 if (tm->table_vacancy.vacancy_down > tm->table_vacancy.vacancy_up) {
910 OFPPROP_LOG(&rl, false,
911 "Value of vacancy_down is greater than vacancy_up");
912 return OFPERR_OFPBPC_BAD_VALUE;
913 }
914 if (tm->table_vacancy.vacancy_down > 100 ||
915 tm->table_vacancy.vacancy_up > 100) {
916 OFPPROP_LOG(&rl, false, "Vacancy threshold percentage "
917 "should not be greater than 100");
918 return OFPERR_OFPBPC_BAD_VALUE;
919 }
920 tm->table_vacancy.vacancy = otv->vacancy;
921 if (tm->table_vacancy.vacancy) {
922 OFPPROP_LOG(&rl, false,
923 "Vacancy value should be zero for table-mod messages");
924 return OFPERR_OFPBPC_BAD_VALUE;
925 }
926 return 0;
927 }
928
929 /* Given 'config', taken from an OpenFlow 'version' message that specifies
930 * table configuration (a table mod, table stats, or table features message),
931 * returns the table vacancy configuration that it specifies.
932 *
933 * Only OpenFlow 1.4 and later specify table vacancy configuration this way,
934 * so for other 'version' this function always returns
935 * OFPUTIL_TABLE_VACANCY_DEFAULT. */
936 static enum ofputil_table_vacancy
937 ofputil_decode_table_vacancy(ovs_be32 config, enum ofp_version version)
938 {
939 return (version < OFP14_VERSION ? OFPUTIL_TABLE_VACANCY_DEFAULT
940 : config & htonl(OFPTC14_VACANCY_EVENTS) ? OFPUTIL_TABLE_VACANCY_ON
941 : OFPUTIL_TABLE_VACANCY_OFF);
942 }
943
944 /* Given 'config', taken from an OpenFlow 'version' message that specifies
945 * table configuration (a table mod, table stats, or table features message),
946 * returns the table eviction configuration that it specifies.
947 *
948 * Only OpenFlow 1.4 and later specify table eviction configuration this way,
949 * so for other 'version' values this function always returns
950 * OFPUTIL_TABLE_EVICTION_DEFAULT. */
951 static enum ofputil_table_eviction
952 ofputil_decode_table_eviction(ovs_be32 config, enum ofp_version version)
953 {
954 return (version < OFP14_VERSION ? OFPUTIL_TABLE_EVICTION_DEFAULT
955 : config & htonl(OFPTC14_EVICTION) ? OFPUTIL_TABLE_EVICTION_ON
956 : OFPUTIL_TABLE_EVICTION_OFF);
957 }
958
959 /* Returns a bitmap of OFPTC* values suitable for 'config' fields in various
960 * OpenFlow messages of the given 'version', based on the provided 'miss' and
961 * 'eviction' values. */
962 static ovs_be32
963 ofputil_encode_table_config(enum ofputil_table_miss miss,
964 enum ofputil_table_eviction eviction,
965 enum ofputil_table_vacancy vacancy,
966 enum ofp_version version)
967 {
968 uint32_t config = 0;
969 /* Search for "OFPTC_* Table Configuration" in the documentation for more
970 * information on the crazy evolution of this field. */
971 switch (version) {
972 case OFP10_VERSION:
973 /* OpenFlow 1.0 didn't have such a field, any value ought to do. */
974 return htonl(0);
975
976 case OFP11_VERSION:
977 case OFP12_VERSION:
978 /* OpenFlow 1.1 and 1.2 define only OFPTC11_TABLE_MISS_*. */
979 switch (miss) {
980 case OFPUTIL_TABLE_MISS_DEFAULT:
981 /* Really this shouldn't be used for encoding (the caller should
982 * provide a specific value) but I can't imagine that defaulting to
983 * the fall-through case here will hurt. */
984 case OFPUTIL_TABLE_MISS_CONTROLLER:
985 default:
986 return htonl(OFPTC11_TABLE_MISS_CONTROLLER);
987 case OFPUTIL_TABLE_MISS_CONTINUE:
988 return htonl(OFPTC11_TABLE_MISS_CONTINUE);
989 case OFPUTIL_TABLE_MISS_DROP:
990 return htonl(OFPTC11_TABLE_MISS_DROP);
991 }
992 OVS_NOT_REACHED();
993
994 case OFP13_VERSION:
995 /* OpenFlow 1.3 removed OFPTC11_TABLE_MISS_* and didn't define any new
996 * flags, so this is correct. */
997 return htonl(0);
998
999 case OFP14_VERSION:
1000 case OFP15_VERSION:
1001 /* OpenFlow 1.4 introduced OFPTC14_EVICTION and
1002 * OFPTC14_VACANCY_EVENTS. */
1003 if (eviction == OFPUTIL_TABLE_EVICTION_ON) {
1004 config |= OFPTC14_EVICTION;
1005 }
1006 if (vacancy == OFPUTIL_TABLE_VACANCY_ON) {
1007 config |= OFPTC14_VACANCY_EVENTS;
1008 }
1009 return htonl(config);
1010 }
1011
1012 OVS_NOT_REACHED();
1013 }
1014
1015 /* Given 'config', taken from an OpenFlow 'version' message that specifies
1016 * table configuration (a table mod, table stats, or table features message),
1017 * returns the table miss configuration that it specifies.
1018 *
1019 * Only OpenFlow 1.1 and 1.2 specify table miss configurations this way, so for
1020 * other 'version' values this function always returns
1021 * OFPUTIL_TABLE_MISS_DEFAULT. */
1022 static enum ofputil_table_miss
1023 ofputil_decode_table_miss(ovs_be32 config_, enum ofp_version version)
1024 {
1025 uint32_t config = ntohl(config_);
1026
1027 if (version == OFP11_VERSION || version == OFP12_VERSION) {
1028 switch (config & OFPTC11_TABLE_MISS_MASK) {
1029 case OFPTC11_TABLE_MISS_CONTROLLER:
1030 return OFPUTIL_TABLE_MISS_CONTROLLER;
1031
1032 case OFPTC11_TABLE_MISS_CONTINUE:
1033 return OFPUTIL_TABLE_MISS_CONTINUE;
1034
1035 case OFPTC11_TABLE_MISS_DROP:
1036 return OFPUTIL_TABLE_MISS_DROP;
1037
1038 default:
1039 VLOG_WARN_RL(&rl, "bad table miss config %d", config);
1040 return OFPUTIL_TABLE_MISS_CONTROLLER;
1041 }
1042 } else {
1043 return OFPUTIL_TABLE_MISS_DEFAULT;
1044 }
1045 }
1046
1047 /* Decodes the OpenFlow "table mod" message in '*oh' into an abstract form in
1048 * '*pm'. Returns 0 if successful, otherwise an OFPERR_* value. */
1049 enum ofperr
1050 ofputil_decode_table_mod(const struct ofp_header *oh,
1051 struct ofputil_table_mod *pm)
1052 {
1053 memset(pm, 0, sizeof *pm);
1054 pm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
1055 pm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
1056 pm->eviction_flags = UINT32_MAX;
1057 pm->vacancy = OFPUTIL_TABLE_VACANCY_DEFAULT;
1058
1059 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1060 enum ofpraw raw = ofpraw_pull_assert(&b);
1061 if (raw == OFPRAW_OFPT11_TABLE_MOD) {
1062 const struct ofp11_table_mod *otm = b.data;
1063
1064 pm->table_id = otm->table_id;
1065 pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
1066 } else if (raw == OFPRAW_OFPT14_TABLE_MOD) {
1067 const struct ofp14_table_mod *otm = ofpbuf_pull(&b, sizeof *otm);
1068
1069 pm->table_id = otm->table_id;
1070 pm->miss = ofputil_decode_table_miss(otm->config, oh->version);
1071 pm->eviction = ofputil_decode_table_eviction(otm->config, oh->version);
1072 pm->vacancy = ofputil_decode_table_vacancy(otm->config, oh->version);
1073 while (b.size > 0) {
1074 struct ofpbuf property;
1075 enum ofperr error;
1076 uint64_t type;
1077
1078 error = ofpprop_pull(&b, &property, &type);
1079 if (error) {
1080 return error;
1081 }
1082
1083 switch (type) {
1084 case OFPTMPT14_EVICTION:
1085 error = ofpprop_parse_u32(&property, &pm->eviction);
1086 break;
1087
1088 case OFPTMPT14_VACANCY:
1089 error = parse_table_mod_vacancy_property(&property, pm);
1090 break;
1091
1092 default:
1093 error = OFPERR_OFPBRC_BAD_TYPE;
1094 break;
1095 }
1096
1097 if (error) {
1098 return error;
1099 }
1100 }
1101 } else {
1102 return OFPERR_OFPBRC_BAD_TYPE;
1103 }
1104
1105 return 0;
1106 }
1107
1108 /* Converts the abstract form of a "table mod" message in '*tm' into an
1109 * OpenFlow message suitable for 'protocol', and returns that encoded form in a
1110 * buffer owned by the caller. */
1111 struct ofpbuf *
1112 ofputil_encode_table_mod(const struct ofputil_table_mod *tm,
1113 enum ofputil_protocol protocol)
1114 {
1115 enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
1116 struct ofpbuf *b;
1117
1118 switch (ofp_version) {
1119 case OFP10_VERSION: {
1120 ovs_fatal(0, "table mod needs OpenFlow 1.1 or later "
1121 "(\'-O OpenFlow11\')");
1122 break;
1123 }
1124 case OFP11_VERSION:
1125 case OFP12_VERSION:
1126 case OFP13_VERSION: {
1127 struct ofp11_table_mod *otm;
1128
1129 b = ofpraw_alloc(OFPRAW_OFPT11_TABLE_MOD, ofp_version, 0);
1130 otm = ofpbuf_put_zeros(b, sizeof *otm);
1131 otm->table_id = tm->table_id;
1132 otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
1133 tm->vacancy, ofp_version);
1134 break;
1135 }
1136 case OFP14_VERSION:
1137 case OFP15_VERSION: {
1138 struct ofp14_table_mod *otm;
1139
1140 b = ofpraw_alloc(OFPRAW_OFPT14_TABLE_MOD, ofp_version, 0);
1141 otm = ofpbuf_put_zeros(b, sizeof *otm);
1142 otm->table_id = tm->table_id;
1143 otm->config = ofputil_encode_table_config(tm->miss, tm->eviction,
1144 tm->vacancy, ofp_version);
1145
1146 if (tm->eviction_flags != UINT32_MAX) {
1147 ofpprop_put_u32(b, OFPTMPT14_EVICTION, tm->eviction_flags);
1148 }
1149 if (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
1150 struct ofp14_table_mod_prop_vacancy *otv;
1151
1152 otv = ofpprop_put_zeros(b, OFPTMPT14_VACANCY, sizeof *otv);
1153 otv->vacancy_down = tm->table_vacancy.vacancy_down;
1154 otv->vacancy_up = tm->table_vacancy.vacancy_up;
1155 }
1156 break;
1157 }
1158 default:
1159 OVS_NOT_REACHED();
1160 }
1161
1162 return b;
1163 }
1164
1165 void
1166 ofputil_table_mod_format(struct ds *s, const struct ofputil_table_mod *tm,
1167 const struct ofputil_table_map *table_map)
1168 {
1169 if (tm->table_id == 0xff) {
1170 ds_put_cstr(s, " table_id: ALL_TABLES");
1171 } else {
1172 ds_put_format(s, " table_id=");
1173 ofputil_format_table(tm->table_id, table_map, s);
1174 }
1175
1176 if (tm->miss != OFPUTIL_TABLE_MISS_DEFAULT) {
1177 ds_put_format(s, ", flow_miss_config=%s",
1178 ofputil_table_miss_to_string(tm->miss));
1179 }
1180 if (tm->eviction != OFPUTIL_TABLE_EVICTION_DEFAULT) {
1181 ds_put_format(s, ", eviction=%s",
1182 ofputil_table_eviction_to_string(tm->eviction));
1183 }
1184 if (tm->eviction_flags != UINT32_MAX) {
1185 ds_put_cstr(s, "eviction_flags=");
1186 ofputil_put_eviction_flags(s, tm->eviction_flags);
1187 }
1188 if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
1189 ds_put_format(s, ", vacancy=%s",
1190 ofputil_table_vacancy_to_string(tm->vacancy));
1191 if (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
1192 ds_put_format(s, " vacancy:%"PRIu8""
1193 ",%"PRIu8"", tm->table_vacancy.vacancy_down,
1194 tm->table_vacancy.vacancy_up);
1195 }
1196 }
1197 }
1198
1199 /* Convert 'setting' (as described for the "mod-table" command
1200 * in ovs-ofctl man page) into 'tm->table_vacancy->vacancy_up' and
1201 * 'tm->table_vacancy->vacancy_down' threshold values.
1202 * For the two threshold values, value of vacancy_up is always greater
1203 * than value of vacancy_down.
1204 *
1205 * Returns NULL if successful, otherwise a malloc()'d string describing the
1206 * error. The caller is responsible for freeing the returned string. */
1207 static char * OVS_WARN_UNUSED_RESULT
1208 parse_ofp_table_vacancy(struct ofputil_table_mod *tm, const char *setting)
1209 {
1210 char *save_ptr = NULL;
1211 char *vac_up, *vac_down;
1212 char *value = xstrdup(setting);
1213 char *ret_msg;
1214 int vacancy_up, vacancy_down;
1215
1216 strtok_r(value, ":", &save_ptr);
1217 vac_down = strtok_r(NULL, ",", &save_ptr);
1218 if (!vac_down) {
1219 ret_msg = xasprintf("Vacancy down value missing");
1220 goto exit;
1221 }
1222 if (!str_to_int(vac_down, 0, &vacancy_down) ||
1223 vacancy_down < 0 || vacancy_down > 100) {
1224 ret_msg = xasprintf("Invalid vacancy down value \"%s\"", vac_down);
1225 goto exit;
1226 }
1227 vac_up = strtok_r(NULL, ",", &save_ptr);
1228 if (!vac_up) {
1229 ret_msg = xasprintf("Vacancy up value missing");
1230 goto exit;
1231 }
1232 if (!str_to_int(vac_up, 0, &vacancy_up) ||
1233 vacancy_up < 0 || vacancy_up > 100) {
1234 ret_msg = xasprintf("Invalid vacancy up value \"%s\"", vac_up);
1235 goto exit;
1236 }
1237 if (vacancy_down > vacancy_up) {
1238 ret_msg = xasprintf("Invalid vacancy range, vacancy up should be "
1239 "greater than vacancy down (%s)",
1240 ofperr_to_string(OFPERR_OFPBPC_BAD_VALUE));
1241 goto exit;
1242 }
1243
1244 free(value);
1245 tm->table_vacancy.vacancy_down = vacancy_down;
1246 tm->table_vacancy.vacancy_up = vacancy_up;
1247 return NULL;
1248
1249 exit:
1250 free(value);
1251 return ret_msg;
1252 }
1253
1254 /* Convert 'table_id' and 'setting' (as described for the "mod-table" command
1255 * in the ovs-ofctl man page) into 'tm' for sending a table_mod command to a
1256 * switch. If 'setting' sets the name of the table, puts the new name in
1257 * '*namep' (a suffix of 'setting'), otherwise stores NULL.
1258 *
1259 * Stores a bitmap of the OpenFlow versions that are usable for 'tm' into
1260 * '*usable_versions'.
1261 *
1262 * Returns NULL if successful, otherwise a malloc()'d string describing the
1263 * error. The caller is responsible for freeing the returned string. */
1264 char * OVS_WARN_UNUSED_RESULT
1265 parse_ofp_table_mod(struct ofputil_table_mod *tm, const char **namep,
1266 const char *table_id, const char *setting,
1267 const struct ofputil_table_map *table_map,
1268 uint32_t *usable_versions)
1269 {
1270 *usable_versions = 0;
1271 *namep = NULL;
1272 if (!strcasecmp(table_id, "all")) {
1273 tm->table_id = OFPTT_ALL;
1274 } else if (!ofputil_table_from_string(table_id, table_map,
1275 &tm->table_id)) {
1276 return xasprintf("unknown table \"%s\"", table_id);
1277 }
1278
1279 tm->miss = OFPUTIL_TABLE_MISS_DEFAULT;
1280 tm->eviction = OFPUTIL_TABLE_EVICTION_DEFAULT;
1281 tm->eviction_flags = UINT32_MAX;
1282 tm->vacancy = OFPUTIL_TABLE_VACANCY_DEFAULT;
1283 tm->table_vacancy.vacancy_down = 0;
1284 tm->table_vacancy.vacancy_up = 0;
1285 tm->table_vacancy.vacancy = 0;
1286 /* Only OpenFlow 1.1 and 1.2 can configure table-miss via table_mod.
1287 * Only OpenFlow 1.4+ can configure eviction and vacancy events
1288 * via table_mod.
1289 */
1290 if (!strcmp(setting, "controller")) {
1291 tm->miss = OFPUTIL_TABLE_MISS_CONTROLLER;
1292 *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
1293 } else if (!strcmp(setting, "continue")) {
1294 tm->miss = OFPUTIL_TABLE_MISS_CONTINUE;
1295 *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
1296 } else if (!strcmp(setting, "drop")) {
1297 tm->miss = OFPUTIL_TABLE_MISS_DROP;
1298 *usable_versions = (1u << OFP11_VERSION) | (1u << OFP12_VERSION);
1299 } else if (!strcmp(setting, "evict")) {
1300 tm->eviction = OFPUTIL_TABLE_EVICTION_ON;
1301 *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
1302 } else if (!strcmp(setting, "noevict")) {
1303 tm->eviction = OFPUTIL_TABLE_EVICTION_OFF;
1304 *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
1305 } else if (!strncmp(setting, "vacancy", strcspn(setting, ":"))) {
1306 tm->vacancy = OFPUTIL_TABLE_VACANCY_ON;
1307 *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
1308 char *error = parse_ofp_table_vacancy(tm, setting);
1309 if (error) {
1310 return error;
1311 }
1312 } else if (!strcmp(setting, "novacancy")) {
1313 tm->vacancy = OFPUTIL_TABLE_VACANCY_OFF;
1314 *usable_versions = (1 << OFP14_VERSION) | (1u << OFP15_VERSION);
1315 } else if (tm->table_id != OFPTT_ALL && !strncmp(setting, "name:", 5)) {
1316 *namep = setting + 5;
1317 *usable_versions = ((1 << OFP13_VERSION) | (1u << OFP14_VERSION)
1318 | (1u << OFP15_VERSION));
1319 } else {
1320 return xasprintf("invalid table_mod setting %s", setting);
1321 }
1322
1323 if (tm->table_id == 0xfe
1324 && tm->miss == OFPUTIL_TABLE_MISS_CONTINUE) {
1325 return xstrdup("last table's flow miss handling can not be continue");
1326 }
1327
1328 return NULL;
1329 }
1330
1331 /* Returns true if 's' consists of only ASCII digits (and at least one). */
1332 static bool
1333 is_all_digits(const char *s)
1334 {
1335 return s[0] && s[strspn(s, "0123456789")] == '\0';
1336 }
1337
1338 /* Returns true if 'a' and 'b' are the same except 'b' ends in a number one
1339 * larger than 'a', for example, "reg0" and "reg1" */
1340 static bool
1341 are_names_sequential(const char *a, const char *b)
1342 {
1343 /* Skip common prefix. */
1344 for (; *a == *b; a++, b++) {
1345 if (!*a) {
1346 /* 'a' and 'b' are the same. Weird, but not sequential. */
1347 return false;
1348 }
1349 }
1350
1351 return (is_all_digits(a)
1352 && is_all_digits(b)
1353 && strlen(a) < 10
1354 && strlen(b) < 10
1355 && atoi(a) + 1 == atoi(b));
1356 }
1357
1358 /* Returns the number of sequential names at the start of the 'n' strings in
1359 * 'ids'. Returns at least 1 (if 'n' > 0). */
1360 static size_t
1361 count_sequential_suffix_run(const char *ids[], size_t n)
1362 {
1363 for (size_t i = 1; ; i++) {
1364 if (i >= n || !are_names_sequential(ids[i - 1], ids[i])) {
1365 /* "x0...x1" is worse than "x0 x1", so suppress it. */
1366 return i == 2 ? 1 : i;
1367 }
1368 }
1369 }
1370
1371 /* Counts the length of the longest common prefix (that ends in "_") between
1372 * strings 'a' and 'b'. Returns 0 if they have no common prefix. */
1373 static size_t
1374 count_common_prefix(const char *a, const char *b)
1375 {
1376 size_t retval = 0;
1377 for (size_t i = 0; ; i++) {
1378 if (a[i] != b[i] || !a[i]) {
1379 return retval;
1380 } else if (a[i] == '_') {
1381 retval = i + 1;
1382 }
1383 }
1384 }
1385
1386 /* Returns the number of strings in the longest run of strings with a common
1387 * prefix (that ends in "_") at the beginning of the 'n' strings in 'ids'.
1388 * This is at least 1, if 'n' > 0. All the strings are already known to have a
1389 * common prefix of length 'prefix_len', so that's not of interest; only an
1390 * additional common prefix is interesting.
1391 *
1392 * If this returns 'n' > 1, then '*extra_prefix_lenp' receives the length of
1393 * the additional common prefix. Otherwise '*extra_prefix_lenp' receives 0. */
1394 static size_t
1395 count_common_prefix_run(const char *ids[], size_t n,
1396 size_t prefix_len, size_t *extra_prefix_lenp)
1397 {
1398 *extra_prefix_lenp = 0;
1399 if (n < 2) {
1400 return n;
1401 }
1402
1403 size_t extra_prefix_len = count_common_prefix(ids[0] + prefix_len,
1404 ids[1] + prefix_len);
1405 if (!extra_prefix_len) {
1406 return 1;
1407 }
1408
1409 size_t i = 2;
1410 while (i < n) {
1411 size_t next = count_common_prefix(ids[0] + prefix_len,
1412 ids[i] + prefix_len);
1413 if (!next) {
1414 break;
1415 } else if (next < extra_prefix_len) {
1416 next = extra_prefix_len;
1417 }
1418 i++;
1419 }
1420 *extra_prefix_lenp = extra_prefix_len;
1421 return i;
1422 }
1423
1424 /* Appends the 'n' names in 'ids' to 's', omitting the first 'prefix_len' bytes
1425 * of each name (which should all be the same), separating them from each other
1426 * with spaces.
1427 *
1428 * Two kinds of abbreviation are implemented:
1429 *
1430 * - Common prefixes: "eth_src eth_dst eth_type" => "eth_{src,dst,type}".
1431 *
1432 * - Sequential suffixes: "reg0 reg1 reg2 reg3" => "reg0...reg3".
1433 */
1434 static void
1435 print_names(struct ds *s, const char *ids[], size_t n, size_t prefix_len)
1436 {
1437 int group = 0;
1438 while (n > 0) {
1439 if (group++) {
1440 ds_put_char(s, prefix_len ? ',' : ' ');
1441 }
1442
1443 /* Count the prefix and suffix runs at the beginning of 'ids'. As of
1444 * this writing we don't have any sequentially numbered fields whose
1445 * names contain "_", so we should only have one or the other at a
1446 * time. However, if we end up with something like "a_0 a_1 a_2"
1447 * someday, we want to render it as a_0...a_2, not as a_{0...2}, so
1448 * given equal suffix and prefix runs, prefer the suffix. */
1449 size_t extra_prefix_len;
1450 size_t prefix_run = count_common_prefix_run(ids, n, prefix_len,
1451 &extra_prefix_len);
1452 size_t suffix_run = count_sequential_suffix_run(ids, n);
1453 size_t run = MAX(prefix_run, suffix_run);
1454 if (suffix_run >= prefix_run) {
1455 ds_put_format(s, "%s", ids[0] + prefix_len);
1456 if (run > 1) {
1457 ds_put_format(s, "...%s", ids[run - 1] + prefix_len);
1458 }
1459 } else {
1460 ds_put_format(s, "%.*s{", (int) extra_prefix_len,
1461 ids[0] + prefix_len);
1462 print_names(s, ids, run, prefix_len + extra_prefix_len);
1463 ds_put_char(s, '}');
1464 }
1465
1466 ids += run;
1467 n -= run;
1468 }
1469 }
1470
1471 static void
1472 print_mf_bitmap(struct ds *s, const struct mf_bitmap *mfb)
1473 {
1474 const char *ids[MFF_N_IDS];
1475 size_t n = 0;
1476
1477 int i;
1478 BITMAP_FOR_EACH_1 (i, MFF_N_IDS, mfb->bm) {
1479 ids[n++] = mf_from_id(i)->name;
1480 }
1481
1482 if (n > 0) {
1483 ds_put_char(s, ' ');
1484 print_names(s, ids, n, 0);
1485 }
1486 }
1487
1488 static void
1489 print_table_action_features(struct ds *s,
1490 const struct ofputil_table_action_features *taf)
1491 {
1492 if (taf->ofpacts) {
1493 ds_put_cstr(s, " actions: ");
1494 ofpact_bitmap_format(taf->ofpacts, s);
1495 ds_put_char(s, '\n');
1496 }
1497
1498 if (!bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS)) {
1499 ds_put_cstr(s, " supported on Set-Field:");
1500 print_mf_bitmap(s, &taf->set_fields);
1501 ds_put_char(s, '\n');
1502 }
1503 }
1504
1505 static bool
1506 table_action_features_equal(const struct ofputil_table_action_features *a,
1507 const struct ofputil_table_action_features *b)
1508 {
1509 return (a->ofpacts == b->ofpacts
1510 && bitmap_equal(a->set_fields.bm, b->set_fields.bm, MFF_N_IDS));
1511 }
1512
1513 static bool
1514 table_action_features_empty(const struct ofputil_table_action_features *taf)
1515 {
1516 return !taf->ofpacts && bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS);
1517 }
1518
1519 static void
1520 print_table_instruction_features(
1521 struct ds *s,
1522 const struct ofputil_table_instruction_features *tif,
1523 const struct ofputil_table_instruction_features *prev_tif)
1524 {
1525 int start, end;
1526
1527 if (!bitmap_is_all_zeros(tif->next, 255)) {
1528 ds_put_cstr(s, " next tables: ");
1529 for (start = bitmap_scan(tif->next, 1, 0, 255); start < 255;
1530 start = bitmap_scan(tif->next, 1, end, 255)) {
1531 end = bitmap_scan(tif->next, 0, start + 1, 255);
1532 if (end == start + 1) {
1533 ds_put_format(s, "%d,", start);
1534 } else {
1535 ds_put_format(s, "%d-%d,", start, end - 1);
1536 }
1537 }
1538 ds_chomp(s, ',');
1539 if (ds_last(s) == ' ') {
1540 ds_put_cstr(s, "none");
1541 }
1542 ds_put_char(s, '\n');
1543 }
1544
1545 if (tif->instructions) {
1546 if (prev_tif && tif->instructions == prev_tif->instructions) {
1547 ds_put_cstr(s, " (same instructions)\n");
1548 } else {
1549 ds_put_cstr(s, " instructions: ");
1550 int i;
1551
1552 for (i = 0; i < 32; i++) {
1553 if (tif->instructions & (1u << i)) {
1554 const char *name = ovs_instruction_name_from_type(i);
1555 if (name) {
1556 ds_put_cstr(s, name);
1557 } else {
1558 ds_put_format(s, "%d", i);
1559 }
1560 ds_put_char(s, ' ');
1561 }
1562 }
1563 ds_chomp(s, ' ');
1564 ds_put_char(s, '\n');
1565 }
1566 }
1567
1568 if (prev_tif
1569 && table_action_features_equal(&tif->write, &prev_tif->write)
1570 && table_action_features_equal(&tif->apply, &prev_tif->apply)
1571 && !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
1572 ds_put_cstr(s, " (same actions)\n");
1573 } else if (!table_action_features_equal(&tif->write, &tif->apply)) {
1574 ds_put_cstr(s, " Write-Actions features:\n");
1575 print_table_action_features(s, &tif->write);
1576 ds_put_cstr(s, " Apply-Actions features:\n");
1577 print_table_action_features(s, &tif->apply);
1578 } else if (tif->write.ofpacts
1579 || !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
1580 ds_put_cstr(s, " Write-Actions and Apply-Actions features:\n");
1581 print_table_action_features(s, &tif->write);
1582 }
1583 }
1584
1585 static void
1586 print_matches(struct ds *s, const struct ofputil_table_features *f,
1587 bool mask, bool wc, const char *title)
1588 {
1589 const struct mf_bitmap m = mask ? f->mask : mf_bitmap_not(f->mask);
1590 const struct mf_bitmap w = wc ? f->wildcard : mf_bitmap_not(f->wildcard);
1591 const struct mf_bitmap bm = mf_bitmap_and(f->match, mf_bitmap_and(m, w));
1592
1593 if (!bitmap_is_all_zeros(bm.bm, MFF_N_IDS)) {
1594 ds_put_format(s, " %s:", title);
1595 print_mf_bitmap(s, &bm);
1596 ds_put_char(s, '\n');
1597 }
1598 }
1599
1600 /* Compares bitmaps of next tables 'a' and 'b', for tables 'a_table_id' and
1601 * 'b_table_id', respectively. Returns true if the bitmaps are equal.
1602 *
1603 * The bitmaps are considered equal if b_table_id == a_table_id + 1 and the bit
1604 * for 'b_table_id' is set in 'a' but not in 'b'. This is because OpenFlow
1605 * requires that a table not be able to do a goto_table back to its own table
1606 * or an earlier one. Without considering these equivalent, every table will
1607 * be different from every one in some way, which just isn't useful in printing
1608 * table features. */
1609 static bool
1610 table_instruction_features_next_equal(const unsigned long *a, int a_table_id,
1611 const unsigned long *b, int b_table_id)
1612 {
1613 if (b_table_id == a_table_id + 1
1614 && bitmap_is_set(a, b_table_id)
1615 && !bitmap_is_set(b, b_table_id)) {
1616 for (size_t i = 0; i < BITMAP_N_LONGS(255); i++) {
1617 unsigned long diff = a[i] ^ b[i];
1618 if (i == b_table_id / BITMAP_ULONG_BITS) {
1619 diff &= ~bitmap_bit__(b_table_id);
1620 }
1621 if (diff) {
1622 return false;
1623 }
1624 }
1625 return true;
1626 } else if (a_table_id == b_table_id + 1) {
1627 return table_instruction_features_next_equal(b, b_table_id,
1628 a, a_table_id);
1629 } else {
1630 return bitmap_equal(a, b, 255);
1631 }
1632 }
1633
1634 static bool
1635 table_instruction_features_equal(
1636 const struct ofputil_table_instruction_features *a, int a_table_id,
1637 const struct ofputil_table_instruction_features *b, int b_table_id)
1638 {
1639 return (table_instruction_features_next_equal(a->next, a_table_id,
1640 b->next, b_table_id)
1641 && a->instructions == b->instructions
1642 && table_action_features_equal(&a->write, &b->write)
1643 && table_action_features_equal(&a->apply, &b->apply));
1644 }
1645
1646 static bool
1647 table_instruction_features_empty(
1648 const struct ofputil_table_instruction_features *tif)
1649 {
1650 return (bitmap_is_all_zeros(tif->next, 255)
1651 && !tif->instructions
1652 && table_action_features_empty(&tif->write)
1653 && table_action_features_empty(&tif->apply));
1654 }
1655
1656 static bool
1657 table_features_equal(const struct ofputil_table_features *a,
1658 const struct ofputil_table_features *b)
1659 {
1660 return (a->metadata_match == b->metadata_match
1661 && a->metadata_write == b->metadata_write
1662 && a->miss_config == b->miss_config
1663 && a->supports_eviction == b->supports_eviction
1664 && a->supports_vacancy_events == b->supports_vacancy_events
1665 && a->max_entries == b->max_entries
1666 && table_instruction_features_equal(&a->nonmiss, a->table_id,
1667 &b->nonmiss, b->table_id)
1668 && table_instruction_features_equal(&a->miss, a->table_id,
1669 &b->miss, b->table_id)
1670 && bitmap_equal(a->match.bm, b->match.bm, MFF_N_IDS));
1671 }
1672
1673 static bool
1674 table_features_empty(const struct ofputil_table_features *tf)
1675 {
1676 return (!tf->metadata_match
1677 && !tf->metadata_write
1678 && tf->miss_config == OFPUTIL_TABLE_MISS_DEFAULT
1679 && tf->supports_eviction < 0
1680 && tf->supports_vacancy_events < 0
1681 && !tf->max_entries
1682 && table_instruction_features_empty(&tf->nonmiss)
1683 && table_instruction_features_empty(&tf->miss)
1684 && bitmap_is_all_zeros(tf->match.bm, MFF_N_IDS));
1685 }
1686
1687 static bool
1688 table_stats_equal(const struct ofputil_table_stats *a,
1689 const struct ofputil_table_stats *b)
1690 {
1691 return (a->active_count == b->active_count
1692 && a->lookup_count == b->lookup_count
1693 && a->matched_count == b->matched_count);
1694 }
1695
1696 void
1697 ofputil_table_features_format(
1698 struct ds *s,
1699 const struct ofputil_table_features *features,
1700 const struct ofputil_table_features *prev_features,
1701 const struct ofputil_table_stats *stats,
1702 const struct ofputil_table_stats *prev_stats,
1703 int *first_ditto, int *last_ditto)
1704 {
1705 if (!prev_features && features->command != OFPTFC15_REPLACE) {
1706 ds_put_format(s, "\n command: %s",
1707 ofp15_table_features_command_to_string(
1708 features->command));
1709 }
1710
1711 int table = features->table_id;
1712 int prev_table = prev_features ? prev_features->table_id : 0;
1713
1714 bool same_stats = !stats || (prev_stats
1715 && table_stats_equal(stats, prev_stats));
1716 bool same_features = prev_features && table_features_equal(features,
1717 prev_features);
1718 if (same_stats && same_features && !features->name[0]) {
1719 if (*first_ditto < 0) {
1720 *first_ditto = table;
1721 }
1722 *last_ditto = table;
1723 return;
1724 }
1725 ofputil_table_features_format_finish(s, *first_ditto, *last_ditto);
1726 *first_ditto = -1;
1727
1728 ds_put_format(s, "\n table %d", table);
1729 if (features->name[0]) {
1730 ds_put_format(s, " (\"%s\")", features->name);
1731 }
1732 ds_put_char(s, ':');
1733
1734 if (same_stats && same_features) {
1735 ds_put_cstr(s, " ditto");
1736 return;
1737 }
1738 ds_put_char(s, '\n');
1739 if (stats) {
1740 ds_put_format(s, " active=%"PRIu32", ", stats->active_count);
1741 ds_put_format(s, "lookup=%"PRIu64", ", stats->lookup_count);
1742 ds_put_format(s, "matched=%"PRIu64"\n", stats->matched_count);
1743 }
1744 if (same_features) {
1745 if (!table_features_empty(features)) {
1746 ds_put_cstr(s, " (same features)\n");
1747 }
1748 return;
1749 }
1750 if (features->metadata_match || features->metadata_write) {
1751 ds_put_format(s, " metadata: match=%#"PRIx64" write=%#"PRIx64"\n",
1752 ntohll(features->metadata_match),
1753 ntohll(features->metadata_write));
1754 }
1755
1756 if (features->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
1757 ds_put_format(s, " config=%s\n",
1758 ofputil_table_miss_to_string(features->miss_config));
1759 }
1760
1761 if (features->supports_eviction >= 0) {
1762 ds_put_format(s, " eviction: %ssupported\n",
1763 features->supports_eviction ? "" : "not ");
1764
1765 }
1766 if (features->supports_vacancy_events >= 0) {
1767 ds_put_format(s, " vacancy events: %ssupported\n",
1768 features->supports_vacancy_events ? "" : "not ");
1769
1770 }
1771
1772 if (features->max_entries) {
1773 ds_put_format(s, " max_entries=%"PRIu32"\n", features->max_entries);
1774 }
1775
1776 const struct ofputil_table_instruction_features *prev_nonmiss
1777 = prev_features ? &prev_features->nonmiss : NULL;
1778 const struct ofputil_table_instruction_features *prev_miss
1779 = prev_features ? &prev_features->miss : NULL;
1780 if (prev_features
1781 && table_instruction_features_equal(&features->nonmiss, table,
1782 prev_nonmiss, prev_table)
1783 && table_instruction_features_equal(&features->miss, table,
1784 prev_miss, prev_table)) {
1785 if (!table_instruction_features_empty(&features->nonmiss)) {
1786 ds_put_cstr(s, " (same instructions)\n");
1787 }
1788 } else if (!table_instruction_features_equal(&features->nonmiss, table,
1789 &features->miss, table)) {
1790 ds_put_cstr(s, " instructions (other than table miss):\n");
1791 print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
1792 ds_put_cstr(s, " instructions (table miss):\n");
1793 print_table_instruction_features(s, &features->miss, prev_miss);
1794 } else if (!table_instruction_features_empty(&features->nonmiss)) {
1795 ds_put_cstr(s, " instructions (table miss and others):\n");
1796 print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
1797 }
1798
1799 if (!bitmap_is_all_zeros(features->match.bm, MFF_N_IDS)) {
1800 if (prev_features
1801 && bitmap_equal(features->match.bm, prev_features->match.bm,
1802 MFF_N_IDS)) {
1803 ds_put_cstr(s, " (same matching)\n");
1804 } else {
1805 ds_put_cstr(s, " matching:\n");
1806
1807 print_matches(s, features, true, true, "arbitrary mask");
1808 print_matches(s, features, false, true, "exact match or wildcard");
1809 print_matches(s, features, false, false, "must exact match");
1810 }
1811 }
1812 }
1813
1814 void
1815 ofputil_table_features_format_finish(struct ds *s,
1816 int first_ditto, int last_ditto)
1817 {
1818 if (first_ditto < 0) {
1819 return;
1820 }
1821
1822 ds_put_char(s, '\n');
1823 if (first_ditto == last_ditto) {
1824 ds_put_format(s, " table %d: ditto\n", first_ditto);
1825 } else {
1826 ds_put_format(s, " tables %d...%d: ditto\n", first_ditto, last_ditto);
1827 }
1828 }
1829
1830 /* Returns true if 'super' is a superset of 'sub', false otherwise. */
1831 static bool
1832 ofputil_table_action_features_is_superset(
1833 const struct ofputil_table_action_features *super,
1834 const struct ofputil_table_action_features *sub)
1835 {
1836 return (uint_is_superset(super->ofpacts, sub->ofpacts)
1837 && mf_bitmap_is_superset(&super->set_fields, &sub->set_fields));
1838 }
1839
1840 /* Returns true if 'super' is a superset of 'sub', false otherwise. */
1841 static bool
1842 ofputil_table_instruction_features_is_superset(
1843 const struct ofputil_table_instruction_features *super,
1844 const struct ofputil_table_instruction_features *sub)
1845 {
1846 return (bitmap_is_superset(super->next, sub->next, 255)
1847 && uint_is_superset(super->instructions, sub->instructions)
1848 && ofputil_table_action_features_is_superset(&super->write,
1849 &sub->write)
1850 && ofputil_table_action_features_is_superset(&super->apply,
1851 &sub->apply));
1852 }
1853
1854 /* Returns true if 'super' is a superset of 'sub', false otherwise. */
1855 bool
1856 ofputil_table_features_are_superset(
1857 const struct ofputil_table_features *super,
1858 const struct ofputil_table_features *sub)
1859 {
1860 return (be64_is_superset(super->metadata_match, sub->metadata_match)
1861 && be64_is_superset(super->metadata_write, sub->metadata_write)
1862 && super->max_entries >= sub->max_entries
1863 && super->supports_eviction >= sub->supports_eviction
1864 && super->supports_vacancy_events >= sub->supports_vacancy_events
1865 && ofputil_table_instruction_features_is_superset(&super->nonmiss,
1866 &sub->nonmiss)
1867 && ofputil_table_instruction_features_is_superset(&super->miss,
1868 &sub->miss)
1869 && mf_bitmap_is_superset(&super->match, &sub->match)
1870 && mf_bitmap_is_superset(&super->mask, &sub->mask)
1871 && mf_bitmap_is_superset(&super->wildcard, &sub->wildcard));
1872 }
1873 \f
1874 /* Table stats. */
1875
1876 /* OpenFlow 1.0 and 1.1 don't distinguish between a field that cannot be
1877 * matched and a field that must be wildcarded. This function returns a bitmap
1878 * that contains both kinds of fields. */
1879 static struct mf_bitmap
1880 wild_or_nonmatchable_fields(const struct ofputil_table_features *features)
1881 {
1882 struct mf_bitmap wc = features->match;
1883 bitmap_not(wc.bm, MFF_N_IDS);
1884 bitmap_or(wc.bm, features->wildcard.bm, MFF_N_IDS);
1885 return wc;
1886 }
1887
1888 struct ofp10_wc_map {
1889 enum ofp10_flow_wildcards wc10;
1890 enum mf_field_id mf;
1891 };
1892
1893 static const struct ofp10_wc_map ofp10_wc_map[] = {
1894 { OFPFW10_IN_PORT, MFF_IN_PORT },
1895 { OFPFW10_DL_VLAN, MFF_VLAN_VID },
1896 { OFPFW10_DL_SRC, MFF_ETH_SRC },
1897 { OFPFW10_DL_DST, MFF_ETH_DST},
1898 { OFPFW10_DL_TYPE, MFF_ETH_TYPE },
1899 { OFPFW10_NW_PROTO, MFF_IP_PROTO },
1900 { OFPFW10_TP_SRC, MFF_TCP_SRC },
1901 { OFPFW10_TP_DST, MFF_TCP_DST },
1902 { OFPFW10_NW_SRC_MASK, MFF_IPV4_SRC },
1903 { OFPFW10_NW_DST_MASK, MFF_IPV4_DST },
1904 { OFPFW10_DL_VLAN_PCP, MFF_VLAN_PCP },
1905 { OFPFW10_NW_TOS, MFF_IP_DSCP },
1906 };
1907
1908 static ovs_be32
1909 mf_bitmap_to_of10(const struct mf_bitmap *fields)
1910 {
1911 const struct ofp10_wc_map *p;
1912 uint32_t wc10 = 0;
1913
1914 for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
1915 if (bitmap_is_set(fields->bm, p->mf)) {
1916 wc10 |= p->wc10;
1917 }
1918 }
1919 return htonl(wc10);
1920 }
1921
1922 static struct mf_bitmap
1923 mf_bitmap_from_of10(ovs_be32 wc10_)
1924 {
1925 struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
1926 const struct ofp10_wc_map *p;
1927 uint32_t wc10 = ntohl(wc10_);
1928
1929 for (p = ofp10_wc_map; p < &ofp10_wc_map[ARRAY_SIZE(ofp10_wc_map)]; p++) {
1930 if (wc10 & p->wc10) {
1931 bitmap_set1(fields.bm, p->mf);
1932 }
1933 }
1934 return fields;
1935 }
1936
1937 static void
1938 ofputil_put_ofp10_table_stats(const struct ofputil_table_stats *stats,
1939 const struct ofputil_table_features *features,
1940 struct ofpbuf *buf)
1941 {
1942 struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
1943 struct ofp10_table_stats *out;
1944
1945 out = ofpbuf_put_zeros(buf, sizeof *out);
1946 out->table_id = features->table_id;
1947 ovs_strlcpy_arrays(out->name, features->name);
1948 out->wildcards = mf_bitmap_to_of10(&wc);
1949 out->max_entries = htonl(features->max_entries);
1950 out->active_count = htonl(stats->active_count);
1951 put_32aligned_be64(&out->lookup_count, htonll(stats->lookup_count));
1952 put_32aligned_be64(&out->matched_count, htonll(stats->matched_count));
1953 }
1954
1955 struct ofp11_wc_map {
1956 enum ofp11_flow_match_fields wc11;
1957 enum mf_field_id mf;
1958 };
1959
1960 static const struct ofp11_wc_map ofp11_wc_map[] = {
1961 { OFPFMF11_IN_PORT, MFF_IN_PORT },
1962 { OFPFMF11_DL_VLAN, MFF_VLAN_VID },
1963 { OFPFMF11_DL_VLAN_PCP, MFF_VLAN_PCP },
1964 { OFPFMF11_DL_TYPE, MFF_ETH_TYPE },
1965 { OFPFMF11_NW_TOS, MFF_IP_DSCP },
1966 { OFPFMF11_NW_PROTO, MFF_IP_PROTO },
1967 { OFPFMF11_TP_SRC, MFF_TCP_SRC },
1968 { OFPFMF11_TP_DST, MFF_TCP_DST },
1969 { OFPFMF11_MPLS_LABEL, MFF_MPLS_LABEL },
1970 { OFPFMF11_MPLS_TC, MFF_MPLS_TC },
1971 /* I don't know what OFPFMF11_TYPE means. */
1972 { OFPFMF11_DL_SRC, MFF_ETH_SRC },
1973 { OFPFMF11_DL_DST, MFF_ETH_DST },
1974 { OFPFMF11_NW_SRC, MFF_IPV4_SRC },
1975 { OFPFMF11_NW_DST, MFF_IPV4_DST },
1976 { OFPFMF11_METADATA, MFF_METADATA },
1977 };
1978
1979 static ovs_be32
1980 mf_bitmap_to_of11(const struct mf_bitmap *fields)
1981 {
1982 const struct ofp11_wc_map *p;
1983 uint32_t wc11 = 0;
1984
1985 for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
1986 if (bitmap_is_set(fields->bm, p->mf)) {
1987 wc11 |= p->wc11;
1988 }
1989 }
1990 return htonl(wc11);
1991 }
1992
1993 static struct mf_bitmap
1994 mf_bitmap_from_of11(ovs_be32 wc11_)
1995 {
1996 struct mf_bitmap fields = MF_BITMAP_INITIALIZER;
1997 const struct ofp11_wc_map *p;
1998 uint32_t wc11 = ntohl(wc11_);
1999
2000 for (p = ofp11_wc_map; p < &ofp11_wc_map[ARRAY_SIZE(ofp11_wc_map)]; p++) {
2001 if (wc11 & p->wc11) {
2002 bitmap_set1(fields.bm, p->mf);
2003 }
2004 }
2005 return fields;
2006 }
2007
2008 static void
2009 ofputil_put_ofp11_table_stats(const struct ofputil_table_stats *stats,
2010 const struct ofputil_table_features *features,
2011 struct ofpbuf *buf)
2012 {
2013 struct mf_bitmap wc = wild_or_nonmatchable_fields(features);
2014 struct ofp11_table_stats *out;
2015
2016 out = ofpbuf_put_zeros(buf, sizeof *out);
2017 out->table_id = features->table_id;
2018 ovs_strlcpy_arrays(out->name, features->name);
2019 out->wildcards = mf_bitmap_to_of11(&wc);
2020 out->match = mf_bitmap_to_of11(&features->match);
2021 out->instructions = ovsinst_bitmap_to_openflow(
2022 features->nonmiss.instructions, OFP11_VERSION);
2023 out->write_actions = ofpact_bitmap_to_openflow(
2024 features->nonmiss.write.ofpacts, OFP11_VERSION);
2025 out->apply_actions = ofpact_bitmap_to_openflow(
2026 features->nonmiss.apply.ofpacts, OFP11_VERSION);
2027 out->config = htonl(features->miss_config);
2028 out->max_entries = htonl(features->max_entries);
2029 out->active_count = htonl(stats->active_count);
2030 out->lookup_count = htonll(stats->lookup_count);
2031 out->matched_count = htonll(stats->matched_count);
2032 }
2033
2034 static void
2035 ofputil_put_ofp12_table_stats(const struct ofputil_table_stats *stats,
2036 const struct ofputil_table_features *features,
2037 struct ofpbuf *buf)
2038 {
2039 struct ofp12_table_stats *out;
2040
2041 out = ofpbuf_put_zeros(buf, sizeof *out);
2042 out->table_id = features->table_id;
2043 ovs_strlcpy_arrays(out->name, features->name);
2044 out->match = oxm_bitmap_from_mf_bitmap(&features->match, OFP12_VERSION);
2045 out->wildcards = oxm_bitmap_from_mf_bitmap(&features->wildcard,
2046 OFP12_VERSION);
2047 out->write_actions = ofpact_bitmap_to_openflow(
2048 features->nonmiss.write.ofpacts, OFP12_VERSION);
2049 out->apply_actions = ofpact_bitmap_to_openflow(
2050 features->nonmiss.apply.ofpacts, OFP12_VERSION);
2051 out->write_setfields = oxm_bitmap_from_mf_bitmap(
2052 &features->nonmiss.write.set_fields, OFP12_VERSION);
2053 out->apply_setfields = oxm_bitmap_from_mf_bitmap(
2054 &features->nonmiss.apply.set_fields, OFP12_VERSION);
2055 out->metadata_match = features->metadata_match;
2056 out->metadata_write = features->metadata_write;
2057 out->instructions = ovsinst_bitmap_to_openflow(
2058 features->nonmiss.instructions, OFP12_VERSION);
2059 out->config = ofputil_encode_table_config(features->miss_config,
2060 OFPUTIL_TABLE_EVICTION_DEFAULT,
2061 OFPUTIL_TABLE_VACANCY_DEFAULT,
2062 OFP12_VERSION);
2063 out->max_entries = htonl(features->max_entries);
2064 out->active_count = htonl(stats->active_count);
2065 out->lookup_count = htonll(stats->lookup_count);
2066 out->matched_count = htonll(stats->matched_count);
2067 }
2068
2069 static void
2070 ofputil_put_ofp13_table_stats(const struct ofputil_table_stats *stats,
2071 struct ofpbuf *buf)
2072 {
2073 struct ofp13_table_stats *out;
2074
2075 out = ofpbuf_put_zeros(buf, sizeof *out);
2076 out->table_id = stats->table_id;
2077 out->active_count = htonl(stats->active_count);
2078 out->lookup_count = htonll(stats->lookup_count);
2079 out->matched_count = htonll(stats->matched_count);
2080 }
2081
2082 struct ofpbuf *
2083 ofputil_encode_table_stats_reply(const struct ofp_header *request)
2084 {
2085 return ofpraw_alloc_stats_reply(request, 0);
2086 }
2087
2088 void
2089 ofputil_append_table_stats_reply(struct ofpbuf *reply,
2090 const struct ofputil_table_stats *stats,
2091 const struct ofputil_table_features *features)
2092 {
2093 struct ofp_header *oh = reply->header;
2094
2095 ovs_assert(stats->table_id == features->table_id);
2096
2097 switch ((enum ofp_version) oh->version) {
2098 case OFP10_VERSION:
2099 ofputil_put_ofp10_table_stats(stats, features, reply);
2100 break;
2101
2102 case OFP11_VERSION:
2103 ofputil_put_ofp11_table_stats(stats, features, reply);
2104 break;
2105
2106 case OFP12_VERSION:
2107 ofputil_put_ofp12_table_stats(stats, features, reply);
2108 break;
2109
2110 case OFP13_VERSION:
2111 case OFP14_VERSION:
2112 case OFP15_VERSION:
2113 ofputil_put_ofp13_table_stats(stats, reply);
2114 break;
2115
2116 default:
2117 OVS_NOT_REACHED();
2118 }
2119 }
2120
2121 static int
2122 ofputil_decode_ofp10_table_stats(struct ofpbuf *msg,
2123 struct ofputil_table_stats *stats,
2124 struct ofputil_table_features *features)
2125 {
2126 struct ofp10_table_stats *ots;
2127
2128 ots = ofpbuf_try_pull(msg, sizeof *ots);
2129 if (!ots) {
2130 return OFPERR_OFPBRC_BAD_LEN;
2131 }
2132
2133 features->table_id = ots->table_id;
2134 ovs_strlcpy_arrays(features->name, ots->name);
2135 features->max_entries = ntohl(ots->max_entries);
2136 features->match = features->wildcard = mf_bitmap_from_of10(ots->wildcards);
2137
2138 stats->table_id = ots->table_id;
2139 stats->active_count = ntohl(ots->active_count);
2140 stats->lookup_count = ntohll(get_32aligned_be64(&ots->lookup_count));
2141 stats->matched_count = ntohll(get_32aligned_be64(&ots->matched_count));
2142
2143 return 0;
2144 }
2145
2146 static int
2147 ofputil_decode_ofp11_table_stats(struct ofpbuf *msg,
2148 struct ofputil_table_stats *stats,
2149 struct ofputil_table_features *features)
2150 {
2151 struct ofp11_table_stats *ots;
2152
2153 ots = ofpbuf_try_pull(msg, sizeof *ots);
2154 if (!ots) {
2155 return OFPERR_OFPBRC_BAD_LEN;
2156 }
2157
2158 features->table_id = ots->table_id;
2159 ovs_strlcpy_arrays(features->name, ots->name);
2160 features->max_entries = ntohl(ots->max_entries);
2161 features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
2162 ots->instructions, OFP11_VERSION);
2163 features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
2164 ots->write_actions, OFP11_VERSION);
2165 features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
2166 ots->write_actions, OFP11_VERSION);
2167 features->miss = features->nonmiss;
2168 features->miss_config = ofputil_decode_table_miss(ots->config,
2169 OFP11_VERSION);
2170 features->match = mf_bitmap_from_of11(ots->match);
2171 features->wildcard = mf_bitmap_from_of11(ots->wildcards);
2172 bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);
2173
2174 stats->table_id = ots->table_id;
2175 stats->active_count = ntohl(ots->active_count);
2176 stats->lookup_count = ntohll(ots->lookup_count);
2177 stats->matched_count = ntohll(ots->matched_count);
2178
2179 return 0;
2180 }
2181
2182 static int
2183 ofputil_decode_ofp12_table_stats(struct ofpbuf *msg,
2184 struct ofputil_table_stats *stats,
2185 struct ofputil_table_features *features)
2186 {
2187 struct ofp12_table_stats *ots;
2188
2189 ots = ofpbuf_try_pull(msg, sizeof *ots);
2190 if (!ots) {
2191 return OFPERR_OFPBRC_BAD_LEN;
2192 }
2193
2194 features->table_id = ots->table_id;
2195 ovs_strlcpy_arrays(features->name, ots->name);
2196 features->metadata_match = ots->metadata_match;
2197 features->metadata_write = ots->metadata_write;
2198 features->miss_config = ofputil_decode_table_miss(ots->config,
2199 OFP12_VERSION);
2200 features->max_entries = ntohl(ots->max_entries);
2201
2202 features->nonmiss.instructions = ovsinst_bitmap_from_openflow(
2203 ots->instructions, OFP12_VERSION);
2204 features->nonmiss.write.ofpacts = ofpact_bitmap_from_openflow(
2205 ots->write_actions, OFP12_VERSION);
2206 features->nonmiss.apply.ofpacts = ofpact_bitmap_from_openflow(
2207 ots->apply_actions, OFP12_VERSION);
2208 features->nonmiss.write.set_fields = oxm_bitmap_to_mf_bitmap(
2209 ots->write_setfields, OFP12_VERSION);
2210 features->nonmiss.apply.set_fields = oxm_bitmap_to_mf_bitmap(
2211 ots->apply_setfields, OFP12_VERSION);
2212 features->miss = features->nonmiss;
2213
2214 features->match = oxm_bitmap_to_mf_bitmap(ots->match, OFP12_VERSION);
2215 features->wildcard = oxm_bitmap_to_mf_bitmap(ots->wildcards,
2216 OFP12_VERSION);
2217 bitmap_or(features->match.bm, features->wildcard.bm, MFF_N_IDS);
2218
2219 stats->table_id = ots->table_id;
2220 stats->active_count = ntohl(ots->active_count);
2221 stats->lookup_count = ntohll(ots->lookup_count);
2222 stats->matched_count = ntohll(ots->matched_count);
2223
2224 return 0;
2225 }
2226
2227 static int
2228 ofputil_decode_ofp13_table_stats(struct ofpbuf *msg,
2229 struct ofputil_table_stats *stats,
2230 struct ofputil_table_features *features)
2231 {
2232 struct ofp13_table_stats *ots;
2233
2234 ots = ofpbuf_try_pull(msg, sizeof *ots);
2235 if (!ots) {
2236 return OFPERR_OFPBRC_BAD_LEN;
2237 }
2238
2239 features->table_id = ots->table_id;
2240
2241 stats->table_id = ots->table_id;
2242 stats->active_count = ntohl(ots->active_count);
2243 stats->lookup_count = ntohll(ots->lookup_count);
2244 stats->matched_count = ntohll(ots->matched_count);
2245
2246 return 0;
2247 }
2248
2249 int
2250 ofputil_decode_table_stats_reply(struct ofpbuf *msg,
2251 struct ofputil_table_stats *stats,
2252 struct ofputil_table_features *features)
2253 {
2254 const struct ofp_header *oh;
2255
2256 if (!msg->header) {
2257 ofpraw_pull_assert(msg);
2258 }
2259 oh = msg->header;
2260
2261 if (!msg->size) {
2262 return EOF;
2263 }
2264
2265 memset(stats, 0, sizeof *stats);
2266 memset(features, 0, sizeof *features);
2267 features->supports_eviction = -1;
2268 features->supports_vacancy_events = -1;
2269
2270 switch ((enum ofp_version) oh->version) {
2271 case OFP10_VERSION:
2272 return ofputil_decode_ofp10_table_stats(msg, stats, features);
2273
2274 case OFP11_VERSION:
2275 return ofputil_decode_ofp11_table_stats(msg, stats, features);
2276
2277 case OFP12_VERSION:
2278 return ofputil_decode_ofp12_table_stats(msg, stats, features);
2279
2280 case OFP13_VERSION:
2281 case OFP14_VERSION:
2282 case OFP15_VERSION:
2283 return ofputil_decode_ofp13_table_stats(msg, stats, features);
2284
2285 default:
2286 OVS_NOT_REACHED();
2287 }
2288 }
2289 \f
2290 /* Returns a string form of 'reason'. The return value is either a statically
2291 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
2292 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
2293 const char *
2294 ofp_table_reason_to_string(enum ofp14_table_reason reason,
2295 char *reasonbuf, size_t bufsize)
2296 {
2297 switch (reason) {
2298 case OFPTR_VACANCY_DOWN:
2299 return "vacancy_down";
2300
2301 case OFPTR_VACANCY_UP:
2302 return "vacancy_up";
2303
2304 default:
2305 snprintf(reasonbuf, bufsize, "%d", (int) reason);
2306 return reasonbuf;
2307 }
2308 }
2309
2310 static void
2311 ofputil_put_ofp14_table_desc(const struct ofputil_table_desc *td,
2312 struct ofpbuf *b, enum ofp_version version)
2313 {
2314 struct ofp14_table_desc *otd;
2315 struct ofp14_table_mod_prop_vacancy *otv;
2316 size_t start_otd;
2317
2318 start_otd = b->size;
2319 ofpbuf_put_zeros(b, sizeof *otd);
2320
2321 ofpprop_put_u32(b, OFPTMPT14_EVICTION, td->eviction_flags);
2322
2323 otv = ofpbuf_put_zeros(b, sizeof *otv);
2324 otv->type = htons(OFPTMPT14_VACANCY);
2325 otv->length = htons(sizeof *otv);
2326 otv->vacancy_down = td->table_vacancy.vacancy_down;
2327 otv->vacancy_up = td->table_vacancy.vacancy_up;
2328 otv->vacancy = td->table_vacancy.vacancy;
2329
2330 otd = ofpbuf_at_assert(b, start_otd, sizeof *otd);
2331 otd->length = htons(b->size - start_otd);
2332 otd->table_id = td->table_id;
2333 otd->config = ofputil_encode_table_config(OFPUTIL_TABLE_MISS_DEFAULT,
2334 td->eviction, td->vacancy,
2335 version);
2336 }
2337
2338 /* Converts the abstract form of a "table status" message in '*ts' into an
2339 * OpenFlow message suitable for 'protocol', and returns that encoded form in
2340 * a buffer owned by the caller. */
2341 struct ofpbuf *
2342 ofputil_encode_table_status(const struct ofputil_table_status *ts,
2343 enum ofputil_protocol protocol)
2344 {
2345 enum ofp_version version;
2346 struct ofpbuf *b;
2347
2348 version = ofputil_protocol_to_ofp_version(protocol);
2349 if (version >= OFP14_VERSION) {
2350 enum ofpraw raw;
2351 struct ofp14_table_status *ots;
2352
2353 raw = OFPRAW_OFPT14_TABLE_STATUS;
2354 b = ofpraw_alloc_xid(raw, version, htonl(0), 0);
2355 ots = ofpbuf_put_zeros(b, sizeof *ots);
2356 ots->reason = ts->reason;
2357 ofputil_put_ofp14_table_desc(&ts->desc, b, version);
2358 ofpmsg_update_length(b);
2359 return b;
2360 } else {
2361 return NULL;
2362 }
2363 }
2364
2365 /* Decodes the OpenFlow "table status" message in '*ots' into an abstract form
2366 * in '*ts'. Returns 0 if successful, otherwise an OFPERR_* value. */
2367 enum ofperr
2368 ofputil_decode_table_status(const struct ofp_header *oh,
2369 struct ofputil_table_status *ts)
2370 {
2371 const struct ofp14_table_status *ots;
2372 struct ofpbuf b;
2373 enum ofperr error;
2374 enum ofpraw raw;
2375
2376 ofpbuf_use_const(&b, oh, ntohs(oh->length));
2377 raw = ofpraw_pull_assert(&b);
2378 ots = ofpbuf_pull(&b, sizeof *ots);
2379
2380 if (raw == OFPRAW_OFPT14_TABLE_STATUS) {
2381 if (ots->reason != OFPTR_VACANCY_DOWN
2382 && ots->reason != OFPTR_VACANCY_UP) {
2383 return OFPERR_OFPBPC_BAD_VALUE;
2384 }
2385 ts->reason = ots->reason;
2386
2387 error = ofputil_decode_table_desc(&b, &ts->desc, oh->version);
2388 return error;
2389 } else {
2390 return OFPERR_OFPBRC_BAD_VERSION;
2391 }
2392
2393 return 0;
2394 }
2395
2396 void
2397 ofputil_format_table_status(struct ds *string,
2398 const struct ofputil_table_status *ts,
2399 const struct ofputil_table_map *table_map)
2400 {
2401 if (ts->reason == OFPTR_VACANCY_DOWN) {
2402 ds_put_format(string, " reason=VACANCY_DOWN");
2403 } else if (ts->reason == OFPTR_VACANCY_UP) {
2404 ds_put_format(string, " reason=VACANCY_UP");
2405 }
2406
2407 ds_put_format(string, "\ntable_desc:-");
2408 ofputil_table_desc_format(string, &ts->desc, table_map);
2409 }