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