]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-print.c
treewide: Convert leading tabs to spaces.
[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 enum ofperr
1528 ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
1529 const struct ofputil_table_map *table_map)
1530 {
1531 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1532 for (;;) {
1533 struct ofputil_table_desc td;
1534 int retval;
1535
1536 retval = ofputil_decode_table_desc(&b, &td, oh->version);
1537 if (retval) {
1538 return retval != EOF ? retval : 0;
1539 }
1540 ofputil_table_desc_format(s, &td, table_map);
1541 }
1542 }
1543
1544 static const char *
1545 bundle_flags_to_name(uint32_t bit)
1546 {
1547 switch (bit) {
1548 case OFPBF_ATOMIC:
1549 return "atomic";
1550 case OFPBF_ORDERED:
1551 return "ordered";
1552 default:
1553 return NULL;
1554 }
1555 }
1556
1557 static enum ofperr
1558 ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
1559 {
1560 int error;
1561 struct ofputil_bundle_ctrl_msg bctrl;
1562
1563 error = ofputil_decode_bundle_ctrl(oh, &bctrl);
1564 if (error) {
1565 return error;
1566 }
1567
1568 ds_put_char(s, '\n');
1569
1570 ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id);
1571 switch (bctrl.type) {
1572 case OFPBCT_OPEN_REQUEST:
1573 ds_put_cstr(s, "OPEN_REQUEST");
1574 break;
1575 case OFPBCT_OPEN_REPLY:
1576 ds_put_cstr(s, "OPEN_REPLY");
1577 break;
1578 case OFPBCT_CLOSE_REQUEST:
1579 ds_put_cstr(s, "CLOSE_REQUEST");
1580 break;
1581 case OFPBCT_CLOSE_REPLY:
1582 ds_put_cstr(s, "CLOSE_REPLY");
1583 break;
1584 case OFPBCT_COMMIT_REQUEST:
1585 ds_put_cstr(s, "COMMIT_REQUEST");
1586 break;
1587 case OFPBCT_COMMIT_REPLY:
1588 ds_put_cstr(s, "COMMIT_REPLY");
1589 break;
1590 case OFPBCT_DISCARD_REQUEST:
1591 ds_put_cstr(s, "DISCARD_REQUEST");
1592 break;
1593 case OFPBCT_DISCARD_REPLY:
1594 ds_put_cstr(s, "DISCARD_REPLY");
1595 break;
1596 }
1597
1598 ds_put_cstr(s, " flags=");
1599 ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' ');
1600
1601 return 0;
1602 }
1603
1604 static enum ofperr
1605 ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
1606 const struct ofputil_port_map *port_map,
1607 const struct ofputil_table_map *table_map,
1608 int verbosity)
1609 {
1610 int error;
1611 struct ofputil_bundle_add_msg badd;
1612
1613 error = ofputil_decode_bundle_add(oh, &badd, NULL);
1614 if (error) {
1615 return error;
1616 }
1617
1618 ds_put_char(s, '\n');
1619 ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id);
1620 ds_put_cstr(s, " flags=");
1621 ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' ');
1622
1623 ds_put_char(s, '\n');
1624 char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map,
1625 table_map, verbosity);
1626 ds_put_and_free_cstr(s, msg);
1627
1628 return 0;
1629 }
1630
1631 static void
1632 print_tlv_table(struct ds *s, struct ovs_list *mappings)
1633 {
1634 struct ofputil_tlv_map *map;
1635
1636 ds_put_cstr(s, " mapping table:\n");
1637 ds_put_cstr(s, " class type length match field\n");
1638 ds_put_cstr(s, " ------ ---- ------ --------------");
1639
1640 LIST_FOR_EACH (map, list_node, mappings) {
1641 ds_put_format(s, "\n %#6"PRIx16" %#4"PRIx8" %6"PRIu8" "
1642 "tun_metadata%"PRIu16,
1643 map->option_class, map->option_type, map->option_len,
1644 map->index);
1645 }
1646 }
1647
1648 static enum ofperr
1649 ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
1650 {
1651 int error;
1652 struct ofputil_tlv_table_mod ttm;
1653
1654 error = ofputil_decode_tlv_table_mod(oh, &ttm);
1655 if (error) {
1656 return error;
1657 }
1658
1659 ds_put_cstr(s, "\n ");
1660
1661 switch (ttm.command) {
1662 case NXTTMC_ADD:
1663 ds_put_cstr(s, "ADD");
1664 break;
1665 case NXTTMC_DELETE:
1666 ds_put_cstr(s, "DEL");
1667 break;
1668 case NXTTMC_CLEAR:
1669 ds_put_cstr(s, "CLEAR");
1670 break;
1671 }
1672
1673 if (ttm.command != NXTTMC_CLEAR) {
1674 print_tlv_table(s, &ttm.mappings);
1675 }
1676
1677 ofputil_uninit_tlv_table(&ttm.mappings);
1678
1679 return 0;
1680 }
1681
1682 static enum ofperr
1683 ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
1684 {
1685 int error;
1686 struct ofputil_tlv_table_reply ttr;
1687 struct ofputil_tlv_map *map;
1688 int allocated_space = 0;
1689
1690 error = ofputil_decode_tlv_table_reply(oh, &ttr);
1691 if (error) {
1692 return error;
1693 }
1694
1695 ds_put_char(s, '\n');
1696
1697 LIST_FOR_EACH (map, list_node, &ttr.mappings) {
1698 allocated_space += map->option_len;
1699 }
1700
1701 ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
1702 ttr.max_option_space, ttr.max_fields);
1703 ds_put_format(s, " allocated option space=%d\n", allocated_space);
1704 ds_put_char(s, '\n');
1705 print_tlv_table(s, &ttr.mappings);
1706
1707 ofputil_uninit_tlv_table(&ttr.mappings);
1708
1709 return 0;
1710 }
1711
1712 /* This function will print the request forward message. The reason for
1713 * request forward is taken from rf.request.type */
1714 static enum ofperr
1715 ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
1716 const struct ofputil_port_map *port_map,
1717 const struct ofputil_table_map *table_map)
1718 {
1719 struct ofputil_requestforward rf;
1720 enum ofperr error;
1721
1722 error = ofputil_decode_requestforward(oh, &rf);
1723 if (error) {
1724 return error;
1725 }
1726
1727 ds_put_cstr(string, " reason=");
1728
1729 switch (rf.reason) {
1730 case OFPRFR_GROUP_MOD:
1731 ds_put_cstr(string, "group_mod");
1732 ofputil_group_mod_format__(string, oh->version, rf.group_mod, port_map,
1733 table_map);
1734 break;
1735
1736 case OFPRFR_METER_MOD:
1737 ds_put_cstr(string, "meter_mod");
1738 ofp_print_meter_mod__(string, rf.meter_mod);
1739 break;
1740
1741 case OFPRFR_N_REASONS:
1742 OVS_NOT_REACHED();
1743 }
1744 ofputil_destroy_requestforward(&rf);
1745
1746 return 0;
1747 }
1748
1749 static void
1750 print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, int more)
1751 {
1752 ds_put_cstr(string, leader);
1753 if (stat != UINT64_MAX) {
1754 ds_put_format(string, "%"PRIu64, stat);
1755 } else {
1756 ds_put_char(string, '?');
1757 }
1758 if (more) {
1759 ds_put_cstr(string, ", ");
1760 } else {
1761 ds_put_cstr(string, "\n");
1762 }
1763 }
1764
1765 static enum ofperr
1766 ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
1767 {
1768 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1769 for (;;) {
1770 struct ofputil_ipfix_stats is;
1771 int retval;
1772
1773 retval = ofputil_pull_ipfix_stats(&is, &b);
1774 if (retval) {
1775 return retval != EOF ? retval : 0;
1776 }
1777
1778 ds_put_cstr(string, "\n bridge ipfix: ");
1779 print_ipfix_stat(string, "flows=", is.total_flows, 1);
1780 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
1781 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
1782 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
1783 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
1784 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
1785 ds_put_cstr(string, " ");
1786 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
1787 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
1788 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
1789 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
1790 }
1791 }
1792
1793 static enum ofperr
1794 ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
1795 {
1796 ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
1797
1798 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1799 for (;;) {
1800 struct ofputil_ipfix_stats is;
1801 int retval;
1802
1803 retval = ofputil_pull_ipfix_stats(&is, &b);
1804 if (retval) {
1805 return retval != EOF ? retval : 0;
1806 }
1807
1808 ds_put_cstr(string, " id");
1809 ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is.collector_set_id);
1810 print_ipfix_stat(string, "flows=", is.total_flows, 1);
1811 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
1812 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
1813 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
1814 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
1815 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
1816 ds_put_cstr(string, " ");
1817 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
1818 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
1819 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
1820 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
1821 }
1822 }
1823
1824 static enum ofperr
1825 ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
1826 {
1827 ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
1828 return 0;
1829 }
1830
1831 static enum ofperr
1832 ofp_to_string__(const struct ofp_header *oh,
1833 const struct ofputil_port_map *port_map,
1834 const struct ofputil_table_map *table_map, enum ofpraw raw,
1835 struct ds *string, int verbosity)
1836 {
1837 if (ofpmsg_is_stat(oh)) {
1838 ofp_print_stats(string, oh);
1839 }
1840
1841 const void *msg = oh;
1842 enum ofptype type = ofptype_from_ofpraw(raw);
1843 switch (type) {
1844 case OFPTYPE_GROUP_STATS_REQUEST:
1845 return ofputil_group_stats_request_format(string, oh);
1846
1847 case OFPTYPE_GROUP_STATS_REPLY:
1848 return ofputil_group_stats_format(string, oh);
1849
1850 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
1851 return ofputil_group_desc_request_format(string, oh);
1852
1853 case OFPTYPE_GROUP_DESC_STATS_REPLY:
1854 return ofputil_group_desc_format(string, oh, port_map, table_map);
1855
1856 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
1857 break;
1858
1859 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
1860 return ofputil_group_features_format(string, oh);
1861
1862 case OFPTYPE_GROUP_MOD:
1863 return ofputil_group_mod_format(string, oh, port_map, table_map);
1864
1865 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
1866 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
1867 return ofp_print_table_features_reply(string, oh, table_map);
1868
1869 case OFPTYPE_TABLE_DESC_REQUEST:
1870 case OFPTYPE_TABLE_DESC_REPLY:
1871 return ofp_print_table_desc_reply(string, oh, table_map);
1872
1873 case OFPTYPE_HELLO:
1874 return ofp_print_hello(string, oh);
1875
1876 case OFPTYPE_ERROR:
1877 return ofp_print_error_msg(string, oh, port_map, table_map);
1878
1879 case OFPTYPE_ECHO_REQUEST:
1880 case OFPTYPE_ECHO_REPLY:
1881 return ofp_print_echo(string, oh, verbosity);
1882
1883 case OFPTYPE_FEATURES_REQUEST:
1884 break;
1885
1886 case OFPTYPE_FEATURES_REPLY:
1887 return ofp_print_switch_features(string, oh);
1888
1889 case OFPTYPE_GET_CONFIG_REQUEST:
1890 break;
1891
1892 case OFPTYPE_GET_CONFIG_REPLY:
1893 return ofp_print_get_config_reply(string, oh);
1894
1895 case OFPTYPE_SET_CONFIG:
1896 return ofp_print_set_config(string, oh);
1897
1898 case OFPTYPE_PACKET_IN:
1899 return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
1900
1901 case OFPTYPE_FLOW_REMOVED:
1902 return ofp_print_flow_removed(string, oh, port_map, table_map);
1903
1904 case OFPTYPE_PORT_STATUS:
1905 return ofp_print_port_status(string, oh);
1906
1907 case OFPTYPE_PACKET_OUT:
1908 return ofp_print_packet_out(string, oh, port_map, table_map,
1909 verbosity);
1910
1911 case OFPTYPE_FLOW_MOD:
1912 return ofputil_flow_mod_format(string, oh, port_map, table_map,
1913 verbosity);
1914
1915 case OFPTYPE_PORT_MOD:
1916 return ofp_print_port_mod(string, oh, port_map);
1917
1918 case OFPTYPE_TABLE_MOD:
1919 return ofp_print_table_mod(string, oh, table_map);
1920
1921 case OFPTYPE_METER_MOD:
1922 return ofp_print_meter_mod(string, oh);
1923
1924 case OFPTYPE_BARRIER_REQUEST:
1925 case OFPTYPE_BARRIER_REPLY:
1926 break;
1927
1928 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
1929 return ofp_print_queue_get_config_request(string, oh, port_map);
1930
1931 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
1932 return ofp_print_queue_get_config_reply(string, oh, port_map);
1933
1934 case OFPTYPE_ROLE_REQUEST:
1935 case OFPTYPE_ROLE_REPLY:
1936 return ofp_print_role_message(string, oh);
1937 case OFPTYPE_ROLE_STATUS:
1938 return ofp_print_role_status_message(string, oh);
1939
1940 case OFPTYPE_REQUESTFORWARD:
1941 return ofp_print_requestforward(string, oh, port_map, table_map);
1942
1943 case OFPTYPE_TABLE_STATUS:
1944 return ofp_print_table_status_message(string, oh, table_map);
1945
1946 case OFPTYPE_METER_STATS_REQUEST:
1947 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
1948 return ofp_print_meter_stats_request(string, oh);
1949
1950 case OFPTYPE_METER_STATS_REPLY:
1951 return ofp_print_meter_stats_reply(string, oh);
1952
1953 case OFPTYPE_METER_CONFIG_STATS_REPLY:
1954 return ofp_print_meter_config_reply(string, oh);
1955
1956 case OFPTYPE_METER_FEATURES_STATS_REPLY:
1957 return ofp_print_meter_features_reply(string, oh);
1958
1959 case OFPTYPE_DESC_STATS_REQUEST:
1960 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
1961 break;
1962
1963 case OFPTYPE_FLOW_STATS_REQUEST:
1964 case OFPTYPE_AGGREGATE_STATS_REQUEST:
1965 return ofp_print_flow_stats_request(string, oh, port_map, table_map);
1966
1967 case OFPTYPE_TABLE_STATS_REQUEST:
1968 break;
1969
1970 case OFPTYPE_PORT_STATS_REQUEST:
1971 return ofp_print_ofpst_port_request(string, oh, port_map);
1972
1973 case OFPTYPE_QUEUE_STATS_REQUEST:
1974 return ofp_print_ofpst_queue_request(string, oh, port_map);
1975
1976 case OFPTYPE_DESC_STATS_REPLY:
1977 return ofp_print_ofpst_desc_reply(string, oh);
1978
1979 case OFPTYPE_FLOW_STATS_REPLY:
1980 return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
1981
1982 case OFPTYPE_QUEUE_STATS_REPLY:
1983 return ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity);
1984
1985 case OFPTYPE_PORT_STATS_REPLY:
1986 return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
1987
1988 case OFPTYPE_TABLE_STATS_REPLY:
1989 return ofp_print_table_stats_reply(string, oh, table_map);
1990
1991 case OFPTYPE_AGGREGATE_STATS_REPLY:
1992 return ofp_print_aggregate_stats_reply(string, oh);
1993
1994 case OFPTYPE_PORT_DESC_STATS_REQUEST:
1995 return ofp_print_ofpst_port_desc_request(string, oh, port_map);
1996
1997 case OFPTYPE_PORT_DESC_STATS_REPLY:
1998 return ofp_print_ofpst_port_desc_reply(string, oh);
1999
2000 case OFPTYPE_FLOW_MOD_TABLE_ID:
2001 return ofp_print_nxt_flow_mod_table_id(string, oh);
2002
2003 case OFPTYPE_SET_FLOW_FORMAT:
2004 return ofp_print_nxt_set_flow_format(string, oh);
2005
2006 case OFPTYPE_SET_PACKET_IN_FORMAT:
2007 return ofp_print_nxt_set_packet_in_format(string, oh);
2008
2009 case OFPTYPE_FLOW_AGE:
2010 break;
2011
2012 case OFPTYPE_SET_CONTROLLER_ID:
2013 return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
2014
2015 case OFPTYPE_GET_ASYNC_REPLY:
2016 case OFPTYPE_SET_ASYNC_CONFIG:
2017 return ofp_print_set_async_config(string, oh, type);
2018 case OFPTYPE_GET_ASYNC_REQUEST:
2019 break;
2020 case OFPTYPE_FLOW_MONITOR_CANCEL:
2021 return ofp_print_nxt_flow_monitor_cancel(string, msg);
2022
2023 case OFPTYPE_FLOW_MONITOR_PAUSED:
2024 case OFPTYPE_FLOW_MONITOR_RESUMED:
2025 break;
2026
2027 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
2028 return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
2029 table_map);
2030
2031 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
2032 return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
2033 table_map);
2034
2035 case OFPTYPE_BUNDLE_CONTROL:
2036 return ofp_print_bundle_ctrl(string, msg);
2037
2038 case OFPTYPE_BUNDLE_ADD_MESSAGE:
2039 return ofp_print_bundle_add(string, msg, port_map, table_map,
2040 verbosity);
2041
2042 case OFPTYPE_NXT_TLV_TABLE_MOD:
2043 return ofp_print_tlv_table_mod(string, msg);
2044
2045 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
2046 break;
2047
2048 case OFPTYPE_NXT_TLV_TABLE_REPLY:
2049 return ofp_print_tlv_table_reply(string, msg);
2050
2051 case OFPTYPE_NXT_RESUME:
2052 return ofp_print_packet_in(string, msg, port_map, table_map,
2053 verbosity);
2054 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
2055 break;
2056 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
2057 return ofp_print_nxst_ipfix_bridge_reply(string, oh);
2058 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
2059 break;
2060 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
2061 return ofp_print_nxst_ipfix_flow_reply(string, oh);
2062
2063 case OFPTYPE_CT_FLUSH_ZONE:
2064 return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
2065 }
2066
2067 return 0;
2068 }
2069
2070 static void
2071 add_newline(struct ds *s)
2072 {
2073 if (s->length && s->string[s->length - 1] != '\n') {
2074 ds_put_char(s, '\n');
2075 }
2076 }
2077
2078 /* Composes and returns a string representing the OpenFlow packet of 'len'
2079 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
2080 * verbosity and higher numbers increase verbosity. The caller is responsible
2081 * for freeing the string. */
2082 char *
2083 ofp_to_string(const void *oh_, size_t len,
2084 const struct ofputil_port_map *port_map,
2085 const struct ofputil_table_map *table_map,
2086 int verbosity)
2087 {
2088 struct ds string = DS_EMPTY_INITIALIZER;
2089 const struct ofp_header *oh = oh_;
2090
2091 if (!len) {
2092 ds_put_cstr(&string, "OpenFlow message is empty\n");
2093 } else if (len < sizeof(struct ofp_header)) {
2094 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
2095 len);
2096 } else if (ntohs(oh->length) > len) {
2097 enum ofperr error;
2098 enum ofpraw raw;
2099
2100 error = ofpraw_decode_partial(&raw, oh, len);
2101 if (!error) {
2102 ofp_header_to_string__(oh, raw, &string);
2103 ds_put_char(&string, '\n');
2104 }
2105
2106 ds_put_format(&string,
2107 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
2108 len, ntohs(oh->length));
2109 } else if (ntohs(oh->length) < len) {
2110 ds_put_format(&string,
2111 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
2112 ntohs(oh->length), len);
2113 } else {
2114 enum ofperr error;
2115 enum ofpraw raw;
2116
2117 error = ofpraw_decode(&raw, oh);
2118 if (!error) {
2119 ofp_header_to_string__(oh, raw, &string);
2120 size_t header_len = string.length;
2121
2122 error = ofp_to_string__(oh, port_map, table_map,
2123 raw, &string, verbosity);
2124 if (error) {
2125 if (string.length > header_len) {
2126 ds_chomp(&string, ' ');
2127 add_newline(&string);
2128 } else {
2129 ds_put_char(&string, ' ');
2130 }
2131 ofp_print_error(&string, error);
2132 } else {
2133 ds_chomp(&string, ' ');
2134 }
2135 } else {
2136 ofp_print_error(&string, error);
2137 }
2138
2139 if (verbosity >= 5 || error) {
2140 add_newline(&string);
2141 ds_put_hex_dump(&string, oh, len, 0, true);
2142 }
2143
2144 add_newline(&string);
2145 return ds_steal_cstr(&string);
2146 }
2147 ds_put_hex_dump(&string, oh, len, 0, true);
2148 return ds_steal_cstr(&string);
2149 }
2150 \f
2151 static void
2152 print_and_free(FILE *stream, char *string)
2153 {
2154 fputs(string, stream);
2155 free(string);
2156 }
2157
2158 /* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
2159 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
2160 * numbers increase verbosity. */
2161 void
2162 ofp_print(FILE *stream, const void *oh, size_t len,
2163 const struct ofputil_port_map *port_map,
2164 const struct ofputil_table_map *table_map, int verbosity)
2165 {
2166 print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
2167 verbosity));
2168 }
2169
2170 /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
2171 * 'data' to 'stream'. */
2172 void
2173 ofp_print_packet(FILE *stream, const void *data, size_t len,
2174 ovs_be32 packet_type)
2175 {
2176 print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
2177 }
2178
2179 void
2180 ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
2181 {
2182 print_and_free(stream, ofp_dp_packet_to_string(packet));
2183 }