]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-print.c
treewide: Convert leading tabs to spaces.
[mirror_ovs.git] / lib / ofp-print.c
CommitLineData
064af421 1/*
04f48a68 2 * Copyright (c) 2008-2017 Nicira, Inc.
064af421 3 *
a14bc59f
BP
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:
064af421 7 *
a14bc59f
BP
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.
064af421
BP
15 */
16
17#include <config.h>
064af421 18
0c24b0ba
BP
19#include "openvswitch/ofp-print.h"
20
064af421
BP
21#include <errno.h>
22#include <inttypes.h>
7f3adc00 23#include <sys/types.h>
064af421
BP
24#include <netinet/in.h>
25#include <sys/wait.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <ctype.h>
29
daff3353 30#include "bundle.h"
10a24935 31#include "byte-order.h"
ab8e7f7d 32#include "colors.h"
064af421 33#include "compiler.h"
25d436fb 34#include "dp-packet.h"
064af421 35#include "flow.h"
75a75043 36#include "learn.h"
53ddd40a 37#include "multipath.h"
9e1fd49b 38#include "netdev.h"
7fa91113 39#include "nx-match.h"
25d436fb 40#include "odp-util.h"
064af421 41#include "openflow/nicira-ext.h"
b598f214 42#include "openflow/openflow.h"
d271907f
BW
43#include "openvswitch/dynamic-string.h"
44#include "openvswitch/meta-flow.h"
b598f214 45#include "openvswitch/ofp-actions.h"
0d71302e
BP
46#include "openvswitch/ofp-bundle.h"
47#include "openvswitch/ofp-connection.h"
e03c096d 48#include "openvswitch/ofp-errors.h"
0d71302e
BP
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"
d271907f 54#include "openvswitch/ofp-msgs.h"
0d71302e
BP
55#include "openvswitch/ofp-port.h"
56#include "openvswitch/ofp-queue.h"
57#include "openvswitch/ofp-switch.h"
58#include "openvswitch/ofp-table.h"
d271907f
BW
59#include "openvswitch/ofp-util.h"
60#include "openvswitch/ofpbuf.h"
61#include "openvswitch/type-props.h"
064af421 62#include "packets.h"
c4617b3c 63#include "unaligned.h"
064af421 64#include "util.h"
d5dc60f0 65#include "uuid.h"
064af421 66
d2805da2 67static void ofp_print_queue_name(struct ds *string, uint32_t port);
90bf1e07 68static void ofp_print_error(struct ds *, enum ofperr);
064af421
BP
69
70/* Returns a string that represents the contents of the Ethernet frame in the
897a8e07 71 * 'len' bytes starting at 'data'. The caller must free the returned string.*/
064af421 72char *
2482b0b0 73ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
064af421
BP
74{
75 struct ds ds = DS_EMPTY_INITIALIZER;
cf62fa4c 76 struct dp_packet buf;
897a8e07 77 struct flow flow;
5a51b2cd 78 size_t l4_size;
064af421 79
cf62fa4c 80 dp_packet_use_const(&buf, data, len);
2482b0b0 81 buf.packet_type = packet_type;
cf62fa4c 82 flow_extract(&buf, &flow);
50f96b10 83 flow_format(&ds, &flow, NULL);
e50abca5 84
cf62fa4c 85 l4_size = dp_packet_l4_size(&buf);
5a51b2cd
JR
86
87 if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
cf62fa4c 88 struct tcp_header *th = dp_packet_l4(&buf);
5a51b2cd
JR
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) {
cf62fa4c 91 struct udp_header *uh = dp_packet_l4(&buf);
5a51b2cd
JR
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) {
cf62fa4c 94 struct sctp_header *sh = dp_packet_l4(&buf);
5fa008d4
BP
95 ds_put_format(&ds, " sctp_csum:%"PRIx32,
96 ntohl(get_16aligned_be32(&sh->sctp_csum)));
e60e935b 97 } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
cf62fa4c 98 struct icmp_header *icmph = dp_packet_l4(&buf);
e60e935b
SRCSA
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) {
cf62fa4c 102 struct icmp6_header *icmp6h = dp_packet_l4(&buf);
e60e935b
SRCSA
103 ds_put_format(&ds, " icmp6_csum:%"PRIx16,
104 ntohs(icmp6h->icmp6_cksum));
e50abca5
EJ
105 }
106
897a8e07 107 ds_put_char(&ds, '\n');
064af421 108
064af421
BP
109 return ds_cstr(&ds);
110}
111
2482b0b0
JS
112char *
113ofp_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
2d071a32 120static enum ofperr
65120a8a 121ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
122 const struct ofputil_port_map *port_map,
123 const struct ofputil_table_map *table_map, int verbosity)
064af421 124{
77ab5fd2 125 struct ofputil_packet_in_private pin;
9bfe9334
BP
126 uint32_t buffer_id;
127 size_t total_len;
dfc77282
BP
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);
b4ccee75 135 }
dfc77282 136 return error;
064af421
BP
137}
138
2d071a32 139static enum ofperr
982697a4 140ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
141 const struct ofputil_port_map *port_map,
142 const struct ofputil_table_map *table_map, int verbosity)
064af421 143{
c6a93eb7 144 struct ofputil_packet_out po;
f25d0cf3 145 struct ofpbuf ofpacts;
c6a93eb7 146 enum ofperr error;
064af421 147
f25d0cf3 148 ofpbuf_init(&ofpacts, 64);
89d7927b 149 error = ofputil_decode_packet_out(&po, oh, NULL, &ofpacts);
dfc77282
BP
150 if (!error) {
151 ofputil_packet_out_format(string, &po, port_map, table_map, verbosity);
064af421 152 }
f25d0cf3 153 ofpbuf_uninit(&ofpacts);
dfc77282 154 return error;
064af421
BP
155}
156
dfc77282 157void
0ab14c8e 158ofp_print_bit_names(struct ds *string, uint32_t bits,
e8fa940e
BP
159 const char *(*bit_to_name)(uint32_t bit),
160 char separator)
064af421 161{
0ab14c8e 162 int n = 0;
9e1fd49b 163 int i;
0ab14c8e
BP
164
165 if (!bits) {
166 ds_put_cstr(string, "0");
064af421
BP
167 return;
168 }
0ab14c8e 169
9e1fd49b
BP
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++) {
e8fa940e 177 ds_put_char(string, separator);
9e1fd49b
BP
178 }
179 ds_put_cstr(string, name);
180 bits &= ~bit;
0ab14c8e 181 }
0ab14c8e 182 }
064af421 183 }
0ab14c8e
BP
184
185 if (bits) {
f5cd6874 186 if (n) {
e8fa940e 187 ds_put_char(string, separator);
0ab14c8e
BP
188 }
189 ds_put_format(string, "0x%"PRIx32, bits);
064af421 190 }
0ab14c8e
BP
191}
192
2d071a32 193static enum ofperr
982697a4 194ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
064af421 195{
9e1fd49b 196 struct ofputil_switch_features features;
0a2869d5
BP
197 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
198 enum ofperr error = ofputil_pull_switch_features(&b, &features);
dfc77282
BP
199 if (!error) {
200 ofputil_switch_features_format(string, &features);
201 error = ofputil_phy_ports_format(string, oh->version, &b);
f0fd1a17 202 }
dfc77282 203 return error;
ad99e2ed
BP
204}
205
2d071a32 206static enum ofperr
ad99e2ed
BP
207ofp_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) {
2d071a32 214 return error;
064af421 215 }
dfc77282 216 ofputil_switch_config_format(string, &config);
2d071a32 217 return 0;
ad99e2ed 218}
064af421 219
2d071a32 220static enum ofperr
ad99e2ed
BP
221ofp_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);
dfc77282 225 ofputil_switch_config_format(string, &config);
2d071a32 226 return 0;
064af421
BP
227}
228
2d071a32 229static enum ofperr
dfc77282
BP
230ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh,
231 const struct ofputil_table_map *table_map)
064af421 232{
dfc77282 233 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
f904747b 234
dfc77282
BP
235 struct ofputil_table_features prev;
236 for (int i = 0; ; i++) {
237 struct ofputil_table_features tf;
238 int retval;
7fa91113 239
dfc77282
BP
240 retval = ofputil_decode_table_features(&b, &tf, true);
241 if (retval) {
242 return retval != EOF ? retval : 0;
243 }
0fb88c18 244
dfc77282
BP
245 ds_put_char(s, '\n');
246 ofputil_table_features_format(s, &tf, i ? &prev : NULL, NULL, NULL,
247 table_map);
248 prev = tf;
7fa91113 249 }
064af421
BP
250}
251
dfc77282 252void
09862ec6
BP
253ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
254{
255 ds_put_format(string, "%u", sec);
b1634591
BP
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
dfc77282
BP
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 }
82c22d34 277 }
dfc77282 278 ds_put_char(string, 's');
82c22d34
BP
279}
280
dfc77282
BP
281static enum ofperr
282ofp_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)
82c22d34 285{
dfc77282
BP
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);
918f2b82 290 }
dfc77282 291 return error;
918f2b82
AZ
292}
293
dfc77282
BP
294static enum ofperr
295ofp_print_port_mod(struct ds *string, const struct ofp_header *oh,
296 const struct ofputil_port_map *port_map)
de7d3c07 297{
dfc77282
BP
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);
de7d3c07 302 }
dfc77282 303 return error;
de7d3c07
SJ
304}
305
2d071a32 306static enum ofperr
4bc938cc
BP
307ofp_print_table_mod(struct ds *string, const struct ofp_header *oh,
308 const struct ofputil_table_map *table_map)
918f2b82 309{
dfc77282
BP
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);
bab86012 314 }
dfc77282 315 return error;
03c72922
BP
316}
317
2d071a32 318static enum ofperr
4bc938cc
BP
319ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh,
320 const struct ofputil_table_map *table_map)
6c6eedc5
SJ
321{
322 struct ofputil_table_status ts;
323 enum ofperr error;
324
325 error = ofputil_decode_table_status(oh, &ts);
326 if (error) {
2d071a32 327 return error;
6c6eedc5
SJ
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:-");
dfc77282 337 ofputil_table_desc_format(string, &ts.desc, table_map);
2d071a32
BP
338
339 return 0;
6c6eedc5
SJ
340}
341
2d071a32 342static enum ofperr
e8f9a7bb 343ofp_print_queue_get_config_request(struct ds *string,
50f96b10
BP
344 const struct ofp_header *oh,
345 const struct ofputil_port_map *port_map)
e8f9a7bb
VG
346{
347 enum ofperr error;
348 ofp_port_t port;
e016fb63 349 uint32_t queue;
e8f9a7bb 350
e016fb63 351 error = ofputil_decode_queue_get_config_request(oh, &port, &queue);
e8f9a7bb 352 if (error) {
2d071a32 353 return error;
e8f9a7bb
VG
354 }
355
356 ds_put_cstr(string, " port=");
50f96b10 357 ofputil_format_port(port, port_map, string);
e016fb63
BP
358
359 if (queue != OFPQ_ALL) {
360 ds_put_cstr(string, " queue=");
361 ofp_print_queue_name(string, queue);
362 }
2d071a32
BP
363
364 return 0;
e8f9a7bb
VG
365}
366
367static void
368print_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
a28239c0
BP
377/* qsort comparison function. */
378static int
379compare_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
2d071a32 395static enum ofperr
e8f9a7bb 396ofp_print_queue_get_config_reply(struct ds *string,
50f96b10
BP
397 const struct ofp_header *oh,
398 const struct ofputil_port_map *port_map)
e8f9a7bb 399{
0a2869d5 400 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
e8f9a7bb 401
a28239c0
BP
402 struct ofputil_queue_config *queues = NULL;
403 size_t allocated_queues = 0;
404 size_t n = 0;
e8f9a7bb 405
a28239c0
BP
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]);
e8f9a7bb 412 if (retval) {
e8f9a7bb
VG
413 break;
414 }
a28239c0
BP
415 n++;
416 }
e8f9a7bb 417
a28239c0
BP
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;
e016fb63
BP
426
427 ds_put_cstr(string, "port=");
50f96b10 428 ofputil_format_port(port, port_map, string);
e016fb63
BP
429 ds_put_char(string, '\n');
430 }
431
a28239c0
BP
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);
e8f9a7bb
VG
435 ds_put_char(string, '\n');
436 }
a28239c0 437
a28239c0 438 ds_chomp(string, ' ');
18dc96b0 439 free(queues);
2d071a32
BP
440
441 return retval != EOF ? retval : 0;
e8f9a7bb
VG
442}
443
638a19b0
JR
444static void
445ofp_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
466static void
467ofp_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
9e638f22
AZ
492static void
493ofp_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
638a19b0
JR
516static void
517ofp_print_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms)
518{
519 uint16_t i;
520
9e638f22
AZ
521 ofp_print_meter_id(s, ms->meter_id, ':');
522 ds_put_char(s, ' ');
638a19b0
JR
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
538static void
539ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc)
540{
541 uint16_t i;
542
9e638f22
AZ
543 ofp_print_meter_id(s, mc->meter_id, '=');
544 ds_put_char(s, ' ');
638a19b0
JR
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
555static void
3c35db62 556ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm)
638a19b0 557{
3c35db62 558 switch (mm->command) {
638a19b0
JR
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:
3c35db62 569 ds_put_format(s, " cmd:%d ", mm->command);
638a19b0
JR
570 }
571
3c35db62
NR
572 ofp_print_meter_config(s, &mm->meter);
573}
574
2d071a32 575static enum ofperr
3c35db62
NR
576ofp_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);
2d071a32 584 if (!error) {
3c35db62
NR
585 ofp_print_meter_mod__(s, &mm);
586 }
638a19b0 587 ofpbuf_uninit(&bands);
2d071a32
BP
588
589 return error;
638a19b0
JR
590}
591
2d071a32 592static enum ofperr
638a19b0
JR
593ofp_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);
9e638f22 598 ds_put_char(s, ' ');
638a19b0 599
9e638f22 600 ofp_print_meter_id(s, meter_id, '=');
2d071a32
BP
601
602 return 0;
638a19b0
JR
603}
604
605static const char *
606ofputil_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
620static const char *
621ofputil_meter_band_types_to_name(uint32_t bit)
622{
638a19b0 623 switch (bit) {
6e055a6c
BP
624 case 1 << OFPMBT13_DROP: return "drop";
625 case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark";
638a19b0
JR
626 }
627
628 return NULL;
629}
630
2d071a32 631static enum ofperr
638a19b0
JR
632ofp_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');
2d071a32
BP
651
652 return 0;
638a19b0
JR
653}
654
2d071a32 655static enum ofperr
638a19b0
JR
656ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
657{
0a2869d5 658 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
638a19b0 659 struct ofpbuf bands;
2d071a32 660 int retval;
638a19b0 661
638a19b0
JR
662 ofpbuf_init(&bands, 64);
663 for (;;) {
664 struct ofputil_meter_config mc;
638a19b0
JR
665
666 retval = ofputil_decode_meter_config(&b, &mc, &bands);
667 if (retval) {
638a19b0
JR
668 break;
669 }
670 ds_put_char(s, '\n');
671 ofp_print_meter_config(s, &mc);
672 }
673 ofpbuf_uninit(&bands);
2d071a32
BP
674
675 return retval != EOF ? retval : 0;
638a19b0
JR
676}
677
2d071a32 678static enum ofperr
638a19b0
JR
679ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
680{
0a2869d5 681 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
638a19b0 682 struct ofpbuf bands;
2d071a32 683 int retval;
638a19b0 684
638a19b0
JR
685 ofpbuf_init(&bands, 64);
686 for (;;) {
687 struct ofputil_meter_stats ms;
638a19b0
JR
688
689 retval = ofputil_decode_meter_stats(&b, &ms, &bands);
690 if (retval) {
638a19b0
JR
691 break;
692 }
693 ds_put_char(s, '\n');
694 ofp_print_meter_stats(s, &ms);
695 }
696 ofpbuf_uninit(&bands);
2d071a32
BP
697
698 return retval != EOF ? retval : 0;
638a19b0
JR
699}
700
7fa91113 701static void
90bf1e07 702ofp_print_error(struct ds *string, enum ofperr error)
7fa91113 703{
90bf1e07 704 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
f74be05a
JP
705}
706
2d071a32 707static enum ofperr
de6c85b0
SH
708ofp_print_hello(struct ds *string, const struct ofp_header *oh)
709{
dfc77282 710 ofputil_hello_format(string, oh);
2d071a32 711 return 0;
de6c85b0
SH
712}
713
2d071a32 714static enum ofperr
50f96b10 715ofp_print_error_msg(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
716 const struct ofputil_port_map *port_map,
717 const struct ofputil_table_map *table_map)
064af421 718{
982697a4 719 struct ofpbuf payload;
dfc77282 720 enum ofperr error = ofperr_decode_msg(oh, &payload);
90bf1e07 721 if (!error) {
2d071a32 722 return OFPERR_OFPBRC_BAD_LEN;
f74be05a 723 }
dfc77282 724 ofperr_msg_format(string, error, &payload, port_map, table_map);
dea241f1 725 ofpbuf_uninit(&payload);
2d071a32
BP
726
727 return 0;
064af421
BP
728}
729
2d071a32 730static enum ofperr
982697a4 731ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
064af421 732{
9e1fd49b 733 struct ofputil_port_status ps;
dfc77282
BP
734 enum ofperr error = ofputil_decode_port_status(oh, &ps);
735 if (!error) {
736 ofputil_port_status_format(string, &ps);
064af421 737 }
dfc77282 738 return error;
064af421
BP
739}
740
2d071a32 741static enum ofperr
982697a4 742ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
064af421 743{
982697a4
BP
744 const struct ofp_desc_stats *ods = ofpmsg_body(oh);
745
fbd76b2e 746 ds_put_char(string, '\n');
d295e8e9 747 ds_put_format(string, "Manufacturer: %.*s\n",
dd70b475
JP
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);
2d071a32
BP
757
758 return 0;
064af421
BP
759}
760
2d071a32 761static enum ofperr
50f96b10 762ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
763 const struct ofputil_port_map *port_map,
764 const struct ofputil_table_map *table_map)
064af421 765{
81d1ea94 766 struct ofputil_flow_stats_request fsr;
dfc77282
BP
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);
bdcc5925 771 }
dfc77282 772 return error;
bdcc5925
BP
773}
774
2d071a32 775static enum ofperr
50f96b10 776ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
777 const struct ofputil_port_map *port_map,
778 const struct ofputil_table_map *table_map)
064af421 779{
0a2869d5 780 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
f25d0cf3 781 struct ofpbuf ofpacts;
2d071a32 782 int retval;
064af421 783
f25d0cf3 784 ofpbuf_init(&ofpacts, 64);
4ffd1b43
BP
785 for (;;) {
786 struct ofputil_flow_stats fs;
fab8fadb 787
f25d0cf3 788 retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
4ffd1b43 789 if (retval) {
064af421
BP
790 break;
791 }
1b3758c3 792 ds_put_cstr(string, "\n ");
dfc77282 793 ofputil_flow_stats_format(string, &fs, port_map, table_map, true);
bdcc5925 794 }
cb80d803 795 ofpbuf_uninit(&ofpacts);
2d071a32
BP
796
797 return retval != EOF ? retval : 0;
c6430da5
BP
798}
799
2d071a32 800static enum ofperr
982697a4 801ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
064af421 802{
982697a4
BP
803 struct ofputil_aggregate_stats as;
804 enum ofperr error;
064af421 805
982697a4 806 error = ofputil_decode_aggregate_stats_reply(&as, oh);
dfc77282
BP
807 if (!error) {
808 ofputil_aggregate_stats_format(string, &as);
982697a4 809 }
dfc77282 810 return error;
a2ad9ecd
BP
811}
812
f8e4867e
SH
813static void
814print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
064af421
BP
815{
816 ds_put_cstr(string, leader);
c4617b3c 817 if (stat != UINT64_MAX) {
064af421
BP
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
d6e3feb5 829static void
830print_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
2d071a32 837static enum ofperr
50f96b10
BP
838ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh,
839 const struct ofputil_port_map *port_map)
abaad8cf 840{
4e022ec0 841 ofp_port_t ofp10_port;
f8e4867e
SH
842 enum ofperr error;
843
844 error = ofputil_decode_port_stats_request(oh, &ofp10_port);
845 if (error) {
2d071a32 846 return error;
f8e4867e
SH
847 }
848
e1db42d6 849 ds_put_cstr(string, " port_no=");
50f96b10 850 ofputil_format_port(ofp10_port, port_map, string);
2d071a32
BP
851
852 return 0;
abaad8cf
JP
853}
854
2d071a32 855static enum ofperr
d1e2cf21 856ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
50f96b10 857 const struct ofputil_port_map *port_map,
d1e2cf21 858 int verbosity)
064af421 859{
971f4b39 860 uint32_t i;
34582733 861 ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh));
064af421 862 if (verbosity < 1) {
2d071a32 863 return 0;
064af421
BP
864 }
865
0a2869d5 866 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 867 for (;;) {
f8e4867e
SH
868 struct ofputil_port_stats ps;
869 int retval;
870
871 retval = ofputil_decode_port_stats(&ps, &b);
872 if (retval) {
2d071a32 873 return retval != EOF ? retval : 0;
982697a4
BP
874 }
875
e1db42d6 876 ds_put_cstr(string, " port ");
4e022ec0 877 if (ofp_to_u16(ps.port_no) < 10) {
e1db42d6
JR
878 ds_put_char(string, ' ');
879 }
50f96b10 880 ofputil_format_port(ps.port_no, port_map, string);
064af421 881
f8e4867e
SH
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);
064af421
BP
890
891 ds_put_cstr(string, " tx ");
f8e4867e
SH
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);
65e0be10
BP
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 }
d6e3feb5 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 }
971f4b39
MW
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 }
064af421
BP
989 }
990}
991
2d071a32 992static enum ofperr
4bc938cc
BP
993ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh,
994 const struct ofputil_table_map *table_map)
26df8b3e 995{
0a2869d5 996 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
26df8b3e
SH
997 ofpraw_pull_assert(&b);
998
8811fc0a
BP
999 struct ofputil_table_features prev_features;
1000 struct ofputil_table_stats prev_stats;
1001 for (int i = 0;; i++) {
3c1bb396
BP
1002 struct ofputil_table_features features;
1003 struct ofputil_table_stats stats;
1004 int retval;
982697a4 1005
3c1bb396
BP
1006 retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
1007 if (retval) {
2d071a32 1008 return retval != EOF ? retval : 0;
982697a4
BP
1009 }
1010
8811fc0a 1011 ds_put_char(string, '\n');
dfc77282
BP
1012 ofputil_table_features_format(string,
1013 &features, i ? &prev_features : NULL,
1014 &stats, i ? &prev_stats : NULL,
1015 table_map);
8811fc0a
BP
1016 prev_features = features;
1017 prev_stats = stats;
26df8b3e
SH
1018 }
1019}
1020
d2805da2
BP
1021static void
1022ofp_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
2d071a32 1031static enum ofperr
50f96b10
BP
1032ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh,
1033 const struct ofputil_port_map *port_map)
d2805da2 1034{
64626975
SH
1035 struct ofputil_queue_stats_request oqsr;
1036 enum ofperr error;
1037
1038 error = ofputil_decode_queue_stats_request(oh, &oqsr);
1039 if (error) {
2d071a32 1040 return error;
64626975 1041 }
982697a4 1042
3e461c2c 1043 ds_put_cstr(string, " port=");
50f96b10 1044 ofputil_format_port(oqsr.port_no, port_map, string);
d2805da2
BP
1045
1046 ds_put_cstr(string, " queue=");
64626975 1047 ofp_print_queue_name(string, oqsr.queue_id);
2d071a32
BP
1048
1049 return 0;
f8e4867e
SH
1050}
1051
2d071a32 1052static enum ofperr
d1e2cf21 1053ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
50f96b10 1054 const struct ofputil_port_map *port_map,
d1e2cf21 1055 int verbosity)
d2805da2 1056{
34582733 1057 ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh));
d2805da2 1058 if (verbosity < 1) {
2d071a32 1059 return 0;
d2805da2
BP
1060 }
1061
0a2869d5 1062 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 1063 for (;;) {
64626975
SH
1064 struct ofputil_queue_stats qs;
1065 int retval;
1066
1067 retval = ofputil_decode_queue_stats(&qs, &b);
1068 if (retval) {
2d071a32 1069 return retval != EOF ? retval : 0;
982697a4
BP
1070 }
1071
d2805da2 1072 ds_put_cstr(string, " port ");
50f96b10 1073 ofputil_format_port(qs.port_no, port_map, string);
d2805da2 1074 ds_put_cstr(string, " queue ");
64626975 1075 ofp_print_queue_name(string, qs.queue_id);
d2805da2
BP
1076 ds_put_cstr(string, ": ");
1077
6dc34a0d
BP
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');
d2805da2
BP
1089 }
1090}
1091
2d071a32 1092static enum ofperr
70ae4f93 1093ofp_print_ofpst_port_desc_request(struct ds *string,
50f96b10
BP
1094 const struct ofp_header *oh,
1095 const struct ofputil_port_map *port_map)
70ae4f93
BP
1096{
1097 enum ofperr error;
1098 ofp_port_t port;
1099
1100 error = ofputil_decode_port_desc_stats_request(oh, &port);
1101 if (error) {
2d071a32 1102 return error;
70ae4f93
BP
1103 }
1104
1105 ds_put_cstr(string, " port=");
50f96b10 1106 ofputil_format_port(port, port_map, string);
2d071a32
BP
1107
1108 return 0;
70ae4f93
BP
1109}
1110
2d071a32 1111static enum ofperr
2be393ed
JP
1112ofp_print_ofpst_port_desc_reply(struct ds *string,
1113 const struct ofp_header *oh)
1114{
0a2869d5 1115 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 1116 ofpraw_pull_assert(&b);
2be393ed 1117 ds_put_char(string, '\n');
dfc77282 1118 return ofputil_phy_ports_format(string, oh->version, &b);
2be393ed
JP
1119}
1120
064af421 1121static void
5d40fc57 1122ofp_print_stats(struct ds *string, const struct ofp_header *oh)
064af421 1123{
982697a4 1124 uint16_t flags = ofpmp_flags(oh);
d1e2cf21 1125
982697a4 1126 if (flags) {
d1e2cf21 1127 ds_put_cstr(string, " flags=");
5d40fc57
SH
1128 if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
1129 && (flags & OFPSF_REPLY_MORE)) {
064af421
BP
1130 ds_put_cstr(string, "[more]");
1131 flags &= ~OFPSF_REPLY_MORE;
1132 }
1133 if (flags) {
d1e2cf21
BP
1134 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
1135 flags);
064af421
BP
1136 }
1137 }
064af421
BP
1138}
1139
2d071a32 1140static enum ofperr
d1e2cf21 1141ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
064af421 1142{
d1e2cf21 1143 size_t len = ntohs(oh->length);
064af421 1144
34582733 1145 ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
064af421 1146 if (verbosity > 1) {
d1e2cf21 1147 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
064af421 1148 }
2d071a32
BP
1149
1150 return 0;
064af421
BP
1151}
1152
61fe3a7b 1153static void
00467f73
AC
1154ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role,
1155 uint64_t generation_id)
61fe3a7b 1156{
61fe3a7b 1157 ds_put_cstr(string, " role=");
6ea4776b 1158
00467f73 1159 switch (role) {
f4f1ea7e
BP
1160 case OFPCR12_ROLE_NOCHANGE:
1161 ds_put_cstr(string, "nochange");
1162 break;
1163 case OFPCR12_ROLE_EQUAL:
6ea4776b
JR
1164 ds_put_cstr(string, "equal"); /* OF 1.2 wording */
1165 break;
f4f1ea7e 1166 case OFPCR12_ROLE_MASTER:
61fe3a7b 1167 ds_put_cstr(string, "master");
6ea4776b 1168 break;
f4f1ea7e 1169 case OFPCR12_ROLE_SLAVE:
61fe3a7b 1170 ds_put_cstr(string, "slave");
6ea4776b
JR
1171 break;
1172 default:
428b2edd 1173 OVS_NOT_REACHED();
6ea4776b
JR
1174 }
1175
00467f73
AC
1176 if (generation_id != UINT64_MAX) {
1177 ds_put_format(string, " generation_id=%"PRIu64, generation_id);
1178 }
1179}
1180
2d071a32 1181static enum ofperr
00467f73
AC
1182ofp_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) {
2d071a32 1189 return error;
00467f73
AC
1190 }
1191
1192 ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX);
2d071a32
BP
1193
1194 return 0;
00467f73
AC
1195}
1196
2d071a32 1197static enum ofperr
00467f73
AC
1198ofp_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) {
2d071a32 1205 return error;
00467f73
AC
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;
d18cc1ee 1222 case OFPCRR_N_REASONS:
00467f73 1223 default:
b76d4a81
BP
1224 ds_put_cstr(string, "(unknown)");
1225 break;
61fe3a7b 1226 }
2d071a32
BP
1227
1228 return 0;
61fe3a7b
BP
1229}
1230
2d071a32 1231static enum ofperr
225c33ba 1232ofp_print_nxt_flow_mod_table_id(struct ds *string, const struct ofp_header *oh)
6c1491fb 1233{
225c33ba
BP
1234 bool enable = ofputil_decode_nx_flow_mod_table_id(oh);
1235 ds_put_format(string, " %s", enable ? "enable" : "disable");
2d071a32 1236 return 0;
6c1491fb
BP
1237}
1238
2d071a32 1239static enum ofperr
225c33ba 1240ofp_print_nxt_set_flow_format(struct ds *string, const struct ofp_header *oh)
7fa91113 1241{
225c33ba
BP
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)");
2d071a32 1247 return 0;
7fa91113
BP
1248}
1249
2d071a32 1250static enum ofperr
54834960 1251ofp_print_nxt_set_packet_in_format(struct ds *string,
d8790c08 1252 const struct ofp_header *oh)
54834960 1253{
d8790c08
BP
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));
54834960 1259 }
d8790c08 1260 return error;
54834960
EJ
1261}
1262
8961699e
BP
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)
80d5aefd 1267static const char *
8961699e
BP
1268ofp_port_reason_to_string(enum ofp_port_reason reason,
1269 char *reasonbuf, size_t bufsize)
80d5aefd 1270{
80d5aefd
BP
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
d18cc1ee 1281 case OFPPR_N_REASONS:
80d5aefd 1282 default:
8961699e
BP
1283 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1284 return reasonbuf;
80d5aefd
BP
1285 }
1286}
1287
98090482
NR
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. */
1291static const char*
1292ofp_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
d18cc1ee 1305 case OFPCRR_N_REASONS:
98090482
NR
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. */
1315static const char*
1316ofp_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. */
1335static const char*
1336ofp_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
d18cc1ee 1346 case OFPRFR_N_REASONS:
98090482
NR
1347 default:
1348 snprintf(reasonbuf, bufsize, "%d", (int) reason);
1349 return reasonbuf;
1350 }
1351}
1352
1353static const char *
1354ofp_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)
2d071a32 1385static enum ofperr
904e5202 1386ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
71f21279 1387 enum ofptype ofptype)
80d5aefd 1388{
904e5202
BP
1389 struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
1390 struct ofputil_async_cfg ac;
80d5aefd 1391
71f21279 1392 bool is_reply = ofptype == OFPTYPE_GET_ASYNC_REPLY;
904e5202
BP
1393 enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
1394 &basis, &ac);
1395 if (error) {
2d071a32 1396 return error;
904e5202 1397 }
8961699e 1398
904e5202
BP
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));
80d5aefd 1404
904e5202
BP
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];
98090482 1409 const char *reason;
8961699e 1410
904e5202
BP
1411 reason = ofp_async_config_reason_to_string(
1412 j, type, reasonbuf, sizeof reasonbuf);
9bfe9334
BP
1413 if (reason[0]) {
1414 ds_put_format(string, " %s", reason);
1415 }
98090482 1416 }
80d5aefd 1417 }
904e5202 1418 if (!role) {
98090482
NR
1419 ds_put_cstr(string, " (off)");
1420 }
1421 ds_put_char(string, '\n');
80d5aefd 1422 }
80d5aefd 1423 }
2d071a32
BP
1424
1425 return 0;
80d5aefd
BP
1426}
1427
2d071a32 1428static enum ofperr
a7349929
BP
1429ofp_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));
2d071a32 1433 return 0;
a7349929
BP
1434}
1435
2d071a32 1436static enum ofperr
2b07c8b1
BP
1437ofp_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));
2d071a32 1442 return 0;
2b07c8b1
BP
1443}
1444
2d071a32 1445static enum ofperr
2b07c8b1 1446ofp_print_nxst_flow_monitor_request(struct ds *string,
50f96b10 1447 const struct ofp_header *oh,
4bc938cc
BP
1448 const struct ofputil_port_map *port_map,
1449 const struct ofputil_table_map *table_map)
2b07c8b1 1450{
0a2869d5 1451 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2b07c8b1
BP
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) {
2d071a32 1458 return retval != EOF ? retval : 0;
2b07c8b1
BP
1459 }
1460
dfc77282
BP
1461 ofputil_flow_monitor_request_format(string, &request,
1462 port_map, table_map);
2b07c8b1
BP
1463 }
1464}
1465
2d071a32 1466static enum ofperr
2b07c8b1 1467ofp_print_nxst_flow_monitor_reply(struct ds *string,
50f96b10 1468 const struct ofp_header *oh,
4bc938cc
BP
1469 const struct ofputil_port_map *port_map,
1470 const struct ofputil_table_map *table_map)
2b07c8b1
BP
1471{
1472 uint64_t ofpacts_stub[1024 / 8];
0a2869d5
BP
1473 struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
1474 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2b07c8b1 1475
2b07c8b1
BP
1476 for (;;) {
1477 struct ofputil_flow_update update;
dfc77282 1478 int retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
2b07c8b1 1479 if (retval) {
2b07c8b1 1480 ofpbuf_uninit(&ofpacts);
2d071a32 1481 return retval != EOF ? retval : 0;
2b07c8b1 1482 }
dfc77282 1483 ofputil_flow_update_format(string, &update, port_map, table_map);
2b07c8b1
BP
1484 }
1485}
1486
bdcc5925
BP
1487void
1488ofp_print_version(const struct ofp_header *oh,
1489 struct ds *string)
d1e2cf21 1490{
3811e66b
BP
1491 switch (oh->version) {
1492 case OFP10_VERSION:
1493 break;
1494 case OFP11_VERSION:
1495 ds_put_cstr(string, " (OF1.1)");
4232ef77
SH
1496 break;
1497 case OFP12_VERSION:
1498 ds_put_cstr(string, " (OF1.2)");
3811e66b 1499 break;
2e1ae200
JR
1500 case OFP13_VERSION:
1501 ds_put_cstr(string, " (OF1.3)");
1502 break;
9620f50c
AC
1503 case OFP14_VERSION:
1504 ds_put_cstr(string, " (OF1.4)");
1505 break;
42dccab5
BP
1506 case OFP15_VERSION:
1507 ds_put_cstr(string, " (OF1.5)");
1508 break;
b79d45a1
BP
1509 case OFP16_VERSION:
1510 ds_put_cstr(string, " (OF1.6)");
1511 break;
3811e66b
BP
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));
bdcc5925 1517}
d1e2cf21 1518
f25b4a81 1519static void
982697a4
BP
1520ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
1521 struct ds *string)
f25b4a81 1522{
982697a4 1523 ds_put_cstr(string, ofpraw_get_name(raw));
f25b4a81
BP
1524 ofp_print_version(oh, string);
1525}
1526
2d071a32 1527static enum ofperr
4bc938cc
BP
1528ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
1529 const struct ofputil_table_map *table_map)
03c72922 1530{
0a2869d5 1531 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
03c72922
BP
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) {
2d071a32 1538 return retval != EOF ? retval : 0;
03c72922 1539 }
dfc77282 1540 ofputil_table_desc_format(s, &td, table_map);
03c72922
BP
1541 }
1542}
1543
777af88d
AC
1544static const char *
1545bundle_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
2d071a32 1557static enum ofperr
777af88d
AC
1558ofp_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) {
2d071a32 1565 return error;
777af88d
AC
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, ' ');
2d071a32
BP
1600
1601 return 0;
777af88d
AC
1602}
1603
2d071a32 1604static enum ofperr
50f96b10 1605ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
4bc938cc
BP
1606 const struct ofputil_port_map *port_map,
1607 const struct ofputil_table_map *table_map,
1608 int verbosity)
777af88d
AC
1609{
1610 int error;
1611 struct ofputil_bundle_add_msg badd;
777af88d 1612
7ac27a04 1613 error = ofputil_decode_bundle_add(oh, &badd, NULL);
777af88d 1614 if (error) {
2d071a32 1615 return error;
777af88d
AC
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');
50f96b10 1624 char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map,
4bc938cc 1625 table_map, verbosity);
cf8fbeaa 1626 ds_put_and_free_cstr(s, msg);
2d071a32
BP
1627
1628 return 0;
777af88d
AC
1629}
1630
6159c531 1631static void
4e548ad9 1632print_tlv_table(struct ds *s, struct ovs_list *mappings)
6159c531 1633{
4e548ad9 1634 struct ofputil_tlv_map *map;
6159c531
JG
1635
1636 ds_put_cstr(s, " mapping table:\n");
5a0e4aec
BP
1637 ds_put_cstr(s, " class type length match field\n");
1638 ds_put_cstr(s, " ------ ---- ------ --------------");
6159c531
JG
1639
1640 LIST_FOR_EACH (map, list_node, mappings) {
5a0e4aec
BP
1641 ds_put_format(s, "\n %#6"PRIx16" %#4"PRIx8" %6"PRIu8" "
1642 "tun_metadata%"PRIu16,
6159c531
JG
1643 map->option_class, map->option_type, map->option_len,
1644 map->index);
1645 }
1646}
1647
2d071a32 1648static enum ofperr
4e548ad9 1649ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
6159c531
JG
1650{
1651 int error;
4e548ad9 1652 struct ofputil_tlv_table_mod ttm;
6159c531 1653
4e548ad9 1654 error = ofputil_decode_tlv_table_mod(oh, &ttm);
6159c531 1655 if (error) {
2d071a32 1656 return error;
6159c531
JG
1657 }
1658
1659 ds_put_cstr(s, "\n ");
1660
4e548ad9
ML
1661 switch (ttm.command) {
1662 case NXTTMC_ADD:
6159c531
JG
1663 ds_put_cstr(s, "ADD");
1664 break;
4e548ad9 1665 case NXTTMC_DELETE:
6159c531
JG
1666 ds_put_cstr(s, "DEL");
1667 break;
4e548ad9 1668 case NXTTMC_CLEAR:
6159c531
JG
1669 ds_put_cstr(s, "CLEAR");
1670 break;
1671 }
1672
4e548ad9
ML
1673 if (ttm.command != NXTTMC_CLEAR) {
1674 print_tlv_table(s, &ttm.mappings);
6159c531
JG
1675 }
1676
4e548ad9 1677 ofputil_uninit_tlv_table(&ttm.mappings);
2d071a32
BP
1678
1679 return 0;
6159c531
JG
1680}
1681
2d071a32 1682static enum ofperr
4e548ad9 1683ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
6159c531
JG
1684{
1685 int error;
4e548ad9
ML
1686 struct ofputil_tlv_table_reply ttr;
1687 struct ofputil_tlv_map *map;
6159c531
JG
1688 int allocated_space = 0;
1689
4e548ad9 1690 error = ofputil_decode_tlv_table_reply(oh, &ttr);
6159c531 1691 if (error) {
2d071a32 1692 return error;
6159c531
JG
1693 }
1694
1695 ds_put_char(s, '\n');
1696
4e548ad9 1697 LIST_FOR_EACH (map, list_node, &ttr.mappings) {
6159c531
JG
1698 allocated_space += map->option_len;
1699 }
1700
1701 ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
4e548ad9 1702 ttr.max_option_space, ttr.max_fields);
6159c531
JG
1703 ds_put_format(s, " allocated option space=%d\n", allocated_space);
1704 ds_put_char(s, '\n');
4e548ad9 1705 print_tlv_table(s, &ttr.mappings);
6159c531 1706
4e548ad9 1707 ofputil_uninit_tlv_table(&ttr.mappings);
2d071a32
BP
1708
1709 return 0;
6159c531
JG
1710}
1711
3c35db62
NR
1712/* This function will print the request forward message. The reason for
1713 * request forward is taken from rf.request.type */
2d071a32 1714static enum ofperr
50f96b10 1715ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
1716 const struct ofputil_port_map *port_map,
1717 const struct ofputil_table_map *table_map)
3c35db62
NR
1718{
1719 struct ofputil_requestforward rf;
1720 enum ofperr error;
1721
1722 error = ofputil_decode_requestforward(oh, &rf);
1723 if (error) {
2d071a32 1724 return error;
3c35db62
NR
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");
e9c9481f
BP
1732 ofputil_group_mod_format__(string, oh->version, rf.group_mod, port_map,
1733 table_map);
3c35db62
NR
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;
d18cc1ee
AA
1740
1741 case OFPRFR_N_REASONS:
1742 OVS_NOT_REACHED();
3c35db62
NR
1743 }
1744 ofputil_destroy_requestforward(&rf);
2d071a32
BP
1745
1746 return 0;
3c35db62
NR
1747}
1748
fb8f22c1
BY
1749static void
1750print_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
2d071a32 1765static enum ofperr
fb8f22c1
BY
1766ofp_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) {
2d071a32 1775 return retval != EOF ? retval : 0;
fb8f22c1
BY
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
2d071a32 1793static enum ofperr
fb8f22c1
BY
1794ofp_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) {
2d071a32 1805 return retval != EOF ? retval : 0;
fb8f22c1
BY
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
2d071a32 1824static enum ofperr
2a7c4805
JP
1825ofp_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));
2d071a32 1828 return 0;
2a7c4805
JP
1829}
1830
2d071a32 1831static enum ofperr
50f96b10 1832ofp_to_string__(const struct ofp_header *oh,
4bc938cc
BP
1833 const struct ofputil_port_map *port_map,
1834 const struct ofputil_table_map *table_map, enum ofpraw raw,
982697a4 1835 struct ds *string, int verbosity)
bdcc5925 1836{
e428148a
BP
1837 if (ofpmsg_is_stat(oh)) {
1838 ofp_print_stats(string, oh);
1839 }
1840
bdcc5925 1841 const void *msg = oh;
904e5202
BP
1842 enum ofptype type = ofptype_from_ofpraw(raw);
1843 switch (type) {
261bd854 1844 case OFPTYPE_GROUP_STATS_REQUEST:
e9c9481f 1845 return ofputil_group_stats_request_format(string, oh);
7395c052 1846
261bd854 1847 case OFPTYPE_GROUP_STATS_REPLY:
e9c9481f 1848 return ofputil_group_stats_format(string, oh);
7395c052 1849
261bd854 1850 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
e9c9481f 1851 return ofputil_group_desc_request_format(string, oh);
7395c052 1852
261bd854 1853 case OFPTYPE_GROUP_DESC_STATS_REPLY:
e9c9481f 1854 return ofputil_group_desc_format(string, oh, port_map, table_map);
7395c052 1855
261bd854 1856 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
7395c052
NZ
1857 break;
1858
261bd854 1859 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
e9c9481f 1860 return ofputil_group_features_format(string, oh);
7395c052
NZ
1861
1862 case OFPTYPE_GROUP_MOD:
e9c9481f 1863 return ofputil_group_mod_format(string, oh, port_map, table_map);
7395c052 1864
261bd854
BP
1865 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
1866 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
4bc938cc 1867 return ofp_print_table_features_reply(string, oh, table_map);
2e1ae200 1868
03c72922
BP
1869 case OFPTYPE_TABLE_DESC_REQUEST:
1870 case OFPTYPE_TABLE_DESC_REPLY:
4bc938cc 1871 return ofp_print_table_desc_reply(string, oh, table_map);
03c72922 1872
982697a4 1873 case OFPTYPE_HELLO:
2d071a32 1874 return ofp_print_hello(string, oh);
d1e2cf21 1875
982697a4 1876 case OFPTYPE_ERROR:
4bc938cc 1877 return ofp_print_error_msg(string, oh, port_map, table_map);
d1e2cf21 1878
982697a4
BP
1879 case OFPTYPE_ECHO_REQUEST:
1880 case OFPTYPE_ECHO_REPLY:
2d071a32 1881 return ofp_print_echo(string, oh, verbosity);
d1e2cf21 1882
982697a4 1883 case OFPTYPE_FEATURES_REQUEST:
d1e2cf21
BP
1884 break;
1885
982697a4 1886 case OFPTYPE_FEATURES_REPLY:
2d071a32 1887 return ofp_print_switch_features(string, oh);
d1e2cf21 1888
982697a4 1889 case OFPTYPE_GET_CONFIG_REQUEST:
d1e2cf21
BP
1890 break;
1891
982697a4 1892 case OFPTYPE_GET_CONFIG_REPLY:
2d071a32 1893 return ofp_print_get_config_reply(string, oh);
ad99e2ed 1894
982697a4 1895 case OFPTYPE_SET_CONFIG:
2d071a32 1896 return ofp_print_set_config(string, oh);
d1e2cf21 1897
982697a4 1898 case OFPTYPE_PACKET_IN:
4bc938cc 1899 return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
d1e2cf21 1900
982697a4 1901 case OFPTYPE_FLOW_REMOVED:
4bc938cc 1902 return ofp_print_flow_removed(string, oh, port_map, table_map);
d1e2cf21 1903
982697a4 1904 case OFPTYPE_PORT_STATUS:
2d071a32 1905 return ofp_print_port_status(string, oh);
d1e2cf21 1906
982697a4 1907 case OFPTYPE_PACKET_OUT:
4bc938cc
BP
1908 return ofp_print_packet_out(string, oh, port_map, table_map,
1909 verbosity);
d1e2cf21 1910
982697a4 1911 case OFPTYPE_FLOW_MOD:
dfc77282
BP
1912 return ofputil_flow_mod_format(string, oh, port_map, table_map,
1913 verbosity);
d1e2cf21 1914
982697a4 1915 case OFPTYPE_PORT_MOD:
2d071a32 1916 return ofp_print_port_mod(string, oh, port_map);
d1e2cf21 1917
918f2b82 1918 case OFPTYPE_TABLE_MOD:
4bc938cc 1919 return ofp_print_table_mod(string, oh, table_map);
918f2b82 1920
638a19b0 1921 case OFPTYPE_METER_MOD:
2d071a32 1922 return ofp_print_meter_mod(string, oh);
638a19b0 1923
982697a4
BP
1924 case OFPTYPE_BARRIER_REQUEST:
1925 case OFPTYPE_BARRIER_REPLY:
d1e2cf21
BP
1926 break;
1927
e8f9a7bb 1928 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
2d071a32 1929 return ofp_print_queue_get_config_request(string, oh, port_map);
e8f9a7bb
VG
1930
1931 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
2d071a32 1932 return ofp_print_queue_get_config_reply(string, oh, port_map);
e8f9a7bb 1933
6ea4776b
JR
1934 case OFPTYPE_ROLE_REQUEST:
1935 case OFPTYPE_ROLE_REPLY:
2d071a32 1936 return ofp_print_role_message(string, oh);
252f3411 1937 case OFPTYPE_ROLE_STATUS:
2d071a32 1938 return ofp_print_role_status_message(string, oh);
6ea4776b 1939
3c35db62 1940 case OFPTYPE_REQUESTFORWARD:
4bc938cc 1941 return ofp_print_requestforward(string, oh, port_map, table_map);
3c35db62 1942
6c6eedc5 1943 case OFPTYPE_TABLE_STATUS:
4bc938cc 1944 return ofp_print_table_status_message(string, oh, table_map);
6c6eedc5 1945
261bd854
BP
1946 case OFPTYPE_METER_STATS_REQUEST:
1947 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
2d071a32 1948 return ofp_print_meter_stats_request(string, oh);
638a19b0 1949
261bd854 1950 case OFPTYPE_METER_STATS_REPLY:
2d071a32 1951 return ofp_print_meter_stats_reply(string, oh);
638a19b0 1952
261bd854 1953 case OFPTYPE_METER_CONFIG_STATS_REPLY:
2d071a32 1954 return ofp_print_meter_config_reply(string, oh);
638a19b0 1955
261bd854 1956 case OFPTYPE_METER_FEATURES_STATS_REPLY:
2d071a32 1957 return ofp_print_meter_features_reply(string, oh);
638a19b0 1958
982697a4 1959 case OFPTYPE_DESC_STATS_REQUEST:
261bd854 1960 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
d1e2cf21
BP
1961 break;
1962
982697a4
BP
1963 case OFPTYPE_FLOW_STATS_REQUEST:
1964 case OFPTYPE_AGGREGATE_STATS_REQUEST:
4bc938cc 1965 return ofp_print_flow_stats_request(string, oh, port_map, table_map);
d1e2cf21 1966
982697a4 1967 case OFPTYPE_TABLE_STATS_REQUEST:
d1e2cf21
BP
1968 break;
1969
982697a4 1970 case OFPTYPE_PORT_STATS_REQUEST:
2d071a32 1971 return ofp_print_ofpst_port_request(string, oh, port_map);
d1e2cf21 1972
982697a4 1973 case OFPTYPE_QUEUE_STATS_REQUEST:
2d071a32 1974 return ofp_print_ofpst_queue_request(string, oh, port_map);
d1e2cf21 1975
982697a4 1976 case OFPTYPE_DESC_STATS_REPLY:
2d071a32 1977 return ofp_print_ofpst_desc_reply(string, oh);
d1e2cf21 1978
982697a4 1979 case OFPTYPE_FLOW_STATS_REPLY:
4bc938cc 1980 return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
d1e2cf21 1981
982697a4 1982 case OFPTYPE_QUEUE_STATS_REPLY:
2d071a32 1983 return ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity);
d1e2cf21 1984
982697a4 1985 case OFPTYPE_PORT_STATS_REPLY:
2d071a32 1986 return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
d1e2cf21 1987
982697a4 1988 case OFPTYPE_TABLE_STATS_REPLY:
4bc938cc 1989 return ofp_print_table_stats_reply(string, oh, table_map);
d1e2cf21 1990
982697a4 1991 case OFPTYPE_AGGREGATE_STATS_REPLY:
2d071a32 1992 return ofp_print_aggregate_stats_reply(string, oh);
064af421 1993
70ae4f93 1994 case OFPTYPE_PORT_DESC_STATS_REQUEST:
2d071a32 1995 return ofp_print_ofpst_port_desc_request(string, oh, port_map);
70ae4f93 1996
982697a4 1997 case OFPTYPE_PORT_DESC_STATS_REPLY:
2d071a32 1998 return ofp_print_ofpst_port_desc_reply(string, oh);
2be393ed 1999
982697a4 2000 case OFPTYPE_FLOW_MOD_TABLE_ID:
225c33ba 2001 return ofp_print_nxt_flow_mod_table_id(string, oh);
6c1491fb 2002
982697a4 2003 case OFPTYPE_SET_FLOW_FORMAT:
225c33ba 2004 return ofp_print_nxt_set_flow_format(string, oh);
7fa91113 2005
982697a4 2006 case OFPTYPE_SET_PACKET_IN_FORMAT:
d8790c08 2007 return ofp_print_nxt_set_packet_in_format(string, oh);
54834960 2008
982697a4 2009 case OFPTYPE_FLOW_AGE:
f27f2134
BP
2010 break;
2011
982697a4 2012 case OFPTYPE_SET_CONTROLLER_ID:
2d071a32 2013 return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
a7349929 2014
db09e430 2015 case OFPTYPE_GET_ASYNC_REPLY:
982697a4 2016 case OFPTYPE_SET_ASYNC_CONFIG:
2d071a32 2017 return ofp_print_set_async_config(string, oh, type);
db09e430
AC
2018 case OFPTYPE_GET_ASYNC_REQUEST:
2019 break;
982697a4 2020 case OFPTYPE_FLOW_MONITOR_CANCEL:
2d071a32 2021 return ofp_print_nxt_flow_monitor_cancel(string, msg);
2b07c8b1 2022
982697a4
BP
2023 case OFPTYPE_FLOW_MONITOR_PAUSED:
2024 case OFPTYPE_FLOW_MONITOR_RESUMED:
2b07c8b1
BP
2025 break;
2026
982697a4 2027 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
4bc938cc
BP
2028 return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
2029 table_map);
2b07c8b1 2030
982697a4 2031 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
4bc938cc
BP
2032 return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
2033 table_map);
777af88d
AC
2034
2035 case OFPTYPE_BUNDLE_CONTROL:
2d071a32 2036 return ofp_print_bundle_ctrl(string, msg);
777af88d
AC
2037
2038 case OFPTYPE_BUNDLE_ADD_MESSAGE:
4bc938cc
BP
2039 return ofp_print_bundle_add(string, msg, port_map, table_map,
2040 verbosity);
6159c531 2041
4e548ad9 2042 case OFPTYPE_NXT_TLV_TABLE_MOD:
2d071a32 2043 return ofp_print_tlv_table_mod(string, msg);
6159c531 2044
4e548ad9 2045 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
6159c531
JG
2046 break;
2047
4e548ad9 2048 case OFPTYPE_NXT_TLV_TABLE_REPLY:
2d071a32 2049 return ofp_print_tlv_table_reply(string, msg);
6159c531 2050
77ab5fd2 2051 case OFPTYPE_NXT_RESUME:
4bc938cc
BP
2052 return ofp_print_packet_in(string, msg, port_map, table_map,
2053 verbosity);
fb8f22c1
BY
2054 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
2055 break;
2056 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
2d071a32 2057 return ofp_print_nxst_ipfix_bridge_reply(string, oh);
fb8f22c1
BY
2058 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
2059 break;
2060 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
2d071a32 2061 return ofp_print_nxst_ipfix_flow_reply(string, oh);
2a7c4805
JP
2062
2063 case OFPTYPE_CT_FLUSH_ZONE:
2d071a32
BP
2064 return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
2065 }
2066
2067 return 0;
2068}
2069
2070static void
2071add_newline(struct ds *s)
2072{
2073 if (s->length && s->string[s->length - 1] != '\n') {
2074 ds_put_char(s, '\n');
246e61ea 2075 }
d1e2cf21 2076}
064af421
BP
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. */
2082char *
50f96b10 2083ofp_to_string(const void *oh_, size_t len,
4bc938cc
BP
2084 const struct ofputil_port_map *port_map,
2085 const struct ofputil_table_map *table_map,
2086 int verbosity)
064af421
BP
2087{
2088 struct ds string = DS_EMPTY_INITIALIZER;
2089 const struct ofp_header *oh = oh_;
064af421 2090
49ad0403
BP
2091 if (!len) {
2092 ds_put_cstr(&string, "OpenFlow message is empty\n");
2093 } else if (len < sizeof(struct ofp_header)) {
34582733 2094 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
49ad0403 2095 len);
d1e2cf21 2096 } else if (ntohs(oh->length) > len) {
f25b4a81 2097 enum ofperr error;
982697a4 2098 enum ofpraw raw;
f25b4a81 2099
982697a4 2100 error = ofpraw_decode_partial(&raw, oh, len);
f25b4a81 2101 if (!error) {
982697a4 2102 ofp_header_to_string__(oh, raw, &string);
f25b4a81
BP
2103 ds_put_char(&string, '\n');
2104 }
2105
d1e2cf21 2106 ds_put_format(&string,
34582733 2107 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
d1e2cf21
BP
2108 len, ntohs(oh->length));
2109 } else if (ntohs(oh->length) < len) {
2110 ds_put_format(&string,
34582733 2111 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
d1e2cf21
BP
2112 ntohs(oh->length), len);
2113 } else {
90bf1e07 2114 enum ofperr error;
982697a4 2115 enum ofpraw raw;
d1e2cf21 2116
982697a4 2117 error = ofpraw_decode(&raw, oh);
d1e2cf21 2118 if (!error) {
2d071a32
BP
2119 ofp_header_to_string__(oh, raw, &string);
2120 size_t header_len = string.length;
2121
4bc938cc
BP
2122 error = ofp_to_string__(oh, port_map, table_map,
2123 raw, &string, verbosity);
2d071a32
BP
2124 if (error) {
2125 if (string.length > header_len) {
2126 ds_chomp(&string, ' ');
2127 add_newline(&string);
2128 } else {
2129 ds_put_char(&string, ' ');
7fa91113 2130 }
2d071a32
BP
2131 ofp_print_error(&string, error);
2132 } else {
2133 ds_chomp(&string, ' ');
d1e2cf21 2134 }
2d071a32
BP
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);
064af421 2142 }
064af421 2143
2d071a32
BP
2144 add_newline(&string);
2145 return ds_steal_cstr(&string);
064af421 2146 }
d1e2cf21
BP
2147 ds_put_hex_dump(&string, oh, len, 0, true);
2148 return ds_steal_cstr(&string);
064af421 2149}
064af421
BP
2150\f
2151static void
d295e8e9 2152print_and_free(FILE *stream, char *string)
064af421
BP
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. */
2161void
50f96b10 2162ofp_print(FILE *stream, const void *oh, size_t len,
4bc938cc
BP
2163 const struct ofputil_port_map *port_map,
2164 const struct ofputil_table_map *table_map, int verbosity)
064af421 2165{
4bc938cc
BP
2166 print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
2167 verbosity));
064af421
BP
2168}
2169
2170/* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
897a8e07 2171 * 'data' to 'stream'. */
064af421 2172void
2482b0b0
JS
2173ofp_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
2179void
2180ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
064af421 2181{
2482b0b0 2182 print_and_free(stream, ofp_dp_packet_to_string(packet));
064af421 2183}