]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-print.c
ovsdb-idl: Improve prototypes.
[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_error(struct ds *, enum ofperr);
68
69 /* Returns a string that represents the contents of the Ethernet frame in the
70 * 'len' bytes starting at 'data'. The caller must free the returned string.*/
71 char *
72 ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
73 {
74 struct ds ds = DS_EMPTY_INITIALIZER;
75 struct dp_packet buf;
76 struct flow flow;
77 size_t l4_size;
78
79 dp_packet_use_const(&buf, data, len);
80 buf.packet_type = packet_type;
81 flow_extract(&buf, &flow);
82 flow_format(&ds, &flow, NULL);
83
84 l4_size = dp_packet_l4_size(&buf);
85
86 if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
87 struct tcp_header *th = dp_packet_l4(&buf);
88 ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum));
89 } else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
90 struct udp_header *uh = dp_packet_l4(&buf);
91 ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum));
92 } else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) {
93 struct sctp_header *sh = dp_packet_l4(&buf);
94 ds_put_format(&ds, " sctp_csum:%"PRIx32,
95 ntohl(get_16aligned_be32(&sh->sctp_csum)));
96 } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
97 struct icmp_header *icmph = dp_packet_l4(&buf);
98 ds_put_format(&ds, " icmp_csum:%"PRIx16,
99 ntohs(icmph->icmp_csum));
100 } else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= ICMP6_HEADER_LEN) {
101 struct icmp6_header *icmp6h = dp_packet_l4(&buf);
102 ds_put_format(&ds, " icmp6_csum:%"PRIx16,
103 ntohs(icmp6h->icmp6_cksum));
104 }
105
106 ds_put_char(&ds, '\n');
107
108 return ds_cstr(&ds);
109 }
110
111 char *
112 ofp_dp_packet_to_string(const struct dp_packet *packet)
113 {
114 return ofp_packet_to_string(dp_packet_data(packet),
115 dp_packet_size(packet),
116 packet->packet_type);
117 }
118
119 static enum ofperr
120 ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
121 const struct ofputil_port_map *port_map,
122 const struct ofputil_table_map *table_map, int verbosity)
123 {
124 struct ofputil_packet_in_private pin;
125 uint32_t buffer_id;
126 size_t total_len;
127 enum ofperr error = ofputil_decode_packet_in_private(oh, true, NULL, NULL,
128 &pin, &total_len,
129 &buffer_id);
130 if (!error) {
131 ofputil_packet_in_private_format(string, &pin, total_len, buffer_id,
132 port_map, table_map, verbosity);
133 ofputil_packet_in_private_destroy(&pin);
134 }
135 return error;
136 }
137
138 static enum ofperr
139 ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
140 const struct ofputil_port_map *port_map,
141 const struct ofputil_table_map *table_map, int verbosity)
142 {
143 struct ofputil_packet_out po;
144 struct ofpbuf ofpacts;
145 enum ofperr error;
146
147 ofpbuf_init(&ofpacts, 64);
148 error = ofputil_decode_packet_out(&po, oh, NULL, &ofpacts);
149 if (!error) {
150 ofputil_packet_out_format(string, &po, port_map, table_map, verbosity);
151 }
152 ofpbuf_uninit(&ofpacts);
153 return error;
154 }
155
156 void
157 ofp_print_bit_names(struct ds *string, uint32_t bits,
158 const char *(*bit_to_name)(uint32_t bit),
159 char separator)
160 {
161 int n = 0;
162 int i;
163
164 if (!bits) {
165 ds_put_cstr(string, "0");
166 return;
167 }
168
169 for (i = 0; i < 32; i++) {
170 uint32_t bit = UINT32_C(1) << i;
171
172 if (bits & bit) {
173 const char *name = bit_to_name(bit);
174 if (name) {
175 if (n++) {
176 ds_put_char(string, separator);
177 }
178 ds_put_cstr(string, name);
179 bits &= ~bit;
180 }
181 }
182 }
183
184 if (bits) {
185 if (n) {
186 ds_put_char(string, separator);
187 }
188 ds_put_format(string, "0x%"PRIx32, bits);
189 }
190 }
191
192 static enum ofperr
193 ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
194 {
195 struct ofputil_switch_features features;
196 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
197 enum ofperr error = ofputil_pull_switch_features(&b, &features);
198 if (!error) {
199 ofputil_switch_features_format(string, &features);
200 error = ofputil_phy_ports_format(string, oh->version, &b);
201 }
202 return error;
203 }
204
205 static enum ofperr
206 ofp_print_set_config(struct ds *string, const struct ofp_header *oh)
207 {
208 struct ofputil_switch_config config;
209 enum ofperr error;
210
211 error = ofputil_decode_set_config(oh, &config);
212 if (error) {
213 return error;
214 }
215 ofputil_switch_config_format(string, &config);
216 return 0;
217 }
218
219 static enum ofperr
220 ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh)
221 {
222 struct ofputil_switch_config config;
223 ofputil_decode_get_config_reply(oh, &config);
224 ofputil_switch_config_format(string, &config);
225 return 0;
226 }
227
228 static enum ofperr
229 ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh)
230 {
231 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
232
233 struct ofputil_table_features prev;
234 int first_ditto = -1, last_ditto = -1;
235 for (int i = 0; ; i++) {
236 struct ofputil_table_features tf;
237 struct ofpbuf raw_properties;
238 int retval = ofputil_decode_table_features(&b, &tf, &raw_properties);
239 if (retval) {
240 ofputil_table_features_format_finish(s, first_ditto, last_ditto);
241 return retval != EOF ? retval : 0;
242 }
243
244 ofputil_table_features_format(s, &tf, i ? &prev : NULL, NULL, NULL,
245 &first_ditto, &last_ditto);
246 prev = tf;
247 }
248 }
249
250 void
251 ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
252 {
253 ds_put_format(string, "%u", sec);
254
255 /* If there are no fractional seconds, don't print any decimals.
256 *
257 * If the fractional seconds can be expressed exactly as milliseconds,
258 * print 3 decimals. Open vSwitch provides millisecond precision for most
259 * time measurements, so printing 3 decimals every time makes it easier to
260 * spot real changes in flow dumps that refresh themselves quickly.
261 *
262 * If the fractional seconds are more precise than milliseconds, print the
263 * number of decimals needed to express them exactly.
264 */
265 if (nsec > 0) {
266 unsigned int msec = nsec / 1000000;
267 if (msec * 1000000 == nsec) {
268 ds_put_format(string, ".%03u", msec);
269 } else {
270 ds_put_format(string, ".%09u", nsec);
271 while (string->string[string->length - 1] == '0') {
272 string->length--;
273 }
274 }
275 }
276 ds_put_char(string, 's');
277 }
278
279 static enum ofperr
280 ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh,
281 const struct ofputil_port_map *port_map,
282 const struct ofputil_table_map *table_map)
283 {
284 struct ofputil_flow_removed fr;
285 enum ofperr error = ofputil_decode_flow_removed(&fr, oh);
286 if (!error) {
287 ofputil_flow_removed_format(string, &fr, port_map, table_map);
288 }
289 return error;
290 }
291
292 static enum ofperr
293 ofp_print_port_mod(struct ds *string, const struct ofp_header *oh,
294 const struct ofputil_port_map *port_map)
295 {
296 struct ofputil_port_mod pm;
297 enum ofperr error = ofputil_decode_port_mod(oh, &pm, true);
298 if (!error) {
299 ofputil_port_mod_format(string, &pm, port_map);
300 }
301 return error;
302 }
303
304 static enum ofperr
305 ofp_print_table_mod(struct ds *string, const struct ofp_header *oh,
306 const struct ofputil_table_map *table_map)
307 {
308 struct ofputil_table_mod tm;
309 enum ofperr error = ofputil_decode_table_mod(oh, &tm);
310 if (!error) {
311 ofputil_table_mod_format(string, &tm, table_map);
312 }
313 return error;
314 }
315
316 static enum ofperr
317 ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh,
318 const struct ofputil_table_map *table_map)
319 {
320 struct ofputil_table_status ts;
321 enum ofperr error = ofputil_decode_table_status(oh, &ts);
322 if (!error) {
323 ofputil_format_table_status(string, &ts, table_map);
324 }
325 return error;
326 }
327
328 static enum ofperr
329 ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh)
330 {
331 struct ofputil_meter_mod mm;
332 struct ofpbuf bands;
333
334 ofpbuf_init(&bands, 64);
335 enum ofperr error = ofputil_decode_meter_mod(oh, &mm, &bands);
336 if (!error) {
337 ofputil_format_meter_mod(s, &mm);
338 }
339 ofpbuf_uninit(&bands);
340
341 return error;
342 }
343
344 static enum ofperr
345 ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh)
346 {
347 uint32_t meter_id;
348
349 ofputil_decode_meter_request(oh, &meter_id);
350 ds_put_char(s, ' ');
351
352 ofputil_format_meter_id(s, meter_id, '=');
353
354 return 0;
355 }
356
357 static enum ofperr
358 ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
359 {
360 struct ofputil_meter_features mf;
361 ofputil_decode_meter_features(oh, &mf);
362 ofputil_format_meter_features(s, &mf);
363 return 0;
364 }
365
366 static enum ofperr
367 ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
368 {
369 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
370 struct ofpbuf bands;
371 int retval;
372
373 ofpbuf_init(&bands, 64);
374 for (;;) {
375 struct ofputil_meter_config mc;
376
377 retval = ofputil_decode_meter_config(&b, &mc, &bands);
378 if (retval) {
379 break;
380 }
381 ds_put_char(s, '\n');
382 ofputil_format_meter_config(s, &mc);
383 }
384 ofpbuf_uninit(&bands);
385
386 return retval != EOF ? retval : 0;
387 }
388
389 static enum ofperr
390 ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
391 {
392 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
393 struct ofpbuf bands;
394 int retval;
395
396 ofpbuf_init(&bands, 64);
397 for (;;) {
398 struct ofputil_meter_stats ms;
399
400 retval = ofputil_decode_meter_stats(&b, &ms, &bands);
401 if (retval) {
402 break;
403 }
404 ds_put_char(s, '\n');
405 ofputil_format_meter_stats(s, &ms);
406 }
407 ofpbuf_uninit(&bands);
408
409 return retval != EOF ? retval : 0;
410 }
411
412 static void
413 ofp_print_error(struct ds *string, enum ofperr error)
414 {
415 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
416 }
417
418 static enum ofperr
419 ofp_print_hello(struct ds *string, const struct ofp_header *oh)
420 {
421 ofputil_hello_format(string, oh);
422 return 0;
423 }
424
425 static enum ofperr
426 ofp_print_error_msg(struct ds *string, const struct ofp_header *oh,
427 const struct ofputil_port_map *port_map,
428 const struct ofputil_table_map *table_map)
429 {
430 struct ofpbuf payload;
431 enum ofperr error = ofperr_decode_msg(oh, &payload);
432 if (!error) {
433 return OFPERR_OFPBRC_BAD_LEN;
434 }
435 ofperr_msg_format(string, error, &payload, port_map, table_map);
436 ofpbuf_uninit(&payload);
437
438 return 0;
439 }
440
441 static enum ofperr
442 ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
443 {
444 struct ofputil_port_status ps;
445 enum ofperr error = ofputil_decode_port_status(oh, &ps);
446 if (!error) {
447 ofputil_port_status_format(string, &ps);
448 }
449 return error;
450 }
451
452 static enum ofperr
453 ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
454 {
455 const struct ofp_desc_stats *ods = ofpmsg_body(oh);
456
457 ds_put_char(string, '\n');
458 ds_put_format(string, "Manufacturer: %.*s\n",
459 (int) sizeof ods->mfr_desc, ods->mfr_desc);
460 ds_put_format(string, "Hardware: %.*s\n",
461 (int) sizeof ods->hw_desc, ods->hw_desc);
462 ds_put_format(string, "Software: %.*s\n",
463 (int) sizeof ods->sw_desc, ods->sw_desc);
464 ds_put_format(string, "Serial Num: %.*s\n",
465 (int) sizeof ods->serial_num, ods->serial_num);
466 ds_put_format(string, "DP Description: %.*s\n",
467 (int) sizeof ods->dp_desc, ods->dp_desc);
468
469 return 0;
470 }
471
472 static enum ofperr
473 ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh,
474 const struct ofputil_port_map *port_map,
475 const struct ofputil_table_map *table_map)
476 {
477 struct ofputil_flow_stats_request fsr;
478 enum ofperr error = ofputil_decode_flow_stats_request(&fsr, oh, NULL,
479 NULL);
480 if (!error) {
481 ofputil_flow_stats_request_format(string, &fsr, port_map, table_map);
482 }
483 return error;
484 }
485
486 static enum ofperr
487 ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
488 const struct ofputil_port_map *port_map,
489 const struct ofputil_table_map *table_map)
490 {
491 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
492 struct ofpbuf ofpacts;
493 int retval;
494
495 ofpbuf_init(&ofpacts, 64);
496 for (;;) {
497 struct ofputil_flow_stats fs;
498
499 retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
500 if (retval) {
501 break;
502 }
503 ds_put_cstr(string, "\n ");
504 ofputil_flow_stats_format(string, &fs, port_map, table_map, true);
505 }
506 ofpbuf_uninit(&ofpacts);
507
508 return retval != EOF ? retval : 0;
509 }
510
511 static enum ofperr
512 ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
513 {
514 struct ofputil_aggregate_stats as;
515 enum ofperr error;
516
517 error = ofputil_decode_aggregate_stats_reply(&as, oh);
518 if (!error) {
519 ofputil_aggregate_stats_format(string, &as);
520 }
521 return error;
522 }
523
524 static enum ofperr
525 ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh,
526 const struct ofputil_port_map *port_map)
527 {
528 ofp_port_t ofp10_port;
529 enum ofperr error;
530
531 error = ofputil_decode_port_stats_request(oh, &ofp10_port);
532 if (error) {
533 return error;
534 }
535
536 ds_put_cstr(string, " port_no=");
537 ofputil_format_port(ofp10_port, port_map, string);
538
539 return 0;
540 }
541
542 static enum ofperr
543 ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
544 const struct ofputil_port_map *port_map,
545 int verbosity)
546 {
547 ds_put_format(string, " %"PRIuSIZE" ports\n",
548 ofputil_count_port_stats(oh));
549 if (verbosity < 1) {
550 return 0;
551 }
552
553 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
554 for (;;) {
555 struct ofputil_port_stats ps;
556 int retval;
557
558 retval = ofputil_decode_port_stats(&ps, &b);
559 if (retval) {
560 return retval != EOF ? retval : 0;
561 }
562 ofputil_format_port_stats(string, &ps, port_map);
563 netdev_free_custom_stats_counters(&ps.custom_stats);
564 }
565 }
566
567 static enum ofperr
568 ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh)
569 {
570 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
571 ofpraw_pull_assert(&b);
572
573 struct ofputil_table_features prev_features;
574 struct ofputil_table_stats prev_stats;
575 int first_ditto = -1, last_ditto = -1;
576 for (int i = 0;; i++) {
577 struct ofputil_table_features features;
578 struct ofputil_table_stats stats;
579 int retval;
580
581 retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
582 if (retval) {
583 ofputil_table_features_format_finish(string,
584 first_ditto, last_ditto);
585 return retval != EOF ? retval : 0;
586 }
587
588 ofputil_table_features_format(string,
589 &features, i ? &prev_features : NULL,
590 &stats, i ? &prev_stats : NULL,
591 &first_ditto, &last_ditto);
592 prev_features = features;
593 prev_stats = stats;
594 }
595 }
596
597 static enum ofperr
598 ofp_print_ofpst_port_desc_request(struct ds *string,
599 const struct ofp_header *oh,
600 const struct ofputil_port_map *port_map)
601 {
602 enum ofperr error;
603 ofp_port_t port;
604
605 error = ofputil_decode_port_desc_stats_request(oh, &port);
606 if (error) {
607 return error;
608 }
609
610 ds_put_cstr(string, " port=");
611 ofputil_format_port(port, port_map, string);
612
613 return 0;
614 }
615
616 static enum ofperr
617 ofp_print_ofpst_port_desc_reply(struct ds *string,
618 const struct ofp_header *oh)
619 {
620 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
621 ofpraw_pull_assert(&b);
622 ds_put_char(string, '\n');
623 return ofputil_phy_ports_format(string, oh->version, &b);
624 }
625
626 static void
627 ofp_print_stats(struct ds *string, const struct ofp_header *oh)
628 {
629 uint16_t flags = ofpmp_flags(oh);
630
631 if (flags) {
632 ds_put_cstr(string, " flags=");
633 if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
634 && (flags & OFPSF_REPLY_MORE)) {
635 ds_put_cstr(string, "[more]");
636 flags &= ~OFPSF_REPLY_MORE;
637 }
638 if (flags) {
639 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
640 flags);
641 }
642 }
643 }
644
645 static enum ofperr
646 ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
647 {
648 size_t len = ntohs(oh->length);
649
650 ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
651 if (verbosity > 1) {
652 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
653 }
654
655 return 0;
656 }
657
658 static enum ofperr
659 ofp_print_role_message(struct ds *string, const struct ofp_header *oh)
660 {
661 struct ofputil_role_request rr;
662 enum ofperr error = ofputil_decode_role_message(oh, &rr);
663 if (!error) {
664 ofputil_format_role_message(string, &rr);
665 }
666 return error;
667 }
668
669 static enum ofperr
670 ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh)
671 {
672 struct ofputil_role_status rs;
673 enum ofperr error = ofputil_decode_role_status(oh, &rs);
674 if (!error) {
675 ofputil_format_role_status(string, &rs);
676 }
677 return error;
678 }
679
680 static enum ofperr
681 ofp_print_nxt_flow_mod_table_id(struct ds *string, const struct ofp_header *oh)
682 {
683 bool enable = ofputil_decode_nx_flow_mod_table_id(oh);
684 ds_put_format(string, " %s", enable ? "enable" : "disable");
685 return 0;
686 }
687
688 static enum ofperr
689 ofp_print_nxt_set_flow_format(struct ds *string, const struct ofp_header *oh)
690 {
691 enum ofputil_protocol p = ofputil_decode_nx_set_flow_format(oh);
692 ds_put_format(string, " format=%s",
693 p == OFPUTIL_P_OF10_STD ? "openflow10"
694 : p == OFPUTIL_P_OF10_NXM ? "nxm"
695 : "(unknown)");
696 return 0;
697 }
698
699 static enum ofperr
700 ofp_print_nxt_set_packet_in_format(struct ds *string,
701 const struct ofp_header *oh)
702 {
703 enum ofputil_packet_in_format format;
704 enum ofperr error = ofputil_decode_set_packet_in_format(oh, &format);
705 if (!error) {
706 ds_put_format(string, " format=%s",
707 ofputil_packet_in_format_to_string(format));
708 }
709 return error;
710 }
711
712 static enum ofperr
713 ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
714 enum ofptype ofptype)
715 {
716 struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
717 struct ofputil_async_cfg ac;
718
719 bool is_reply = ofptype == OFPTYPE_GET_ASYNC_REPLY;
720 enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
721 &basis, &ac);
722 if (error) {
723 return error;
724 }
725 ofputil_format_set_async_config(string, &ac);
726 return 0;
727 }
728
729 static enum ofperr
730 ofp_print_nxt_set_controller_id(struct ds *string,
731 const struct nx_controller_id *nci)
732 {
733 ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
734 return 0;
735 }
736
737 static enum ofperr
738 ofp_print_nxt_flow_monitor_cancel(struct ds *string,
739 const struct ofp_header *oh)
740 {
741 ds_put_format(string, " id=%"PRIu32,
742 ofputil_decode_flow_monitor_cancel(oh));
743 return 0;
744 }
745
746 static enum ofperr
747 ofp_print_nxst_flow_monitor_request(struct ds *string,
748 const struct ofp_header *oh,
749 const struct ofputil_port_map *port_map,
750 const struct ofputil_table_map *table_map)
751 {
752 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
753 for (;;) {
754 struct ofputil_flow_monitor_request request;
755 int retval;
756
757 retval = ofputil_decode_flow_monitor_request(&request, &b);
758 if (retval) {
759 return retval != EOF ? retval : 0;
760 }
761
762 ofputil_flow_monitor_request_format(string, &request,
763 port_map, table_map);
764 }
765 }
766
767 static enum ofperr
768 ofp_print_nxst_flow_monitor_reply(struct ds *string,
769 const struct ofp_header *oh,
770 const struct ofputil_port_map *port_map,
771 const struct ofputil_table_map *table_map)
772 {
773 uint64_t ofpacts_stub[1024 / 8];
774 struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
775 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
776
777 for (;;) {
778 struct ofputil_flow_update update;
779 int retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
780 if (retval) {
781 ofpbuf_uninit(&ofpacts);
782 return retval != EOF ? retval : 0;
783 }
784 ofputil_flow_update_format(string, &update, port_map, table_map);
785 }
786 }
787
788 void
789 ofp_print_version(const struct ofp_header *oh,
790 struct ds *string)
791 {
792 switch (oh->version) {
793 case OFP10_VERSION:
794 break;
795 case OFP11_VERSION:
796 ds_put_cstr(string, " (OF1.1)");
797 break;
798 case OFP12_VERSION:
799 ds_put_cstr(string, " (OF1.2)");
800 break;
801 case OFP13_VERSION:
802 ds_put_cstr(string, " (OF1.3)");
803 break;
804 case OFP14_VERSION:
805 ds_put_cstr(string, " (OF1.4)");
806 break;
807 case OFP15_VERSION:
808 ds_put_cstr(string, " (OF1.5)");
809 break;
810 default:
811 ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
812 break;
813 }
814 ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid));
815 }
816
817 static void
818 ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
819 struct ds *string)
820 {
821 ds_put_cstr(string, ofpraw_get_name(raw));
822 ofp_print_version(oh, string);
823 }
824
825 static enum ofperr
826 ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
827 const struct ofputil_table_map *table_map)
828 {
829 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
830 for (;;) {
831 struct ofputil_table_desc td;
832 int retval;
833
834 retval = ofputil_decode_table_desc(&b, &td, oh->version);
835 if (retval) {
836 return retval != EOF ? retval : 0;
837 }
838 ofputil_table_desc_format(s, &td, table_map);
839 }
840 }
841
842 static enum ofperr
843 ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
844 {
845 int error;
846 struct ofputil_bundle_ctrl_msg bctrl;
847
848 error = ofputil_decode_bundle_ctrl(oh, &bctrl);
849 if (error) {
850 return error;
851 }
852 ofputil_format_bundle_ctrl_request(s, &bctrl);
853 return 0;
854 }
855
856 static enum ofperr
857 ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
858 const struct ofputil_port_map *port_map,
859 const struct ofputil_table_map *table_map,
860 int verbosity)
861 {
862 struct ofputil_bundle_add_msg badd;
863 int error = ofputil_decode_bundle_add(oh, &badd, NULL);
864 if (!error) {
865 ofputil_format_bundle_add(s, &badd, port_map, table_map, verbosity);
866 }
867 return error;
868 }
869
870 static enum ofperr
871 ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
872 {
873 struct ofputil_tlv_table_mod ttm;
874 int error = ofputil_decode_tlv_table_mod(oh, &ttm);
875 if (!error) {
876 ofputil_format_tlv_table_mod(s, &ttm);
877 ofputil_uninit_tlv_table(&ttm.mappings);
878 }
879 return error;
880 }
881
882 static enum ofperr
883 ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
884 {
885 struct ofputil_tlv_table_reply ttr;
886 int error = ofputil_decode_tlv_table_reply(oh, &ttr);
887 if (!error) {
888 ofputil_format_tlv_table_reply(s, &ttr);
889 ofputil_uninit_tlv_table(&ttr.mappings);
890 }
891 return error;
892 }
893
894 /* This function will print the request forward message. The reason for
895 * request forward is taken from rf.request.type */
896 static enum ofperr
897 ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
898 const struct ofputil_port_map *port_map,
899 const struct ofputil_table_map *table_map)
900 {
901 struct ofputil_requestforward rf;
902 enum ofperr error = ofputil_decode_requestforward(oh, &rf);
903 if (!error) {
904 ofputil_format_requestforward(string, oh->version,
905 &rf, port_map, table_map);
906 ofputil_destroy_requestforward(&rf);
907 }
908 return error;
909 }
910
911 static enum ofperr
912 ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
913 {
914 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
915 for (;;) {
916 struct ofputil_ipfix_stats is;
917 int retval;
918
919 retval = ofputil_pull_ipfix_stats(&is, &b);
920 if (retval) {
921 return retval != EOF ? retval : 0;
922 }
923 ofputil_format_ipfix_stats_bridge(string, &is);
924 }
925 }
926
927 static enum ofperr
928 ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
929 {
930 ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
931
932 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
933 for (;;) {
934 struct ofputil_ipfix_stats is;
935 int retval;
936
937 retval = ofputil_pull_ipfix_stats(&is, &b);
938 if (retval) {
939 return retval != EOF ? retval : 0;
940 }
941 ofputil_format_ipfix_stats_flow(string, &is);
942 }
943 }
944
945 static enum ofperr
946 ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
947 {
948 ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
949 return 0;
950 }
951
952 static enum ofperr
953 ofp_to_string__(const struct ofp_header *oh,
954 const struct ofputil_port_map *port_map,
955 const struct ofputil_table_map *table_map, enum ofpraw raw,
956 struct ds *string, int verbosity)
957 {
958 if (ofpmsg_is_stat(oh)) {
959 ofp_print_stats(string, oh);
960 }
961
962 const void *msg = oh;
963 enum ofptype type = ofptype_from_ofpraw(raw);
964 switch (type) {
965 case OFPTYPE_GROUP_STATS_REQUEST:
966 return ofputil_group_stats_request_format(string, oh);
967
968 case OFPTYPE_GROUP_STATS_REPLY:
969 return ofputil_group_stats_format(string, oh);
970
971 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
972 return ofputil_group_desc_request_format(string, oh);
973
974 case OFPTYPE_GROUP_DESC_STATS_REPLY:
975 return ofputil_group_desc_format(string, oh, port_map, table_map);
976
977 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
978 break;
979
980 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
981 return ofputil_group_features_format(string, oh);
982
983 case OFPTYPE_GROUP_MOD:
984 return ofputil_group_mod_format(string, oh, port_map, table_map);
985
986 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
987 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
988 return ofp_print_table_features_reply(string, oh);
989
990 case OFPTYPE_TABLE_DESC_REQUEST:
991 case OFPTYPE_TABLE_DESC_REPLY:
992 return ofp_print_table_desc_reply(string, oh, table_map);
993
994 case OFPTYPE_HELLO:
995 return ofp_print_hello(string, oh);
996
997 case OFPTYPE_ERROR:
998 return ofp_print_error_msg(string, oh, port_map, table_map);
999
1000 case OFPTYPE_ECHO_REQUEST:
1001 case OFPTYPE_ECHO_REPLY:
1002 return ofp_print_echo(string, oh, verbosity);
1003
1004 case OFPTYPE_FEATURES_REQUEST:
1005 break;
1006
1007 case OFPTYPE_FEATURES_REPLY:
1008 return ofp_print_switch_features(string, oh);
1009
1010 case OFPTYPE_GET_CONFIG_REQUEST:
1011 break;
1012
1013 case OFPTYPE_GET_CONFIG_REPLY:
1014 return ofp_print_get_config_reply(string, oh);
1015
1016 case OFPTYPE_SET_CONFIG:
1017 return ofp_print_set_config(string, oh);
1018
1019 case OFPTYPE_PACKET_IN:
1020 return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
1021
1022 case OFPTYPE_FLOW_REMOVED:
1023 return ofp_print_flow_removed(string, oh, port_map, table_map);
1024
1025 case OFPTYPE_PORT_STATUS:
1026 return ofp_print_port_status(string, oh);
1027
1028 case OFPTYPE_PACKET_OUT:
1029 return ofp_print_packet_out(string, oh, port_map, table_map,
1030 verbosity);
1031
1032 case OFPTYPE_FLOW_MOD:
1033 return ofputil_flow_mod_format(string, oh, port_map, table_map,
1034 verbosity);
1035
1036 case OFPTYPE_PORT_MOD:
1037 return ofp_print_port_mod(string, oh, port_map);
1038
1039 case OFPTYPE_TABLE_MOD:
1040 return ofp_print_table_mod(string, oh, table_map);
1041
1042 case OFPTYPE_METER_MOD:
1043 return ofp_print_meter_mod(string, oh);
1044
1045 case OFPTYPE_BARRIER_REQUEST:
1046 case OFPTYPE_BARRIER_REPLY:
1047 break;
1048
1049 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
1050 return ofputil_queue_get_config_request_format(string, oh, port_map);
1051
1052 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
1053 return ofputil_queue_get_config_reply_format(string, oh, port_map);
1054
1055 case OFPTYPE_ROLE_REQUEST:
1056 case OFPTYPE_ROLE_REPLY:
1057 return ofp_print_role_message(string, oh);
1058 case OFPTYPE_ROLE_STATUS:
1059 return ofp_print_role_status_message(string, oh);
1060
1061 case OFPTYPE_REQUESTFORWARD:
1062 return ofp_print_requestforward(string, oh, port_map, table_map);
1063
1064 case OFPTYPE_TABLE_STATUS:
1065 return ofp_print_table_status_message(string, oh, table_map);
1066
1067 case OFPTYPE_METER_STATS_REQUEST:
1068 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
1069 return ofp_print_meter_stats_request(string, oh);
1070
1071 case OFPTYPE_METER_STATS_REPLY:
1072 return ofp_print_meter_stats_reply(string, oh);
1073
1074 case OFPTYPE_METER_CONFIG_STATS_REPLY:
1075 return ofp_print_meter_config_reply(string, oh);
1076
1077 case OFPTYPE_METER_FEATURES_STATS_REPLY:
1078 return ofp_print_meter_features_reply(string, oh);
1079
1080 case OFPTYPE_DESC_STATS_REQUEST:
1081 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
1082 break;
1083
1084 case OFPTYPE_FLOW_STATS_REQUEST:
1085 case OFPTYPE_AGGREGATE_STATS_REQUEST:
1086 return ofp_print_flow_stats_request(string, oh, port_map, table_map);
1087
1088 case OFPTYPE_TABLE_STATS_REQUEST:
1089 break;
1090
1091 case OFPTYPE_PORT_STATS_REQUEST:
1092 return ofp_print_ofpst_port_request(string, oh, port_map);
1093
1094 case OFPTYPE_QUEUE_STATS_REQUEST:
1095 return ofputil_queue_stats_request_format(string, oh, port_map);
1096
1097 case OFPTYPE_DESC_STATS_REPLY:
1098 return ofp_print_ofpst_desc_reply(string, oh);
1099
1100 case OFPTYPE_FLOW_STATS_REPLY:
1101 return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
1102
1103 case OFPTYPE_QUEUE_STATS_REPLY:
1104 return ofputil_queue_stats_reply_format(string, oh, port_map,
1105 verbosity);
1106
1107 case OFPTYPE_PORT_STATS_REPLY:
1108 return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
1109
1110 case OFPTYPE_TABLE_STATS_REPLY:
1111 return ofp_print_table_stats_reply(string, oh);
1112
1113 case OFPTYPE_AGGREGATE_STATS_REPLY:
1114 return ofp_print_aggregate_stats_reply(string, oh);
1115
1116 case OFPTYPE_PORT_DESC_STATS_REQUEST:
1117 return ofp_print_ofpst_port_desc_request(string, oh, port_map);
1118
1119 case OFPTYPE_PORT_DESC_STATS_REPLY:
1120 return ofp_print_ofpst_port_desc_reply(string, oh);
1121
1122 case OFPTYPE_FLOW_MOD_TABLE_ID:
1123 return ofp_print_nxt_flow_mod_table_id(string, oh);
1124
1125 case OFPTYPE_SET_FLOW_FORMAT:
1126 return ofp_print_nxt_set_flow_format(string, oh);
1127
1128 case OFPTYPE_SET_PACKET_IN_FORMAT:
1129 return ofp_print_nxt_set_packet_in_format(string, oh);
1130
1131 case OFPTYPE_FLOW_AGE:
1132 break;
1133
1134 case OFPTYPE_SET_CONTROLLER_ID:
1135 return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
1136
1137 case OFPTYPE_GET_ASYNC_REPLY:
1138 case OFPTYPE_SET_ASYNC_CONFIG:
1139 return ofp_print_set_async_config(string, oh, type);
1140 case OFPTYPE_GET_ASYNC_REQUEST:
1141 break;
1142 case OFPTYPE_FLOW_MONITOR_CANCEL:
1143 return ofp_print_nxt_flow_monitor_cancel(string, msg);
1144
1145 case OFPTYPE_FLOW_MONITOR_PAUSED:
1146 case OFPTYPE_FLOW_MONITOR_RESUMED:
1147 break;
1148
1149 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
1150 return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
1151 table_map);
1152
1153 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
1154 return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
1155 table_map);
1156
1157 case OFPTYPE_BUNDLE_CONTROL:
1158 return ofp_print_bundle_ctrl(string, msg);
1159
1160 case OFPTYPE_BUNDLE_ADD_MESSAGE:
1161 return ofp_print_bundle_add(string, msg, port_map, table_map,
1162 verbosity);
1163
1164 case OFPTYPE_NXT_TLV_TABLE_MOD:
1165 return ofp_print_tlv_table_mod(string, msg);
1166
1167 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
1168 break;
1169
1170 case OFPTYPE_NXT_TLV_TABLE_REPLY:
1171 return ofp_print_tlv_table_reply(string, msg);
1172
1173 case OFPTYPE_NXT_RESUME:
1174 return ofp_print_packet_in(string, msg, port_map, table_map,
1175 verbosity);
1176 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
1177 break;
1178 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
1179 return ofp_print_nxst_ipfix_bridge_reply(string, oh);
1180 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
1181 break;
1182 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
1183 return ofp_print_nxst_ipfix_flow_reply(string, oh);
1184
1185 case OFPTYPE_CT_FLUSH_ZONE:
1186 return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
1187 }
1188
1189 return 0;
1190 }
1191
1192 static void
1193 add_newline(struct ds *s)
1194 {
1195 if (s->length && s->string[s->length - 1] != '\n') {
1196 ds_put_char(s, '\n');
1197 }
1198 }
1199
1200 /* Composes and returns a string representing the OpenFlow packet of 'len'
1201 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
1202 * verbosity and higher numbers increase verbosity. The caller is responsible
1203 * for freeing the string. */
1204 char *
1205 ofp_to_string(const void *oh_, size_t len,
1206 const struct ofputil_port_map *port_map,
1207 const struct ofputil_table_map *table_map,
1208 int verbosity)
1209 {
1210 struct ds string = DS_EMPTY_INITIALIZER;
1211 const struct ofp_header *oh = oh_;
1212
1213 if (!len) {
1214 ds_put_cstr(&string, "OpenFlow message is empty\n");
1215 } else if (len < sizeof(struct ofp_header)) {
1216 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
1217 len);
1218 } else if (ntohs(oh->length) > len) {
1219 enum ofperr error;
1220 enum ofpraw raw;
1221
1222 error = ofpraw_decode_partial(&raw, oh, len);
1223 if (!error) {
1224 ofp_header_to_string__(oh, raw, &string);
1225 ds_put_char(&string, '\n');
1226 }
1227
1228 ds_put_format(&string,
1229 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
1230 len, ntohs(oh->length));
1231 } else if (ntohs(oh->length) < len) {
1232 ds_put_format(&string,
1233 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
1234 ntohs(oh->length), len);
1235 } else {
1236 enum ofperr error;
1237 enum ofpraw raw;
1238
1239 error = ofpraw_decode(&raw, oh);
1240 if (!error) {
1241 ofp_header_to_string__(oh, raw, &string);
1242 size_t header_len = string.length;
1243
1244 error = ofp_to_string__(oh, port_map, table_map,
1245 raw, &string, verbosity);
1246 if (error) {
1247 if (string.length > header_len) {
1248 ds_chomp(&string, ' ');
1249 add_newline(&string);
1250 } else {
1251 ds_put_char(&string, ' ');
1252 }
1253 ofp_print_error(&string, error);
1254 } else {
1255 ds_chomp(&string, ' ');
1256 }
1257 } else {
1258 ofp_print_error(&string, error);
1259 }
1260
1261 if (verbosity >= 5 || error) {
1262 add_newline(&string);
1263 ds_put_hex_dump(&string, oh, len, 0, true);
1264 }
1265
1266 add_newline(&string);
1267 return ds_steal_cstr(&string);
1268 }
1269 ds_put_hex_dump(&string, oh, len, 0, true);
1270 return ds_steal_cstr(&string);
1271 }
1272 \f
1273 static void
1274 print_and_free(FILE *stream, char *string)
1275 {
1276 fputs(string, stream);
1277 free(string);
1278 }
1279
1280 /* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
1281 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
1282 * numbers increase verbosity. */
1283 void
1284 ofp_print(FILE *stream, const void *oh, size_t len,
1285 const struct ofputil_port_map *port_map,
1286 const struct ofputil_table_map *table_map, int verbosity)
1287 {
1288 print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
1289 verbosity));
1290 }
1291
1292 /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
1293 * 'data' to 'stream'. */
1294 void
1295 ofp_print_packet(FILE *stream, const void *data, size_t len,
1296 ovs_be32 packet_type)
1297 {
1298 print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
1299 }
1300
1301 void
1302 ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
1303 {
1304 print_and_free(stream, ofp_dp_packet_to_string(packet));
1305 }