]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-print.c
ovs-vswitchd: Better document that ovs-vswitchd manages its own datapaths.
[mirror_ovs.git] / lib / ofp-print.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
19 #include "openvswitch/ofp-print.h"
20
21 #include <errno.h>
22 #include <inttypes.h>
23 #include <sys/types.h>
24 #include <netinet/in.h>
25 #include <sys/wait.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29
30 #include "bundle.h"
31 #include "byte-order.h"
32 #include "colors.h"
33 #include "compiler.h"
34 #include "dp-packet.h"
35 #include "flow.h"
36 #include "learn.h"
37 #include "multipath.h"
38 #include "netdev.h"
39 #include "nx-match.h"
40 #include "odp-util.h"
41 #include "openflow/nicira-ext.h"
42 #include "openflow/openflow.h"
43 #include "openvswitch/dynamic-string.h"
44 #include "openvswitch/meta-flow.h"
45 #include "openvswitch/ofp-actions.h"
46 #include "openvswitch/ofp-bundle.h"
47 #include "openvswitch/ofp-connection.h"
48 #include "openvswitch/ofp-errors.h"
49 #include "openvswitch/ofp-group.h"
50 #include "openvswitch/ofp-ipfix.h"
51 #include "openvswitch/ofp-match.h"
52 #include "openvswitch/ofp-meter.h"
53 #include "openvswitch/ofp-monitor.h"
54 #include "openvswitch/ofp-msgs.h"
55 #include "openvswitch/ofp-port.h"
56 #include "openvswitch/ofp-queue.h"
57 #include "openvswitch/ofp-switch.h"
58 #include "openvswitch/ofp-table.h"
59 #include "openvswitch/ofp-util.h"
60 #include "openvswitch/ofpbuf.h"
61 #include "openvswitch/type-props.h"
62 #include "packets.h"
63 #include "unaligned.h"
64 #include "util.h"
65 #include "uuid.h"
66
67 static void ofp_print_queue_name(struct ds *string, uint32_t port);
68 static void ofp_print_error(struct ds *, enum ofperr);
69
70 /* Returns a string that represents the contents of the Ethernet frame in the
71 * 'len' bytes starting at 'data'. The caller must free the returned string.*/
72 char *
73 ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
74 {
75 struct ds ds = DS_EMPTY_INITIALIZER;
76 struct dp_packet buf;
77 struct flow flow;
78 size_t l4_size;
79
80 dp_packet_use_const(&buf, data, len);
81 buf.packet_type = packet_type;
82 flow_extract(&buf, &flow);
83 flow_format(&ds, &flow, NULL);
84
85 l4_size = dp_packet_l4_size(&buf);
86
87 if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
88 struct tcp_header *th = dp_packet_l4(&buf);
89 ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum));
90 } else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
91 struct udp_header *uh = dp_packet_l4(&buf);
92 ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum));
93 } else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) {
94 struct sctp_header *sh = dp_packet_l4(&buf);
95 ds_put_format(&ds, " sctp_csum:%"PRIx32,
96 ntohl(get_16aligned_be32(&sh->sctp_csum)));
97 } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
98 struct icmp_header *icmph = dp_packet_l4(&buf);
99 ds_put_format(&ds, " icmp_csum:%"PRIx16,
100 ntohs(icmph->icmp_csum));
101 } else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= ICMP6_HEADER_LEN) {
102 struct icmp6_header *icmp6h = dp_packet_l4(&buf);
103 ds_put_format(&ds, " icmp6_csum:%"PRIx16,
104 ntohs(icmp6h->icmp6_cksum));
105 }
106
107 ds_put_char(&ds, '\n');
108
109 return ds_cstr(&ds);
110 }
111
112 char *
113 ofp_dp_packet_to_string(const struct dp_packet *packet)
114 {
115 return ofp_packet_to_string(dp_packet_data(packet),
116 dp_packet_size(packet),
117 packet->packet_type);
118 }
119
120 static enum ofperr
121 ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
122 const struct ofputil_port_map *port_map,
123 const struct ofputil_table_map *table_map, int verbosity)
124 {
125 struct ofputil_packet_in_private pin;
126 uint32_t buffer_id;
127 size_t total_len;
128 enum ofperr error = ofputil_decode_packet_in_private(oh, true, NULL, NULL,
129 &pin, &total_len,
130 &buffer_id);
131 if (!error) {
132 ofputil_packet_in_private_format(string, &pin, total_len, buffer_id,
133 port_map, table_map, verbosity);
134 ofputil_packet_in_private_destroy(&pin);
135 }
136 return error;
137 }
138
139 static enum ofperr
140 ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
141 const struct ofputil_port_map *port_map,
142 const struct ofputil_table_map *table_map, int verbosity)
143 {
144 struct ofputil_packet_out po;
145 struct ofpbuf ofpacts;
146 enum ofperr error;
147
148 ofpbuf_init(&ofpacts, 64);
149 error = ofputil_decode_packet_out(&po, oh, NULL, &ofpacts);
150 if (!error) {
151 ofputil_packet_out_format(string, &po, port_map, table_map, verbosity);
152 }
153 ofpbuf_uninit(&ofpacts);
154 return error;
155 }
156
157 void
158 ofp_print_bit_names(struct ds *string, uint32_t bits,
159 const char *(*bit_to_name)(uint32_t bit),
160 char separator)
161 {
162 int n = 0;
163 int i;
164
165 if (!bits) {
166 ds_put_cstr(string, "0");
167 return;
168 }
169
170 for (i = 0; i < 32; i++) {
171 uint32_t bit = UINT32_C(1) << i;
172
173 if (bits & bit) {
174 const char *name = bit_to_name(bit);
175 if (name) {
176 if (n++) {
177 ds_put_char(string, separator);
178 }
179 ds_put_cstr(string, name);
180 bits &= ~bit;
181 }
182 }
183 }
184
185 if (bits) {
186 if (n) {
187 ds_put_char(string, separator);
188 }
189 ds_put_format(string, "0x%"PRIx32, bits);
190 }
191 }
192
193 static enum ofperr
194 ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
195 {
196 struct ofputil_switch_features features;
197 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
198 enum ofperr error = ofputil_pull_switch_features(&b, &features);
199 if (!error) {
200 ofputil_switch_features_format(string, &features);
201 error = ofputil_phy_ports_format(string, oh->version, &b);
202 }
203 return error;
204 }
205
206 static enum ofperr
207 ofp_print_set_config(struct ds *string, const struct ofp_header *oh)
208 {
209 struct ofputil_switch_config config;
210 enum ofperr error;
211
212 error = ofputil_decode_set_config(oh, &config);
213 if (error) {
214 return error;
215 }
216 ofputil_switch_config_format(string, &config);
217 return 0;
218 }
219
220 static enum ofperr
221 ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh)
222 {
223 struct ofputil_switch_config config;
224 ofputil_decode_get_config_reply(oh, &config);
225 ofputil_switch_config_format(string, &config);
226 return 0;
227 }
228
229 static enum ofperr
230 ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh,
231 const struct ofputil_table_map *table_map)
232 {
233 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
234
235 struct ofputil_table_features prev;
236 for (int i = 0; ; i++) {
237 struct ofputil_table_features tf;
238 int retval;
239
240 retval = ofputil_decode_table_features(&b, &tf, true);
241 if (retval) {
242 return retval != EOF ? retval : 0;
243 }
244
245 ds_put_char(s, '\n');
246 ofputil_table_features_format(s, &tf, i ? &prev : NULL, NULL, NULL,
247 table_map);
248 prev = tf;
249 }
250 }
251
252 void
253 ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
254 {
255 ds_put_format(string, "%u", sec);
256
257 /* If there are no fractional seconds, don't print any decimals.
258 *
259 * If the fractional seconds can be expressed exactly as milliseconds,
260 * print 3 decimals. Open vSwitch provides millisecond precision for most
261 * time measurements, so printing 3 decimals every time makes it easier to
262 * spot real changes in flow dumps that refresh themselves quickly.
263 *
264 * If the fractional seconds are more precise than milliseconds, print the
265 * number of decimals needed to express them exactly.
266 */
267 if (nsec > 0) {
268 unsigned int msec = nsec / 1000000;
269 if (msec * 1000000 == nsec) {
270 ds_put_format(string, ".%03u", msec);
271 } else {
272 ds_put_format(string, ".%09u", nsec);
273 while (string->string[string->length - 1] == '0') {
274 string->length--;
275 }
276 }
277 }
278 ds_put_char(string, 's');
279 }
280
281 static enum ofperr
282 ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh,
283 const struct ofputil_port_map *port_map,
284 const struct ofputil_table_map *table_map)
285 {
286 struct ofputil_flow_removed fr;
287 enum ofperr error = ofputil_decode_flow_removed(&fr, oh);
288 if (!error) {
289 ofputil_flow_removed_format(string, &fr, port_map, table_map);
290 }
291 return error;
292 }
293
294 static enum ofperr
295 ofp_print_port_mod(struct ds *string, const struct ofp_header *oh,
296 const struct ofputil_port_map *port_map)
297 {
298 struct ofputil_port_mod pm;
299 enum ofperr error = ofputil_decode_port_mod(oh, &pm, true);
300 if (!error) {
301 ofputil_port_mod_format(string, &pm, port_map);
302 }
303 return error;
304 }
305
306 static enum ofperr
307 ofp_print_table_mod(struct ds *string, const struct ofp_header *oh,
308 const struct ofputil_table_map *table_map)
309 {
310 struct ofputil_table_mod tm;
311 enum ofperr error = ofputil_decode_table_mod(oh, &tm);
312 if (!error) {
313 ofputil_table_mod_format(string, &tm, table_map);
314 }
315 return error;
316 }
317
318 static enum ofperr
319 ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh,
320 const struct ofputil_table_map *table_map)
321 {
322 struct ofputil_table_status ts;
323 enum ofperr error;
324
325 error = ofputil_decode_table_status(oh, &ts);
326 if (error) {
327 return error;
328 }
329
330 if (ts.reason == OFPTR_VACANCY_DOWN) {
331 ds_put_format(string, " reason=VACANCY_DOWN");
332 } else if (ts.reason == OFPTR_VACANCY_UP) {
333 ds_put_format(string, " reason=VACANCY_UP");
334 }
335
336 ds_put_format(string, "\ntable_desc:-");
337 ofputil_table_desc_format(string, &ts.desc, table_map);
338
339 return 0;
340 }
341
342 static enum ofperr
343 ofp_print_queue_get_config_request(struct ds *string,
344 const struct ofp_header *oh,
345 const struct ofputil_port_map *port_map)
346 {
347 enum ofperr error;
348 ofp_port_t port;
349 uint32_t queue;
350
351 error = ofputil_decode_queue_get_config_request(oh, &port, &queue);
352 if (error) {
353 return error;
354 }
355
356 ds_put_cstr(string, " port=");
357 ofputil_format_port(port, port_map, string);
358
359 if (queue != OFPQ_ALL) {
360 ds_put_cstr(string, " queue=");
361 ofp_print_queue_name(string, queue);
362 }
363
364 return 0;
365 }
366
367 static void
368 print_queue_rate(struct ds *string, const char *name, unsigned int rate)
369 {
370 if (rate <= 1000) {
371 ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10);
372 } else if (rate < UINT16_MAX) {
373 ds_put_format(string, " %s:(disabled)", name);
374 }
375 }
376
377 /* qsort comparison function. */
378 static int
379 compare_queues(const void *a_, const void *b_)
380 {
381 const struct ofputil_queue_config *a = a_;
382 const struct ofputil_queue_config *b = b_;
383
384 uint16_t ap = ofp_to_u16(a->port);
385 uint16_t bp = ofp_to_u16(b->port);
386 if (ap != bp) {
387 return ap < bp ? -1 : 1;
388 }
389
390 uint32_t aq = a->queue;
391 uint32_t bq = b->queue;
392 return aq < bq ? -1 : aq > bq;
393 }
394
395 static enum ofperr
396 ofp_print_queue_get_config_reply(struct ds *string,
397 const struct ofp_header *oh,
398 const struct ofputil_port_map *port_map)
399 {
400 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
401
402 struct ofputil_queue_config *queues = NULL;
403 size_t allocated_queues = 0;
404 size_t n = 0;
405
406 int retval = 0;
407 for (;;) {
408 if (n >= allocated_queues) {
409 queues = x2nrealloc(queues, &allocated_queues, sizeof *queues);
410 }
411 retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]);
412 if (retval) {
413 break;
414 }
415 n++;
416 }
417
418 qsort(queues, n, sizeof *queues, compare_queues);
419
420 ds_put_char(string, ' ');
421
422 ofp_port_t port = 0;
423 for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) {
424 if (q->port != port) {
425 port = q->port;
426
427 ds_put_cstr(string, "port=");
428 ofputil_format_port(port, port_map, string);
429 ds_put_char(string, '\n');
430 }
431
432 ds_put_format(string, "queue %"PRIu32":", q->queue);
433 print_queue_rate(string, "min_rate", q->min_rate);
434 print_queue_rate(string, "max_rate", q->max_rate);
435 ds_put_char(string, '\n');
436 }
437
438 ds_chomp(string, ' ');
439 free(queues);
440
441 return retval != EOF ? retval : 0;
442 }
443
444 static void
445 ofp_print_meter_flags(struct ds *s, uint16_t flags)
446 {
447 if (flags & OFPMF13_KBPS) {
448 ds_put_cstr(s, "kbps ");
449 }
450 if (flags & OFPMF13_PKTPS) {
451 ds_put_cstr(s, "pktps ");
452 }
453 if (flags & OFPMF13_BURST) {
454 ds_put_cstr(s, "burst ");
455 }
456 if (flags & OFPMF13_STATS) {
457 ds_put_cstr(s, "stats ");
458 }
459
460 flags &= ~(OFPMF13_KBPS | OFPMF13_PKTPS | OFPMF13_BURST | OFPMF13_STATS);
461 if (flags) {
462 ds_put_format(s, "flags:0x%"PRIx16" ", flags);
463 }
464 }
465
466 static void
467 ofp_print_meter_band(struct ds *s, uint16_t flags,
468 const struct ofputil_meter_band *mb)
469 {
470 ds_put_cstr(s, "\ntype=");
471 switch (mb->type) {
472 case OFPMBT13_DROP:
473 ds_put_cstr(s, "drop");
474 break;
475 case OFPMBT13_DSCP_REMARK:
476 ds_put_cstr(s, "dscp_remark");
477 break;
478 default:
479 ds_put_format(s, "%u", mb->type);
480 }
481
482 ds_put_format(s, " rate=%"PRIu32, mb->rate);
483
484 if (flags & OFPMF13_BURST) {
485 ds_put_format(s, " burst_size=%"PRIu32, mb->burst_size);
486 }
487 if (mb->type == OFPMBT13_DSCP_REMARK) {
488 ds_put_format(s, " prec_level=%"PRIu8, mb->prec_level);
489 }
490 }
491
492 static void
493 ofp_print_meter_id(struct ds *s, uint32_t meter_id, char seperator)
494 {
495 if (meter_id <= OFPM13_MAX) {
496 ds_put_format(s, "meter%c%"PRIu32, seperator, meter_id);
497 } else {
498 const char *name;
499 switch (meter_id) {
500 case OFPM13_SLOWPATH:
501 name = "slowpath";
502 break;
503 case OFPM13_CONTROLLER:
504 name = "controller";
505 break;
506 case OFPM13_ALL:
507 name = "all";
508 break;
509 default:
510 name = "unknown";
511 }
512 ds_put_format(s, "meter%c%s", seperator, name);
513 }
514 }
515
516 static void
517 ofp_print_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms)
518 {
519 uint16_t i;
520
521 ofp_print_meter_id(s, ms->meter_id, ':');
522 ds_put_char(s, ' ');
523 ds_put_format(s, "flow_count:%"PRIu32" ", ms->flow_count);
524 ds_put_format(s, "packet_in_count:%"PRIu64" ", ms->packet_in_count);
525 ds_put_format(s, "byte_in_count:%"PRIu64" ", ms->byte_in_count);
526 ds_put_cstr(s, "duration:");
527 ofp_print_duration(s, ms->duration_sec, ms->duration_nsec);
528 ds_put_char(s, ' ');
529
530 ds_put_cstr(s, "bands:\n");
531 for (i = 0; i < ms->n_bands; ++i) {
532 ds_put_format(s, "%d: ", i);
533 ds_put_format(s, "packet_count:%"PRIu64" ", ms->bands[i].packet_count);
534 ds_put_format(s, "byte_count:%"PRIu64"\n", ms->bands[i].byte_count);
535 }
536 }
537
538 static void
539 ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc)
540 {
541 uint16_t i;
542
543 ofp_print_meter_id(s, mc->meter_id, '=');
544 ds_put_char(s, ' ');
545
546 ofp_print_meter_flags(s, mc->flags);
547
548 ds_put_cstr(s, "bands=");
549 for (i = 0; i < mc->n_bands; ++i) {
550 ofp_print_meter_band(s, mc->flags, &mc->bands[i]);
551 }
552 ds_put_char(s, '\n');
553 }
554
555 static void
556 ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm)
557 {
558 switch (mm->command) {
559 case OFPMC13_ADD:
560 ds_put_cstr(s, " ADD ");
561 break;
562 case OFPMC13_MODIFY:
563 ds_put_cstr(s, " MOD ");
564 break;
565 case OFPMC13_DELETE:
566 ds_put_cstr(s, " DEL ");
567 break;
568 default:
569 ds_put_format(s, " cmd:%d ", mm->command);
570 }
571
572 ofp_print_meter_config(s, &mm->meter);
573 }
574
575 static enum ofperr
576 ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh)
577 {
578 struct ofputil_meter_mod mm;
579 struct ofpbuf bands;
580 enum ofperr error;
581
582 ofpbuf_init(&bands, 64);
583 error = ofputil_decode_meter_mod(oh, &mm, &bands);
584 if (!error) {
585 ofp_print_meter_mod__(s, &mm);
586 }
587 ofpbuf_uninit(&bands);
588
589 return error;
590 }
591
592 static enum ofperr
593 ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh)
594 {
595 uint32_t meter_id;
596
597 ofputil_decode_meter_request(oh, &meter_id);
598 ds_put_char(s, ' ');
599
600 ofp_print_meter_id(s, meter_id, '=');
601
602 return 0;
603 }
604
605 static const char *
606 ofputil_meter_capabilities_to_name(uint32_t bit)
607 {
608 enum ofp13_meter_flags flag = bit;
609
610 switch (flag) {
611 case OFPMF13_KBPS: return "kbps";
612 case OFPMF13_PKTPS: return "pktps";
613 case OFPMF13_BURST: return "burst";
614 case OFPMF13_STATS: return "stats";
615 }
616
617 return NULL;
618 }
619
620 static const char *
621 ofputil_meter_band_types_to_name(uint32_t bit)
622 {
623 switch (bit) {
624 case 1 << OFPMBT13_DROP: return "drop";
625 case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark";
626 }
627
628 return NULL;
629 }
630
631 static enum ofperr
632 ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
633 {
634 struct ofputil_meter_features mf;
635
636 ofputil_decode_meter_features(oh, &mf);
637
638 ds_put_format(s, "\nmax_meter:%"PRIu32, mf.max_meters);
639 ds_put_format(s, " max_bands:%"PRIu8, mf.max_bands);
640 ds_put_format(s, " max_color:%"PRIu8"\n", mf.max_color);
641
642 ds_put_cstr(s, "band_types: ");
643 ofp_print_bit_names(s, mf.band_types,
644 ofputil_meter_band_types_to_name, ' ');
645 ds_put_char(s, '\n');
646
647 ds_put_cstr(s, "capabilities: ");
648 ofp_print_bit_names(s, mf.capabilities,
649 ofputil_meter_capabilities_to_name, ' ');
650 ds_put_char(s, '\n');
651
652 return 0;
653 }
654
655 static enum ofperr
656 ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
657 {
658 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
659 struct ofpbuf bands;
660 int retval;
661
662 ofpbuf_init(&bands, 64);
663 for (;;) {
664 struct ofputil_meter_config mc;
665
666 retval = ofputil_decode_meter_config(&b, &mc, &bands);
667 if (retval) {
668 break;
669 }
670 ds_put_char(s, '\n');
671 ofp_print_meter_config(s, &mc);
672 }
673 ofpbuf_uninit(&bands);
674
675 return retval != EOF ? retval : 0;
676 }
677
678 static enum ofperr
679 ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
680 {
681 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
682 struct ofpbuf bands;
683 int retval;
684
685 ofpbuf_init(&bands, 64);
686 for (;;) {
687 struct ofputil_meter_stats ms;
688
689 retval = ofputil_decode_meter_stats(&b, &ms, &bands);
690 if (retval) {
691 break;
692 }
693 ds_put_char(s, '\n');
694 ofp_print_meter_stats(s, &ms);
695 }
696 ofpbuf_uninit(&bands);
697
698 return retval != EOF ? retval : 0;
699 }
700
701 static void
702 ofp_print_error(struct ds *string, enum ofperr error)
703 {
704 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
705 }
706
707 static enum ofperr
708 ofp_print_hello(struct ds *string, const struct ofp_header *oh)
709 {
710 ofputil_hello_format(string, oh);
711 return 0;
712 }
713
714 static enum ofperr
715 ofp_print_error_msg(struct ds *string, const struct ofp_header *oh,
716 const struct ofputil_port_map *port_map,
717 const struct ofputil_table_map *table_map)
718 {
719 struct ofpbuf payload;
720 enum ofperr error = ofperr_decode_msg(oh, &payload);
721 if (!error) {
722 return OFPERR_OFPBRC_BAD_LEN;
723 }
724 ofperr_msg_format(string, error, &payload, port_map, table_map);
725 ofpbuf_uninit(&payload);
726
727 return 0;
728 }
729
730 static enum ofperr
731 ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
732 {
733 struct ofputil_port_status ps;
734 enum ofperr error = ofputil_decode_port_status(oh, &ps);
735 if (!error) {
736 ofputil_port_status_format(string, &ps);
737 }
738 return error;
739 }
740
741 static enum ofperr
742 ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
743 {
744 const struct ofp_desc_stats *ods = ofpmsg_body(oh);
745
746 ds_put_char(string, '\n');
747 ds_put_format(string, "Manufacturer: %.*s\n",
748 (int) sizeof ods->mfr_desc, ods->mfr_desc);
749 ds_put_format(string, "Hardware: %.*s\n",
750 (int) sizeof ods->hw_desc, ods->hw_desc);
751 ds_put_format(string, "Software: %.*s\n",
752 (int) sizeof ods->sw_desc, ods->sw_desc);
753 ds_put_format(string, "Serial Num: %.*s\n",
754 (int) sizeof ods->serial_num, ods->serial_num);
755 ds_put_format(string, "DP Description: %.*s\n",
756 (int) sizeof ods->dp_desc, ods->dp_desc);
757
758 return 0;
759 }
760
761 static enum ofperr
762 ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh,
763 const struct ofputil_port_map *port_map,
764 const struct ofputil_table_map *table_map)
765 {
766 struct ofputil_flow_stats_request fsr;
767 enum ofperr error = ofputil_decode_flow_stats_request(&fsr, oh, NULL,
768 NULL);
769 if (!error) {
770 ofputil_flow_stats_request_format(string, &fsr, port_map, table_map);
771 }
772 return error;
773 }
774
775 static enum ofperr
776 ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
777 const struct ofputil_port_map *port_map,
778 const struct ofputil_table_map *table_map)
779 {
780 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
781 struct ofpbuf ofpacts;
782 int retval;
783
784 ofpbuf_init(&ofpacts, 64);
785 for (;;) {
786 struct ofputil_flow_stats fs;
787
788 retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
789 if (retval) {
790 break;
791 }
792 ds_put_cstr(string, "\n ");
793 ofputil_flow_stats_format(string, &fs, port_map, table_map, true);
794 }
795 ofpbuf_uninit(&ofpacts);
796
797 return retval != EOF ? retval : 0;
798 }
799
800 static enum ofperr
801 ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
802 {
803 struct ofputil_aggregate_stats as;
804 enum ofperr error;
805
806 error = ofputil_decode_aggregate_stats_reply(&as, oh);
807 if (!error) {
808 ofputil_aggregate_stats_format(string, &as);
809 }
810 return error;
811 }
812
813 static void
814 print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
815 {
816 ds_put_cstr(string, leader);
817 if (stat != UINT64_MAX) {
818 ds_put_format(string, "%"PRIu64, stat);
819 } else {
820 ds_put_char(string, '?');
821 }
822 if (more) {
823 ds_put_cstr(string, ", ");
824 } else {
825 ds_put_cstr(string, "\n");
826 }
827 }
828
829 static void
830 print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat)
831 {
832 if (stat != UINT64_MAX) {
833 ds_put_format(string, "%s%"PRIu64", ", leader, stat);
834 }
835 }
836
837 static enum ofperr
838 ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh,
839 const struct ofputil_port_map *port_map)
840 {
841 ofp_port_t ofp10_port;
842 enum ofperr error;
843
844 error = ofputil_decode_port_stats_request(oh, &ofp10_port);
845 if (error) {
846 return error;
847 }
848
849 ds_put_cstr(string, " port_no=");
850 ofputil_format_port(ofp10_port, port_map, string);
851
852 return 0;
853 }
854
855 static enum ofperr
856 ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
857 const struct ofputil_port_map *port_map,
858 int verbosity)
859 {
860 uint32_t i;
861 ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh));
862 if (verbosity < 1) {
863 return 0;
864 }
865
866 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
867 for (;;) {
868 struct ofputil_port_stats ps;
869 int retval;
870
871 retval = ofputil_decode_port_stats(&ps, &b);
872 if (retval) {
873 return retval != EOF ? retval : 0;
874 }
875
876 ds_put_cstr(string, " port ");
877 if (ofp_to_u16(ps.port_no) < 10) {
878 ds_put_char(string, ' ');
879 }
880 ofputil_format_port(ps.port_no, port_map, string);
881
882 ds_put_cstr(string, ": rx ");
883 print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
884 print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
885 print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
886 print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
887 print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
888 print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
889 print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
890
891 ds_put_cstr(string, " tx ");
892 print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
893 print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
894 print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
895 print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
896 print_port_stat(string, "coll=", ps.stats.collisions, 0);
897
898 if (ps.duration_sec != UINT32_MAX) {
899 ds_put_cstr(string, " duration=");
900 ofp_print_duration(string, ps.duration_sec, ps.duration_nsec);
901 ds_put_char(string, '\n');
902 }
903 struct ds string_ext_stats = DS_EMPTY_INITIALIZER;
904
905 ds_init(&string_ext_stats);
906
907 print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
908 ps.stats.rx_1_to_64_packets);
909 print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
910 ps.stats.rx_65_to_127_packets);
911 print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
912 ps.stats.rx_128_to_255_packets);
913 print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
914 ps.stats.rx_256_to_511_packets);
915 print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
916 ps.stats.rx_512_to_1023_packets);
917 print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
918 ps.stats.rx_1024_to_1522_packets);
919 print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
920 ps.stats.rx_1523_to_max_packets);
921 print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
922 ps.stats.rx_broadcast_packets);
923 print_port_stat_cond(&string_ext_stats, "undersized_errors=",
924 ps.stats.rx_undersized_errors);
925 print_port_stat_cond(&string_ext_stats, "oversize_errors=",
926 ps.stats.rx_oversize_errors);
927 print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=",
928 ps.stats.rx_fragmented_errors);
929 print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=",
930 ps.stats.rx_jabber_errors);
931
932 if (string_ext_stats.length != 0) {
933 /* If at least one statistics counter is reported: */
934 ds_put_cstr(string, " rx rfc2819 ");
935 ds_put_buffer(string, string_ext_stats.string,
936 string_ext_stats.length);
937 ds_put_cstr(string, "\n");
938 ds_destroy(&string_ext_stats);
939 }
940
941 ds_init(&string_ext_stats);
942
943 print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
944 ps.stats.tx_1_to_64_packets);
945 print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
946 ps.stats.tx_65_to_127_packets);
947 print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
948 ps.stats.tx_128_to_255_packets);
949 print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
950 ps.stats.tx_256_to_511_packets);
951 print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
952 ps.stats.tx_512_to_1023_packets);
953 print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
954 ps.stats.tx_1024_to_1522_packets);
955 print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
956 ps.stats.tx_1523_to_max_packets);
957 print_port_stat_cond(&string_ext_stats, "multicast_packets=",
958 ps.stats.tx_multicast_packets);
959 print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
960 ps.stats.tx_broadcast_packets);
961
962 if (string_ext_stats.length != 0) {
963 /* If at least one statistics counter is reported: */
964 ds_put_cstr(string, " tx rfc2819 ");
965 ds_put_buffer(string, string_ext_stats.string,
966 string_ext_stats.length);
967 ds_put_cstr(string, "\n");
968 ds_destroy(&string_ext_stats);
969 }
970
971 if (ps.custom_stats.size) {
972 ds_put_cstr(string, " CUSTOM Statistics");
973 for (i = 0; i < ps.custom_stats.size; i++) {
974 /* 3 counters in the row */
975 if (ps.custom_stats.counters[i].name[0]) {
976 if (i % 3 == 0) {
977 ds_put_cstr(string, "\n");
978 ds_put_cstr(string, " ");
979 } else {
980 ds_put_char(string, ' ');
981 }
982 ds_put_format(string, "%s=%"PRIu64",",
983 ps.custom_stats.counters[i].name,
984 ps.custom_stats.counters[i].value);
985 }
986 }
987 ds_put_cstr(string, "\n");
988 }
989 }
990 }
991
992 static enum ofperr
993 ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh,
994 const struct ofputil_table_map *table_map)
995 {
996 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
997 ofpraw_pull_assert(&b);
998
999 struct ofputil_table_features prev_features;
1000 struct ofputil_table_stats prev_stats;
1001 for (int i = 0;; i++) {
1002 struct ofputil_table_features features;
1003 struct ofputil_table_stats stats;
1004 int retval;
1005
1006 retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
1007 if (retval) {
1008 return retval != EOF ? retval : 0;
1009 }
1010
1011 ds_put_char(string, '\n');
1012 ofputil_table_features_format(string,
1013 &features, i ? &prev_features : NULL,
1014 &stats, i ? &prev_stats : NULL,
1015 table_map);
1016 prev_features = features;
1017 prev_stats = stats;
1018 }
1019 }
1020
1021 static void
1022 ofp_print_queue_name(struct ds *string, uint32_t queue_id)
1023 {
1024 if (queue_id == OFPQ_ALL) {
1025 ds_put_cstr(string, "ALL");
1026 } else {
1027 ds_put_format(string, "%"PRIu32, queue_id);
1028 }
1029 }
1030
1031 static enum ofperr
1032 ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh,
1033 const struct ofputil_port_map *port_map)
1034 {
1035 struct ofputil_queue_stats_request oqsr;
1036 enum ofperr error;
1037
1038 error = ofputil_decode_queue_stats_request(oh, &oqsr);
1039 if (error) {
1040 return error;
1041 }
1042
1043 ds_put_cstr(string, " port=");
1044 ofputil_format_port(oqsr.port_no, port_map, string);
1045
1046 ds_put_cstr(string, " queue=");
1047 ofp_print_queue_name(string, oqsr.queue_id);
1048
1049 return 0;
1050 }
1051
1052 static enum ofperr
1053 ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
1054 const struct ofputil_port_map *port_map,
1055 int verbosity)
1056 {
1057 ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh));
1058 if (verbosity < 1) {
1059 return 0;
1060 }
1061
1062 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1063 for (;;) {
1064 struct ofputil_queue_stats qs;
1065 int retval;
1066
1067 retval = ofputil_decode_queue_stats(&qs, &b);
1068 if (retval) {
1069 return retval != EOF ? retval : 0;
1070 }
1071
1072 ds_put_cstr(string, " port ");
1073 ofputil_format_port(qs.port_no, port_map, string);
1074 ds_put_cstr(string, " queue ");
1075 ofp_print_queue_name(string, qs.queue_id);
1076 ds_put_cstr(string, ": ");
1077
1078 print_port_stat(string, "bytes=", qs.tx_bytes, 1);
1079 print_port_stat(string, "pkts=", qs.tx_packets, 1);
1080 print_port_stat(string, "errors=", qs.tx_errors, 1);
1081
1082 ds_put_cstr(string, "duration=");
1083 if (qs.duration_sec != UINT32_MAX) {
1084 ofp_print_duration(string, qs.duration_sec, qs.duration_nsec);
1085 } else {
1086 ds_put_char(string, '?');
1087 }
1088 ds_put_char(string, '\n');
1089 }
1090 }
1091
1092 static enum ofperr
1093 ofp_print_ofpst_port_desc_request(struct ds *string,
1094 const struct ofp_header *oh,
1095 const struct ofputil_port_map *port_map)
1096 {
1097 enum ofperr error;
1098 ofp_port_t port;
1099
1100 error = ofputil_decode_port_desc_stats_request(oh, &port);
1101 if (error) {
1102 return error;
1103 }
1104
1105 ds_put_cstr(string, " port=");
1106 ofputil_format_port(port, port_map, string);
1107
1108 return 0;
1109 }
1110
1111 static enum ofperr
1112 ofp_print_ofpst_port_desc_reply(struct ds *string,
1113 const struct ofp_header *oh)
1114 {
1115 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1116 ofpraw_pull_assert(&b);
1117 ds_put_char(string, '\n');
1118 return ofputil_phy_ports_format(string, oh->version, &b);
1119 }
1120
1121 static void
1122 ofp_print_stats(struct ds *string, const struct ofp_header *oh)
1123 {
1124 uint16_t flags = ofpmp_flags(oh);
1125
1126 if (flags) {
1127 ds_put_cstr(string, " flags=");
1128 if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
1129 && (flags & OFPSF_REPLY_MORE)) {
1130 ds_put_cstr(string, "[more]");
1131 flags &= ~OFPSF_REPLY_MORE;
1132 }
1133 if (flags) {
1134 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
1135 flags);
1136 }
1137 }
1138 }
1139
1140 static enum ofperr
1141 ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
1142 {
1143 size_t len = ntohs(oh->length);
1144
1145 ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
1146 if (verbosity > 1) {
1147 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
1148 }
1149
1150 return 0;
1151 }
1152
1153 static void
1154 ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role,
1155 uint64_t generation_id)
1156 {
1157 ds_put_cstr(string, " role=");
1158
1159 switch (role) {
1160 case OFPCR12_ROLE_NOCHANGE:
1161 ds_put_cstr(string, "nochange");
1162 break;
1163 case OFPCR12_ROLE_EQUAL:
1164 ds_put_cstr(string, "equal"); /* OF 1.2 wording */
1165 break;
1166 case OFPCR12_ROLE_MASTER:
1167 ds_put_cstr(string, "master");
1168 break;
1169 case OFPCR12_ROLE_SLAVE:
1170 ds_put_cstr(string, "slave");
1171 break;
1172 default:
1173 OVS_NOT_REACHED();
1174 }
1175
1176 if (generation_id != UINT64_MAX) {
1177 ds_put_format(string, " generation_id=%"PRIu64, generation_id);
1178 }
1179 }
1180
1181 static enum ofperr
1182 ofp_print_role_message(struct ds *string, const struct ofp_header *oh)
1183 {
1184 struct ofputil_role_request rr;
1185 enum ofperr error;
1186
1187 error = ofputil_decode_role_message(oh, &rr);
1188 if (error) {
1189 return error;
1190 }
1191
1192 ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX);
1193
1194 return 0;
1195 }
1196
1197 static enum ofperr
1198 ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh)
1199 {
1200 struct ofputil_role_status rs;
1201 enum ofperr error;
1202
1203 error = ofputil_decode_role_status(oh, &rs);
1204 if (error) {
1205 return error;
1206 }
1207
1208 ofp_print_role_generic(string, rs.role, rs.generation_id);
1209
1210 ds_put_cstr(string, " reason=");
1211
1212 switch (rs.reason) {
1213 case OFPCRR_MASTER_REQUEST:
1214 ds_put_cstr(string, "master_request");
1215 break;
1216 case OFPCRR_CONFIG:
1217 ds_put_cstr(string, "configuration_changed");
1218 break;
1219 case OFPCRR_EXPERIMENTER:
1220 ds_put_cstr(string, "experimenter_data_changed");
1221 break;
1222 case OFPCRR_N_REASONS:
1223 default:
1224 ds_put_cstr(string, "(unknown)");
1225 break;
1226 }
1227
1228 return 0;
1229 }
1230
1231 static enum ofperr
1232 ofp_print_nxt_flow_mod_table_id(struct ds *string, const struct ofp_header *oh)
1233 {
1234 bool enable = ofputil_decode_nx_flow_mod_table_id(oh);
1235 ds_put_format(string, " %s", enable ? "enable" : "disable");
1236 return 0;
1237 }
1238
1239 static enum ofperr
1240 ofp_print_nxt_set_flow_format(struct ds *string, const struct ofp_header *oh)
1241 {
1242 enum ofputil_protocol p = ofputil_decode_nx_set_flow_format(oh);
1243 ds_put_format(string, " format=%s",
1244 p == OFPUTIL_P_OF10_STD ? "openflow10"
1245 : p == OFPUTIL_P_OF10_NXM ? "nxm"
1246 : "(unknown)");
1247 return 0;
1248 }
1249
1250 static enum ofperr
1251 ofp_print_nxt_set_packet_in_format(struct ds *string,
1252 const struct ofp_header *oh)
1253 {
1254 enum ofputil_packet_in_format format;
1255 enum ofperr error = ofputil_decode_set_packet_in_format(oh, &format);
1256 if (!error) {
1257 ds_put_format(string, " format=%s",
1258 ofputil_packet_in_format_to_string(format));
1259 }
1260 return error;
1261 }
1262
1263 /* Returns a string form of 'reason'. The return value is either a statically
1264 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
1265 * 'bufsize' should be at least OFP_PORT_REASON_BUFSIZE. */
1266 #define OFP_PORT_REASON_BUFSIZE (INT_STRLEN(int) + 1)
1267 static const char *
1268 ofp_port_reason_to_string(enum ofp_port_reason reason,
1269 char *reasonbuf, size_t bufsize)
1270 {
1271 switch (reason) {
1272 case OFPPR_ADD:
1273 return "add";
1274
1275 case OFPPR_DELETE:
1276 return "delete";
1277
1278 case OFPPR_MODIFY:
1279 return "modify";
1280
1281 case OFPPR_N_REASONS:
1282 default:
1283 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1284 return reasonbuf;
1285 }
1286 }
1287
1288 /* Returns a string form of 'reason'. The return value is either a statically
1289 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
1290 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
1291 static const char*
1292 ofp_role_reason_to_string(enum ofp14_controller_role_reason reason,
1293 char *reasonbuf, size_t bufsize)
1294 {
1295 switch (reason) {
1296 case OFPCRR_MASTER_REQUEST:
1297 return "master_request";
1298
1299 case OFPCRR_CONFIG:
1300 return "configuration_changed";
1301
1302 case OFPCRR_EXPERIMENTER:
1303 return "experimenter_data_changed";
1304
1305 case OFPCRR_N_REASONS:
1306 default:
1307 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1308 return reasonbuf;
1309 }
1310 }
1311
1312 /* Returns a string form of 'reason'. The return value is either a statically
1313 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
1314 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
1315 static const char*
1316 ofp_table_reason_to_string(enum ofp14_table_reason reason,
1317 char *reasonbuf, size_t bufsize)
1318 {
1319 switch (reason) {
1320 case OFPTR_VACANCY_DOWN:
1321 return "vacancy_down";
1322
1323 case OFPTR_VACANCY_UP:
1324 return "vacancy_up";
1325
1326 default:
1327 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1328 return reasonbuf;
1329 }
1330 }
1331
1332 /* Returns a string form of 'reason'. The return value is either a statically
1333 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
1334 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
1335 static const char*
1336 ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason,
1337 char *reasonbuf, size_t bufsize)
1338 {
1339 switch (reason) {
1340 case OFPRFR_GROUP_MOD:
1341 return "group_mod_request";
1342
1343 case OFPRFR_METER_MOD:
1344 return "meter_mod_request";
1345
1346 case OFPRFR_N_REASONS:
1347 default:
1348 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1349 return reasonbuf;
1350 }
1351 }
1352
1353 static const char *
1354 ofp_async_config_reason_to_string(uint32_t reason,
1355 enum ofputil_async_msg_type type,
1356 char *reasonbuf, size_t bufsize)
1357 {
1358 switch (type) {
1359 case OAM_PACKET_IN:
1360 return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize);
1361
1362 case OAM_PORT_STATUS:
1363 return ofp_port_reason_to_string(reason, reasonbuf, bufsize);
1364
1365 case OAM_FLOW_REMOVED:
1366 return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize);
1367
1368 case OAM_ROLE_STATUS:
1369 return ofp_role_reason_to_string(reason, reasonbuf, bufsize);
1370
1371 case OAM_TABLE_STATUS:
1372 return ofp_table_reason_to_string(reason, reasonbuf, bufsize);
1373
1374 case OAM_REQUESTFORWARD:
1375 return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize);
1376
1377 case OAM_N_TYPES:
1378 default:
1379 return "Unknown asynchronous configuration message type";
1380 }
1381 }
1382
1383
1384 #define OFP_ASYNC_CONFIG_REASON_BUFSIZE (INT_STRLEN(int) + 1)
1385 static enum ofperr
1386 ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
1387 enum ofptype ofptype)
1388 {
1389 struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
1390 struct ofputil_async_cfg ac;
1391
1392 bool is_reply = ofptype == OFPTYPE_GET_ASYNC_REPLY;
1393 enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
1394 &basis, &ac);
1395 if (error) {
1396 return error;
1397 }
1398
1399 for (int i = 0; i < 2; i++) {
1400 ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
1401 for (uint32_t type = 0; type < OAM_N_TYPES; type++) {
1402 ds_put_format(string, "%16s:",
1403 ofputil_async_msg_type_to_string(type));
1404
1405 uint32_t role = i == 0 ? ac.master[type] : ac.slave[type];
1406 for (int j = 0; j < 32; j++) {
1407 if (role & (1u << j)) {
1408 char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE];
1409 const char *reason;
1410
1411 reason = ofp_async_config_reason_to_string(
1412 j, type, reasonbuf, sizeof reasonbuf);
1413 if (reason[0]) {
1414 ds_put_format(string, " %s", reason);
1415 }
1416 }
1417 }
1418 if (!role) {
1419 ds_put_cstr(string, " (off)");
1420 }
1421 ds_put_char(string, '\n');
1422 }
1423 }
1424
1425 return 0;
1426 }
1427
1428 static enum ofperr
1429 ofp_print_nxt_set_controller_id(struct ds *string,
1430 const struct nx_controller_id *nci)
1431 {
1432 ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
1433 return 0;
1434 }
1435
1436 static enum ofperr
1437 ofp_print_nxt_flow_monitor_cancel(struct ds *string,
1438 const struct ofp_header *oh)
1439 {
1440 ds_put_format(string, " id=%"PRIu32,
1441 ofputil_decode_flow_monitor_cancel(oh));
1442 return 0;
1443 }
1444
1445 static enum ofperr
1446 ofp_print_nxst_flow_monitor_request(struct ds *string,
1447 const struct ofp_header *oh,
1448 const struct ofputil_port_map *port_map,
1449 const struct ofputil_table_map *table_map)
1450 {
1451 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1452 for (;;) {
1453 struct ofputil_flow_monitor_request request;
1454 int retval;
1455
1456 retval = ofputil_decode_flow_monitor_request(&request, &b);
1457 if (retval) {
1458 return retval != EOF ? retval : 0;
1459 }
1460
1461 ofputil_flow_monitor_request_format(string, &request,
1462 port_map, table_map);
1463 }
1464 }
1465
1466 static enum ofperr
1467 ofp_print_nxst_flow_monitor_reply(struct ds *string,
1468 const struct ofp_header *oh,
1469 const struct ofputil_port_map *port_map,
1470 const struct ofputil_table_map *table_map)
1471 {
1472 uint64_t ofpacts_stub[1024 / 8];
1473 struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
1474 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1475
1476 for (;;) {
1477 struct ofputil_flow_update update;
1478 int retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
1479 if (retval) {
1480 ofpbuf_uninit(&ofpacts);
1481 return retval != EOF ? retval : 0;
1482 }
1483 ofputil_flow_update_format(string, &update, port_map, table_map);
1484 }
1485 }
1486
1487 void
1488 ofp_print_version(const struct ofp_header *oh,
1489 struct ds *string)
1490 {
1491 switch (oh->version) {
1492 case OFP10_VERSION:
1493 break;
1494 case OFP11_VERSION:
1495 ds_put_cstr(string, " (OF1.1)");
1496 break;
1497 case OFP12_VERSION:
1498 ds_put_cstr(string, " (OF1.2)");
1499 break;
1500 case OFP13_VERSION:
1501 ds_put_cstr(string, " (OF1.3)");
1502 break;
1503 case OFP14_VERSION:
1504 ds_put_cstr(string, " (OF1.4)");
1505 break;
1506 case OFP15_VERSION:
1507 ds_put_cstr(string, " (OF1.5)");
1508 break;
1509 case OFP16_VERSION:
1510 ds_put_cstr(string, " (OF1.6)");
1511 break;
1512 default:
1513 ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
1514 break;
1515 }
1516 ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid));
1517 }
1518
1519 static void
1520 ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
1521 struct ds *string)
1522 {
1523 ds_put_cstr(string, ofpraw_get_name(raw));
1524 ofp_print_version(oh, string);
1525 }
1526
1527 static void
1528 ofp_print_bucket_id(struct ds *s, const char *label, uint32_t bucket_id,
1529 enum ofp_version ofp_version)
1530 {
1531 if (ofp_version < OFP15_VERSION) {
1532 return;
1533 }
1534
1535 ds_put_cstr(s, label);
1536
1537 switch (bucket_id) {
1538 case OFPG15_BUCKET_FIRST:
1539 ds_put_cstr(s, "first");
1540 break;
1541 case OFPG15_BUCKET_LAST:
1542 ds_put_cstr(s, "last");
1543 break;
1544 case OFPG15_BUCKET_ALL:
1545 ds_put_cstr(s, "all");
1546 break;
1547 default:
1548 ds_put_format(s, "%"PRIu32, bucket_id);
1549 break;
1550 }
1551
1552 ds_put_char(s, ',');
1553 }
1554
1555 static void
1556 ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type,
1557 const struct ovs_list *p_buckets,
1558 const struct ofputil_group_props *props,
1559 enum ofp_version ofp_version, bool suppress_type,
1560 const struct ofputil_port_map *port_map,
1561 const struct ofputil_table_map *table_map)
1562 {
1563 struct ofputil_bucket *bucket;
1564
1565 ds_put_format(s, "group_id=%"PRIu32, group_id);
1566
1567 if (!suppress_type) {
1568 static const char *type_str[] = { "all", "select", "indirect",
1569 "ff", "unknown" };
1570 ds_put_format(s, ",type=%s", type_str[type > 4 ? 4 : type]);
1571 }
1572
1573 if (props->selection_method[0]) {
1574 ds_put_format(s, ",selection_method=%s", props->selection_method);
1575 if (props->selection_method_param) {
1576 ds_put_format(s, ",selection_method_param=%"PRIu64,
1577 props->selection_method_param);
1578 }
1579
1580 size_t n = bitmap_count1(props->fields.used.bm, MFF_N_IDS);
1581 if (n == 1) {
1582 ds_put_cstr(s, ",fields=");
1583 oxm_format_field_array(s, &props->fields);
1584 } else if (n > 1) {
1585 ds_put_cstr(s, ",fields(");
1586 oxm_format_field_array(s, &props->fields);
1587 ds_put_char(s, ')');
1588 }
1589 }
1590
1591 if (!p_buckets) {
1592 return;
1593 }
1594
1595 ds_put_char(s, ',');
1596
1597 LIST_FOR_EACH (bucket, list_node, p_buckets) {
1598 ds_put_cstr(s, "bucket=");
1599
1600 ofp_print_bucket_id(s, "bucket_id:", bucket->bucket_id, ofp_version);
1601 if (bucket->weight != (type == OFPGT11_SELECT ? 1 : 0)) {
1602 ds_put_format(s, "weight:%"PRIu16",", bucket->weight);
1603 }
1604 if (bucket->watch_port != OFPP_NONE) {
1605 ds_put_cstr(s, "watch_port:");
1606 ofputil_format_port(bucket->watch_port, port_map, s);
1607 ds_put_char(s, ',');
1608 }
1609 if (bucket->watch_group != OFPG_ANY) {
1610 ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group);
1611 }
1612
1613 ds_put_cstr(s, "actions=");
1614 struct ofpact_format_params fp = {
1615 .port_map = port_map,
1616 .table_map = table_map,
1617 .s = s,
1618 };
1619 ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, &fp);
1620 ds_put_char(s, ',');
1621 }
1622
1623 ds_chomp(s, ',');
1624 }
1625
1626 static enum ofperr
1627 ofp_print_ofpst_group_desc_request(struct ds *string,
1628 const struct ofp_header *oh)
1629 {
1630 uint32_t group_id = ofputil_decode_group_desc_request(oh);
1631 ds_put_cstr(string, " group_id=");
1632 ofputil_format_group(group_id, string);
1633
1634 return 0;
1635 }
1636
1637 static enum ofperr
1638 ofp_print_group_desc(struct ds *s, const struct ofp_header *oh,
1639 const struct ofputil_port_map *port_map,
1640 const struct ofputil_table_map *table_map)
1641 {
1642 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1643 for (;;) {
1644 struct ofputil_group_desc gd;
1645 int retval;
1646
1647 retval = ofputil_decode_group_desc_reply(&gd, &b, oh->version);
1648 if (retval) {
1649 return retval != EOF ? retval : 0;
1650 }
1651
1652 ds_put_char(s, '\n');
1653 ds_put_char(s, ' ');
1654 ofp_print_group(s, gd.group_id, gd.type, &gd.buckets, &gd.props,
1655 oh->version, false, port_map, table_map);
1656 ofputil_uninit_group_desc(&gd);
1657 }
1658 }
1659
1660 static enum ofperr
1661 ofp_print_ofpst_group_request(struct ds *string, const struct ofp_header *oh)
1662 {
1663 enum ofperr error;
1664 uint32_t group_id;
1665
1666 error = ofputil_decode_group_stats_request(oh, &group_id);
1667 if (error) {
1668 return error;
1669 }
1670
1671 ds_put_cstr(string, " group_id=");
1672 ofputil_format_group(group_id, string);
1673 return 0;
1674 }
1675
1676 static enum ofperr
1677 ofp_print_group_stats(struct ds *s, const struct ofp_header *oh)
1678 {
1679 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1680 for (;;) {
1681 struct ofputil_group_stats gs;
1682 int retval;
1683
1684 retval = ofputil_decode_group_stats_reply(&b, &gs);
1685 if (retval) {
1686 if (retval != EOF) {
1687 ds_put_cstr(s, " ***parse error***");
1688 return retval;
1689 }
1690 break;
1691 }
1692
1693 ds_put_char(s, '\n');
1694
1695 ds_put_char(s, ' ');
1696 ds_put_format(s, "group_id=%"PRIu32",", gs.group_id);
1697
1698 if (gs.duration_sec != UINT32_MAX) {
1699 ds_put_cstr(s, "duration=");
1700 ofp_print_duration(s, gs.duration_sec, gs.duration_nsec);
1701 ds_put_char(s, ',');
1702 }
1703 ds_put_format(s, "ref_count=%"PRIu32",", gs.ref_count);
1704 ds_put_format(s, "packet_count=%"PRIu64",", gs.packet_count);
1705 ds_put_format(s, "byte_count=%"PRIu64"", gs.byte_count);
1706
1707 for (uint32_t bucket_i = 0; bucket_i < gs.n_buckets; bucket_i++) {
1708 if (gs.bucket_stats[bucket_i].packet_count != UINT64_MAX) {
1709 ds_put_format(s, ",bucket%"PRIu32":", bucket_i);
1710 ds_put_format(s, "packet_count=%"PRIu64",", gs.bucket_stats[bucket_i].packet_count);
1711 ds_put_format(s, "byte_count=%"PRIu64"", gs.bucket_stats[bucket_i].byte_count);
1712 }
1713 }
1714
1715 free(gs.bucket_stats);
1716 }
1717 return 0;
1718 }
1719
1720 static const char *
1721 group_type_to_string(enum ofp11_group_type type)
1722 {
1723 switch (type) {
1724 case OFPGT11_ALL: return "all";
1725 case OFPGT11_SELECT: return "select";
1726 case OFPGT11_INDIRECT: return "indirect";
1727 case OFPGT11_FF: return "fast failover";
1728 default: OVS_NOT_REACHED();
1729 }
1730 }
1731
1732 static enum ofperr
1733 ofp_print_group_features(struct ds *string, const struct ofp_header *oh)
1734 {
1735 struct ofputil_group_features features;
1736 int i;
1737
1738 ofputil_decode_group_features_reply(oh, &features);
1739
1740 ds_put_format(string, "\n Group table:\n");
1741 ds_put_format(string, " Types: 0x%"PRIx32"\n", features.types);
1742 ds_put_format(string, " Capabilities: 0x%"PRIx32"\n",
1743 features.capabilities);
1744
1745 for (i = 0; i < OFPGT12_N_TYPES; i++) {
1746 if (features.types & (1u << i)) {
1747 ds_put_format(string, " %s group:\n", group_type_to_string(i));
1748 ds_put_format(string, " max_groups=%#"PRIx32"\n",
1749 features.max_groups[i]);
1750 ds_put_format(string, " actions: ");
1751 ofpact_bitmap_format(features.ofpacts[i], string);
1752 ds_put_char(string, '\n');
1753 }
1754 }
1755
1756 return 0;
1757 }
1758
1759 static void
1760 ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version,
1761 const struct ofputil_group_mod *gm,
1762 const struct ofputil_port_map *port_map,
1763 const struct ofputil_table_map *table_map)
1764 {
1765 bool bucket_command = false;
1766
1767 ds_put_char(s, '\n');
1768
1769 ds_put_char(s, ' ');
1770 switch (gm->command) {
1771 case OFPGC11_ADD:
1772 ds_put_cstr(s, "ADD");
1773 break;
1774
1775 case OFPGC11_MODIFY:
1776 ds_put_cstr(s, "MOD");
1777 break;
1778
1779 case OFPGC11_ADD_OR_MOD:
1780 ds_put_cstr(s, "ADD_OR_MOD");
1781 break;
1782
1783 case OFPGC11_DELETE:
1784 ds_put_cstr(s, "DEL");
1785 break;
1786
1787 case OFPGC15_INSERT_BUCKET:
1788 ds_put_cstr(s, "INSERT_BUCKET");
1789 bucket_command = true;
1790 break;
1791
1792 case OFPGC15_REMOVE_BUCKET:
1793 ds_put_cstr(s, "REMOVE_BUCKET");
1794 bucket_command = true;
1795 break;
1796
1797 default:
1798 ds_put_format(s, "cmd:%"PRIu16"", gm->command);
1799 }
1800 ds_put_char(s, ' ');
1801
1802 if (bucket_command) {
1803 ofp_print_bucket_id(s, "command_bucket_id:",
1804 gm->command_bucket_id, ofp_version);
1805 }
1806
1807 ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props,
1808 ofp_version, bucket_command, port_map, table_map);
1809 }
1810
1811 static enum ofperr
1812 ofp_print_group_mod(struct ds *s, const struct ofp_header *oh,
1813 const struct ofputil_port_map *port_map,
1814 const struct ofputil_table_map *table_map)
1815 {
1816 struct ofputil_group_mod gm;
1817 int error;
1818
1819 error = ofputil_decode_group_mod(oh, &gm);
1820 if (error) {
1821 return error;
1822 }
1823 ofp_print_group_mod__(s, oh->version, &gm, port_map, table_map);
1824 ofputil_uninit_group_mod(&gm);
1825 return 0;
1826 }
1827
1828 static enum ofperr
1829 ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
1830 const struct ofputil_table_map *table_map)
1831 {
1832 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1833 for (;;) {
1834 struct ofputil_table_desc td;
1835 int retval;
1836
1837 retval = ofputil_decode_table_desc(&b, &td, oh->version);
1838 if (retval) {
1839 return retval != EOF ? retval : 0;
1840 }
1841 ofputil_table_desc_format(s, &td, table_map);
1842 }
1843 }
1844
1845 static const char *
1846 bundle_flags_to_name(uint32_t bit)
1847 {
1848 switch (bit) {
1849 case OFPBF_ATOMIC:
1850 return "atomic";
1851 case OFPBF_ORDERED:
1852 return "ordered";
1853 default:
1854 return NULL;
1855 }
1856 }
1857
1858 static enum ofperr
1859 ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
1860 {
1861 int error;
1862 struct ofputil_bundle_ctrl_msg bctrl;
1863
1864 error = ofputil_decode_bundle_ctrl(oh, &bctrl);
1865 if (error) {
1866 return error;
1867 }
1868
1869 ds_put_char(s, '\n');
1870
1871 ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id);
1872 switch (bctrl.type) {
1873 case OFPBCT_OPEN_REQUEST:
1874 ds_put_cstr(s, "OPEN_REQUEST");
1875 break;
1876 case OFPBCT_OPEN_REPLY:
1877 ds_put_cstr(s, "OPEN_REPLY");
1878 break;
1879 case OFPBCT_CLOSE_REQUEST:
1880 ds_put_cstr(s, "CLOSE_REQUEST");
1881 break;
1882 case OFPBCT_CLOSE_REPLY:
1883 ds_put_cstr(s, "CLOSE_REPLY");
1884 break;
1885 case OFPBCT_COMMIT_REQUEST:
1886 ds_put_cstr(s, "COMMIT_REQUEST");
1887 break;
1888 case OFPBCT_COMMIT_REPLY:
1889 ds_put_cstr(s, "COMMIT_REPLY");
1890 break;
1891 case OFPBCT_DISCARD_REQUEST:
1892 ds_put_cstr(s, "DISCARD_REQUEST");
1893 break;
1894 case OFPBCT_DISCARD_REPLY:
1895 ds_put_cstr(s, "DISCARD_REPLY");
1896 break;
1897 }
1898
1899 ds_put_cstr(s, " flags=");
1900 ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' ');
1901
1902 return 0;
1903 }
1904
1905 static enum ofperr
1906 ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
1907 const struct ofputil_port_map *port_map,
1908 const struct ofputil_table_map *table_map,
1909 int verbosity)
1910 {
1911 int error;
1912 struct ofputil_bundle_add_msg badd;
1913
1914 error = ofputil_decode_bundle_add(oh, &badd, NULL);
1915 if (error) {
1916 return error;
1917 }
1918
1919 ds_put_char(s, '\n');
1920 ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id);
1921 ds_put_cstr(s, " flags=");
1922 ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' ');
1923
1924 ds_put_char(s, '\n');
1925 char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map,
1926 table_map, verbosity);
1927 ds_put_and_free_cstr(s, msg);
1928
1929 return 0;
1930 }
1931
1932 static void
1933 print_tlv_table(struct ds *s, struct ovs_list *mappings)
1934 {
1935 struct ofputil_tlv_map *map;
1936
1937 ds_put_cstr(s, " mapping table:\n");
1938 ds_put_cstr(s, " class\ttype\tlength\tmatch field\n");
1939 ds_put_cstr(s, " -----\t----\t------\t-----------");
1940
1941 LIST_FOR_EACH (map, list_node, mappings) {
1942 ds_put_char(s, '\n');
1943 ds_put_format(s, " 0x%"PRIx16"\t0x%"PRIx8"\t%"PRIu8"\ttun_metadata%"PRIu16,
1944 map->option_class, map->option_type, map->option_len,
1945 map->index);
1946 }
1947 }
1948
1949 static enum ofperr
1950 ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
1951 {
1952 int error;
1953 struct ofputil_tlv_table_mod ttm;
1954
1955 error = ofputil_decode_tlv_table_mod(oh, &ttm);
1956 if (error) {
1957 return error;
1958 }
1959
1960 ds_put_cstr(s, "\n ");
1961
1962 switch (ttm.command) {
1963 case NXTTMC_ADD:
1964 ds_put_cstr(s, "ADD");
1965 break;
1966 case NXTTMC_DELETE:
1967 ds_put_cstr(s, "DEL");
1968 break;
1969 case NXTTMC_CLEAR:
1970 ds_put_cstr(s, "CLEAR");
1971 break;
1972 }
1973
1974 if (ttm.command != NXTTMC_CLEAR) {
1975 print_tlv_table(s, &ttm.mappings);
1976 }
1977
1978 ofputil_uninit_tlv_table(&ttm.mappings);
1979
1980 return 0;
1981 }
1982
1983 static enum ofperr
1984 ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
1985 {
1986 int error;
1987 struct ofputil_tlv_table_reply ttr;
1988 struct ofputil_tlv_map *map;
1989 int allocated_space = 0;
1990
1991 error = ofputil_decode_tlv_table_reply(oh, &ttr);
1992 if (error) {
1993 return error;
1994 }
1995
1996 ds_put_char(s, '\n');
1997
1998 LIST_FOR_EACH (map, list_node, &ttr.mappings) {
1999 allocated_space += map->option_len;
2000 }
2001
2002 ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
2003 ttr.max_option_space, ttr.max_fields);
2004 ds_put_format(s, " allocated option space=%d\n", allocated_space);
2005 ds_put_char(s, '\n');
2006 print_tlv_table(s, &ttr.mappings);
2007
2008 ofputil_uninit_tlv_table(&ttr.mappings);
2009
2010 return 0;
2011 }
2012
2013 /* This function will print the request forward message. The reason for
2014 * request forward is taken from rf.request.type */
2015 static enum ofperr
2016 ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
2017 const struct ofputil_port_map *port_map,
2018 const struct ofputil_table_map *table_map)
2019 {
2020 struct ofputil_requestforward rf;
2021 enum ofperr error;
2022
2023 error = ofputil_decode_requestforward(oh, &rf);
2024 if (error) {
2025 return error;
2026 }
2027
2028 ds_put_cstr(string, " reason=");
2029
2030 switch (rf.reason) {
2031 case OFPRFR_GROUP_MOD:
2032 ds_put_cstr(string, "group_mod");
2033 ofp_print_group_mod__(string, oh->version, rf.group_mod, port_map,
2034 table_map);
2035 break;
2036
2037 case OFPRFR_METER_MOD:
2038 ds_put_cstr(string, "meter_mod");
2039 ofp_print_meter_mod__(string, rf.meter_mod);
2040 break;
2041
2042 case OFPRFR_N_REASONS:
2043 OVS_NOT_REACHED();
2044 }
2045 ofputil_destroy_requestforward(&rf);
2046
2047 return 0;
2048 }
2049
2050 static void
2051 print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, int more)
2052 {
2053 ds_put_cstr(string, leader);
2054 if (stat != UINT64_MAX) {
2055 ds_put_format(string, "%"PRIu64, stat);
2056 } else {
2057 ds_put_char(string, '?');
2058 }
2059 if (more) {
2060 ds_put_cstr(string, ", ");
2061 } else {
2062 ds_put_cstr(string, "\n");
2063 }
2064 }
2065
2066 static enum ofperr
2067 ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
2068 {
2069 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2070 for (;;) {
2071 struct ofputil_ipfix_stats is;
2072 int retval;
2073
2074 retval = ofputil_pull_ipfix_stats(&is, &b);
2075 if (retval) {
2076 return retval != EOF ? retval : 0;
2077 }
2078
2079 ds_put_cstr(string, "\n bridge ipfix: ");
2080 print_ipfix_stat(string, "flows=", is.total_flows, 1);
2081 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
2082 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
2083 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
2084 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
2085 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
2086 ds_put_cstr(string, " ");
2087 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
2088 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
2089 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
2090 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
2091 }
2092 }
2093
2094 static enum ofperr
2095 ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
2096 {
2097 ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
2098
2099 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2100 for (;;) {
2101 struct ofputil_ipfix_stats is;
2102 int retval;
2103
2104 retval = ofputil_pull_ipfix_stats(&is, &b);
2105 if (retval) {
2106 return retval != EOF ? retval : 0;
2107 }
2108
2109 ds_put_cstr(string, " id");
2110 ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is.collector_set_id);
2111 print_ipfix_stat(string, "flows=", is.total_flows, 1);
2112 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
2113 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
2114 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
2115 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
2116 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
2117 ds_put_cstr(string, " ");
2118 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
2119 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
2120 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
2121 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
2122 }
2123 }
2124
2125 static enum ofperr
2126 ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
2127 {
2128 ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
2129 return 0;
2130 }
2131
2132 static enum ofperr
2133 ofp_to_string__(const struct ofp_header *oh,
2134 const struct ofputil_port_map *port_map,
2135 const struct ofputil_table_map *table_map, enum ofpraw raw,
2136 struct ds *string, int verbosity)
2137 {
2138 const void *msg = oh;
2139 enum ofptype type = ofptype_from_ofpraw(raw);
2140 switch (type) {
2141 case OFPTYPE_GROUP_STATS_REQUEST:
2142 ofp_print_stats(string, oh);
2143 return ofp_print_ofpst_group_request(string, oh);
2144
2145 case OFPTYPE_GROUP_STATS_REPLY:
2146 return ofp_print_group_stats(string, oh);
2147
2148 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
2149 ofp_print_stats(string, oh);
2150 return ofp_print_ofpst_group_desc_request(string, oh);
2151
2152 case OFPTYPE_GROUP_DESC_STATS_REPLY:
2153 return ofp_print_group_desc(string, oh, port_map, table_map);
2154
2155 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
2156 ofp_print_stats(string, oh);
2157 break;
2158
2159 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
2160 return ofp_print_group_features(string, oh);
2161
2162 case OFPTYPE_GROUP_MOD:
2163 return ofp_print_group_mod(string, oh, port_map, table_map);
2164
2165 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
2166 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
2167 return ofp_print_table_features_reply(string, oh, table_map);
2168
2169 case OFPTYPE_TABLE_DESC_REQUEST:
2170 case OFPTYPE_TABLE_DESC_REPLY:
2171 return ofp_print_table_desc_reply(string, oh, table_map);
2172
2173 case OFPTYPE_HELLO:
2174 return ofp_print_hello(string, oh);
2175
2176 case OFPTYPE_ERROR:
2177 return ofp_print_error_msg(string, oh, port_map, table_map);
2178
2179 case OFPTYPE_ECHO_REQUEST:
2180 case OFPTYPE_ECHO_REPLY:
2181 return ofp_print_echo(string, oh, verbosity);
2182
2183 case OFPTYPE_FEATURES_REQUEST:
2184 break;
2185
2186 case OFPTYPE_FEATURES_REPLY:
2187 return ofp_print_switch_features(string, oh);
2188
2189 case OFPTYPE_GET_CONFIG_REQUEST:
2190 break;
2191
2192 case OFPTYPE_GET_CONFIG_REPLY:
2193 return ofp_print_get_config_reply(string, oh);
2194
2195 case OFPTYPE_SET_CONFIG:
2196 return ofp_print_set_config(string, oh);
2197
2198 case OFPTYPE_PACKET_IN:
2199 return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
2200
2201 case OFPTYPE_FLOW_REMOVED:
2202 return ofp_print_flow_removed(string, oh, port_map, table_map);
2203
2204 case OFPTYPE_PORT_STATUS:
2205 return ofp_print_port_status(string, oh);
2206
2207 case OFPTYPE_PACKET_OUT:
2208 return ofp_print_packet_out(string, oh, port_map, table_map,
2209 verbosity);
2210
2211 case OFPTYPE_FLOW_MOD:
2212 return ofputil_flow_mod_format(string, oh, port_map, table_map,
2213 verbosity);
2214
2215 case OFPTYPE_PORT_MOD:
2216 return ofp_print_port_mod(string, oh, port_map);
2217
2218 case OFPTYPE_TABLE_MOD:
2219 return ofp_print_table_mod(string, oh, table_map);
2220
2221 case OFPTYPE_METER_MOD:
2222 return ofp_print_meter_mod(string, oh);
2223
2224 case OFPTYPE_BARRIER_REQUEST:
2225 case OFPTYPE_BARRIER_REPLY:
2226 break;
2227
2228 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
2229 return ofp_print_queue_get_config_request(string, oh, port_map);
2230
2231 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
2232 return ofp_print_queue_get_config_reply(string, oh, port_map);
2233
2234 case OFPTYPE_ROLE_REQUEST:
2235 case OFPTYPE_ROLE_REPLY:
2236 return ofp_print_role_message(string, oh);
2237 case OFPTYPE_ROLE_STATUS:
2238 return ofp_print_role_status_message(string, oh);
2239
2240 case OFPTYPE_REQUESTFORWARD:
2241 return ofp_print_requestforward(string, oh, port_map, table_map);
2242
2243 case OFPTYPE_TABLE_STATUS:
2244 return ofp_print_table_status_message(string, oh, table_map);
2245
2246 case OFPTYPE_METER_STATS_REQUEST:
2247 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
2248 ofp_print_stats(string, oh);
2249 return ofp_print_meter_stats_request(string, oh);
2250
2251 case OFPTYPE_METER_STATS_REPLY:
2252 ofp_print_stats(string, oh);
2253 return ofp_print_meter_stats_reply(string, oh);
2254
2255 case OFPTYPE_METER_CONFIG_STATS_REPLY:
2256 ofp_print_stats(string, oh);
2257 return ofp_print_meter_config_reply(string, oh);
2258
2259 case OFPTYPE_METER_FEATURES_STATS_REPLY:
2260 ofp_print_stats(string, oh);
2261 return ofp_print_meter_features_reply(string, oh);
2262
2263 case OFPTYPE_DESC_STATS_REQUEST:
2264 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
2265 ofp_print_stats(string, oh);
2266 break;
2267
2268 case OFPTYPE_FLOW_STATS_REQUEST:
2269 case OFPTYPE_AGGREGATE_STATS_REQUEST:
2270 ofp_print_stats(string, oh);
2271 return ofp_print_flow_stats_request(string, oh, port_map, table_map);
2272
2273 case OFPTYPE_TABLE_STATS_REQUEST:
2274 ofp_print_stats(string, oh);
2275 break;
2276
2277 case OFPTYPE_PORT_STATS_REQUEST:
2278 ofp_print_stats(string, oh);
2279 return ofp_print_ofpst_port_request(string, oh, port_map);
2280
2281 case OFPTYPE_QUEUE_STATS_REQUEST:
2282 ofp_print_stats(string, oh);
2283 return ofp_print_ofpst_queue_request(string, oh, port_map);
2284
2285 case OFPTYPE_DESC_STATS_REPLY:
2286 ofp_print_stats(string, oh);
2287 return ofp_print_ofpst_desc_reply(string, oh);
2288
2289 case OFPTYPE_FLOW_STATS_REPLY:
2290 ofp_print_stats(string, oh);
2291 return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
2292
2293 case OFPTYPE_QUEUE_STATS_REPLY:
2294 ofp_print_stats(string, oh);
2295 return ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity);
2296
2297 case OFPTYPE_PORT_STATS_REPLY:
2298 ofp_print_stats(string, oh);
2299 return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
2300
2301 case OFPTYPE_TABLE_STATS_REPLY:
2302 ofp_print_stats(string, oh);
2303 return ofp_print_table_stats_reply(string, oh, table_map);
2304
2305 case OFPTYPE_AGGREGATE_STATS_REPLY:
2306 ofp_print_stats(string, oh);
2307 return ofp_print_aggregate_stats_reply(string, oh);
2308
2309 case OFPTYPE_PORT_DESC_STATS_REQUEST:
2310 ofp_print_stats(string, oh);
2311 return ofp_print_ofpst_port_desc_request(string, oh, port_map);
2312
2313 case OFPTYPE_PORT_DESC_STATS_REPLY:
2314 ofp_print_stats(string, oh);
2315 return ofp_print_ofpst_port_desc_reply(string, oh);
2316
2317 case OFPTYPE_FLOW_MOD_TABLE_ID:
2318 return ofp_print_nxt_flow_mod_table_id(string, oh);
2319
2320 case OFPTYPE_SET_FLOW_FORMAT:
2321 return ofp_print_nxt_set_flow_format(string, oh);
2322
2323 case OFPTYPE_SET_PACKET_IN_FORMAT:
2324 return ofp_print_nxt_set_packet_in_format(string, oh);
2325
2326 case OFPTYPE_FLOW_AGE:
2327 break;
2328
2329 case OFPTYPE_SET_CONTROLLER_ID:
2330 return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
2331
2332 case OFPTYPE_GET_ASYNC_REPLY:
2333 case OFPTYPE_SET_ASYNC_CONFIG:
2334 return ofp_print_set_async_config(string, oh, type);
2335 case OFPTYPE_GET_ASYNC_REQUEST:
2336 break;
2337 case OFPTYPE_FLOW_MONITOR_CANCEL:
2338 return ofp_print_nxt_flow_monitor_cancel(string, msg);
2339
2340 case OFPTYPE_FLOW_MONITOR_PAUSED:
2341 case OFPTYPE_FLOW_MONITOR_RESUMED:
2342 break;
2343
2344 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
2345 return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
2346 table_map);
2347
2348 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
2349 return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
2350 table_map);
2351
2352 case OFPTYPE_BUNDLE_CONTROL:
2353 return ofp_print_bundle_ctrl(string, msg);
2354
2355 case OFPTYPE_BUNDLE_ADD_MESSAGE:
2356 return ofp_print_bundle_add(string, msg, port_map, table_map,
2357 verbosity);
2358
2359 case OFPTYPE_NXT_TLV_TABLE_MOD:
2360 return ofp_print_tlv_table_mod(string, msg);
2361
2362 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
2363 break;
2364
2365 case OFPTYPE_NXT_TLV_TABLE_REPLY:
2366 return ofp_print_tlv_table_reply(string, msg);
2367
2368 case OFPTYPE_NXT_RESUME:
2369 return ofp_print_packet_in(string, msg, port_map, table_map,
2370 verbosity);
2371 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
2372 break;
2373 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
2374 return ofp_print_nxst_ipfix_bridge_reply(string, oh);
2375 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
2376 break;
2377 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
2378 return ofp_print_nxst_ipfix_flow_reply(string, oh);
2379
2380 case OFPTYPE_CT_FLUSH_ZONE:
2381 return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
2382 }
2383
2384 return 0;
2385 }
2386
2387 static void
2388 add_newline(struct ds *s)
2389 {
2390 if (s->length && s->string[s->length - 1] != '\n') {
2391 ds_put_char(s, '\n');
2392 }
2393 }
2394
2395 /* Composes and returns a string representing the OpenFlow packet of 'len'
2396 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
2397 * verbosity and higher numbers increase verbosity. The caller is responsible
2398 * for freeing the string. */
2399 char *
2400 ofp_to_string(const void *oh_, size_t len,
2401 const struct ofputil_port_map *port_map,
2402 const struct ofputil_table_map *table_map,
2403 int verbosity)
2404 {
2405 struct ds string = DS_EMPTY_INITIALIZER;
2406 const struct ofp_header *oh = oh_;
2407
2408 if (!len) {
2409 ds_put_cstr(&string, "OpenFlow message is empty\n");
2410 } else if (len < sizeof(struct ofp_header)) {
2411 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
2412 len);
2413 } else if (ntohs(oh->length) > len) {
2414 enum ofperr error;
2415 enum ofpraw raw;
2416
2417 error = ofpraw_decode_partial(&raw, oh, len);
2418 if (!error) {
2419 ofp_header_to_string__(oh, raw, &string);
2420 ds_put_char(&string, '\n');
2421 }
2422
2423 ds_put_format(&string,
2424 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
2425 len, ntohs(oh->length));
2426 } else if (ntohs(oh->length) < len) {
2427 ds_put_format(&string,
2428 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
2429 ntohs(oh->length), len);
2430 } else {
2431 enum ofperr error;
2432 enum ofpraw raw;
2433
2434 error = ofpraw_decode(&raw, oh);
2435 if (!error) {
2436 ofp_header_to_string__(oh, raw, &string);
2437 size_t header_len = string.length;
2438
2439 error = ofp_to_string__(oh, port_map, table_map,
2440 raw, &string, verbosity);
2441 if (error) {
2442 if (string.length > header_len) {
2443 ds_chomp(&string, ' ');
2444 add_newline(&string);
2445 } else {
2446 ds_put_char(&string, ' ');
2447 }
2448 ofp_print_error(&string, error);
2449 } else {
2450 ds_chomp(&string, ' ');
2451 }
2452 } else {
2453 ofp_print_error(&string, error);
2454 }
2455
2456 if (verbosity >= 5 || error) {
2457 add_newline(&string);
2458 ds_put_hex_dump(&string, oh, len, 0, true);
2459 }
2460
2461 add_newline(&string);
2462 return ds_steal_cstr(&string);
2463 }
2464 ds_put_hex_dump(&string, oh, len, 0, true);
2465 return ds_steal_cstr(&string);
2466 }
2467 \f
2468 static void
2469 print_and_free(FILE *stream, char *string)
2470 {
2471 fputs(string, stream);
2472 free(string);
2473 }
2474
2475 /* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
2476 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
2477 * numbers increase verbosity. */
2478 void
2479 ofp_print(FILE *stream, const void *oh, size_t len,
2480 const struct ofputil_port_map *port_map,
2481 const struct ofputil_table_map *table_map, int verbosity)
2482 {
2483 print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
2484 verbosity));
2485 }
2486
2487 /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
2488 * 'data' to 'stream'. */
2489 void
2490 ofp_print_packet(FILE *stream, const void *data, size_t len,
2491 ovs_be32 packet_type)
2492 {
2493 print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
2494 }
2495
2496 void
2497 ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
2498 {
2499 print_and_free(stream, ofp_dp_packet_to_string(packet));
2500 }