]> git.proxmox.com Git - mirror_ovs.git/blame_incremental - lib/ofp-print.c
Revert "dpif-netdev: includes microsecond delta in meter bucket calculation".
[mirror_ovs.git] / lib / ofp-print.c
... / ...
CommitLineData
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
67static 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.*/
71char *
72ofp_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
111char *
112ofp_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
119static enum ofperr
120ofp_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
138static enum ofperr
139ofp_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
156void
157ofp_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
192static enum ofperr
193ofp_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
205static enum ofperr
206ofp_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
219static enum ofperr
220ofp_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
228static enum ofperr
229ofp_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
250void
251ofp_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
279static enum ofperr
280ofp_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
292static enum ofperr
293ofp_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
304static enum ofperr
305ofp_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
316static enum ofperr
317ofp_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
328static enum ofperr
329ofp_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
344static enum ofperr
345ofp_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
357static enum ofperr
358ofp_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
366static enum ofperr
367ofp_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
389static enum ofperr
390ofp_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
412static void
413ofp_print_error(struct ds *string, enum ofperr error)
414{
415 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
416}
417
418static enum ofperr
419ofp_print_hello(struct ds *string, const struct ofp_header *oh)
420{
421 ofputil_hello_format(string, oh);
422 return 0;
423}
424
425static enum ofperr
426ofp_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
441static enum ofperr
442ofp_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
452static enum ofperr
453ofp_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
472static enum ofperr
473ofp_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
486static enum ofperr
487ofp_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
511static enum ofperr
512ofp_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
524static enum ofperr
525ofp_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
542static enum ofperr
543ofp_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
567static enum ofperr
568ofp_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
597static enum ofperr
598ofp_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
616static enum ofperr
617ofp_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
626static void
627ofp_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
645static enum ofperr
646ofp_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
658static enum ofperr
659ofp_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
669static enum ofperr
670ofp_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
680static enum ofperr
681ofp_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
688static enum ofperr
689ofp_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
699static enum ofperr
700ofp_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
712static enum ofperr
713ofp_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
729static enum ofperr
730ofp_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
737static enum ofperr
738ofp_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
746static enum ofperr
747ofp_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
767static enum ofperr
768ofp_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
788void
789ofp_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
817static void
818ofp_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
825static enum ofperr
826ofp_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
842static enum ofperr
843ofp_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
856static enum ofperr
857ofp_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
870static enum ofperr
871ofp_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
882static enum ofperr
883ofp_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 */
896static enum ofperr
897ofp_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
911static enum ofperr
912ofp_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
927static enum ofperr
928ofp_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
945static enum ofperr
946ofp_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
952static enum ofperr
953ofp_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
1192static void
1193add_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. */
1204char *
1205ofp_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
1273static void
1274print_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. */
1283void
1284ofp_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'. */
1294void
1295ofp_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
1301void
1302ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
1303{
1304 print_and_free(stream, ofp_dp_packet_to_string(packet));
1305}