]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-print.c
dpif-netdev: Reorder elements in dp_netdev_port structure.
[mirror_ovs.git] / lib / ofp-print.c
1 /*
2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 <errno.h>
20 #include <inttypes.h>
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <sys/wait.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27
28 #include "bundle.h"
29 #include "byte-order.h"
30 #include "colors.h"
31 #include "compiler.h"
32 #include "dp-packet.h"
33 #include "flow.h"
34 #include "learn.h"
35 #include "multipath.h"
36 #include "netdev.h"
37 #include "nx-match.h"
38 #include "odp-util.h"
39 #include "openflow/nicira-ext.h"
40 #include "openflow/openflow.h"
41 #include "openvswitch/dynamic-string.h"
42 #include "openvswitch/meta-flow.h"
43 #include "openvswitch/ofp-actions.h"
44 #include "openvswitch/ofp-errors.h"
45 #include "openvswitch/ofp-msgs.h"
46 #include "openvswitch/ofp-print.h"
47 #include "openvswitch/ofp-util.h"
48 #include "openvswitch/ofpbuf.h"
49 #include "openvswitch/type-props.h"
50 #include "packets.h"
51 #include "unaligned.h"
52 #include "util.h"
53 #include "uuid.h"
54
55 static void ofp_print_queue_name(struct ds *string, uint32_t port);
56 static void ofp_print_error(struct ds *, enum ofperr);
57
58 /* Returns a string that represents the contents of the Ethernet frame in the
59 * 'len' bytes starting at 'data'. The caller must free the returned string.*/
60 char *
61 ofp_packet_to_string(const void *data, size_t len)
62 {
63 struct ds ds = DS_EMPTY_INITIALIZER;
64 struct dp_packet buf;
65 struct flow flow;
66 size_t l4_size;
67
68 dp_packet_use_const(&buf, data, len);
69 flow_extract(&buf, &flow);
70 flow_format(&ds, &flow);
71
72 l4_size = dp_packet_l4_size(&buf);
73
74 if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
75 struct tcp_header *th = dp_packet_l4(&buf);
76 ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum));
77 } else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
78 struct udp_header *uh = dp_packet_l4(&buf);
79 ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum));
80 } else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) {
81 struct sctp_header *sh = dp_packet_l4(&buf);
82 ds_put_format(&ds, " sctp_csum:%"PRIx32,
83 ntohl(get_16aligned_be32(&sh->sctp_csum)));
84 } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
85 struct icmp_header *icmph = dp_packet_l4(&buf);
86 ds_put_format(&ds, " icmp_csum:%"PRIx16,
87 ntohs(icmph->icmp_csum));
88 } else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= ICMP6_HEADER_LEN) {
89 struct icmp6_header *icmp6h = dp_packet_l4(&buf);
90 ds_put_format(&ds, " icmp6_csum:%"PRIx16,
91 ntohs(icmp6h->icmp6_cksum));
92 }
93
94 ds_put_char(&ds, '\n');
95
96 return ds_cstr(&ds);
97 }
98
99 static void
100 format_hex_arg(struct ds *s, const uint8_t *data, size_t len)
101 {
102 for (size_t i = 0; i < len; i++) {
103 if (i) {
104 ds_put_char(s, '.');
105 }
106 ds_put_format(s, "%02"PRIx8, data[i]);
107 }
108 }
109
110 static void
111 ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
112 int verbosity)
113 {
114 char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
115 struct ofputil_packet_in_private pin;
116 const struct ofputil_packet_in *public = &pin.public;
117 uint32_t buffer_id;
118 size_t total_len;
119 enum ofperr error;
120
121 error = ofputil_decode_packet_in_private(oh, true, NULL,
122 &pin, &total_len, &buffer_id);
123 if (error) {
124 ofp_print_error(string, error);
125 return;
126 }
127
128 if (public->table_id) {
129 ds_put_format(string, " table_id=%"PRIu8, public->table_id);
130 }
131
132 if (public->cookie != OVS_BE64_MAX) {
133 ds_put_format(string, " cookie=0x%"PRIx64, ntohll(public->cookie));
134 }
135
136 ds_put_format(string, " total_len=%"PRIuSIZE" ", total_len);
137
138 match_format(&public->flow_metadata, string, OFP_DEFAULT_PRIORITY);
139
140 ds_put_format(string, " (via %s)",
141 ofputil_packet_in_reason_to_string(public->reason,
142 reasonbuf,
143 sizeof reasonbuf));
144
145 ds_put_format(string, " data_len=%"PRIuSIZE, public->packet_len);
146 if (buffer_id == UINT32_MAX) {
147 ds_put_format(string, " (unbuffered)");
148 if (total_len != public->packet_len) {
149 ds_put_format(string, " (***total_len != data_len***)");
150 }
151 } else {
152 ds_put_format(string, " buffer=0x%08"PRIx32, buffer_id);
153 if (total_len < public->packet_len) {
154 ds_put_format(string, " (***total_len < data_len***)");
155 }
156 }
157 ds_put_char(string, '\n');
158
159 if (public->userdata_len) {
160 ds_put_cstr(string, " userdata=");
161 format_hex_arg(string, pin.public.userdata, pin.public.userdata_len);
162 ds_put_char(string, '\n');
163 }
164
165 if (!uuid_is_zero(&pin.bridge)) {
166 ds_put_format(string, " continuation.bridge="UUID_FMT"\n",
167 UUID_ARGS(&pin.bridge));
168 }
169
170 if (pin.n_stack) {
171 ds_put_cstr(string, " continuation.stack=");
172 for (size_t i = 0; i < pin.n_stack; i++) {
173 if (i) {
174 ds_put_char(string, ' ');
175 }
176 mf_subvalue_format(&pin.stack[i], string);
177 }
178 }
179
180 if (pin.mirrors) {
181 ds_put_format(string, " continuation.mirrors=0x%"PRIx32"\n",
182 pin.mirrors);
183 }
184
185 if (pin.conntracked) {
186 ds_put_cstr(string, " continuation.conntracked=true\n");
187 }
188
189 if (pin.actions_len) {
190 ds_put_cstr(string, " continuation.actions=");
191 ofpacts_format(pin.actions, pin.actions_len, string);
192 ds_put_char(string, '\n');
193 }
194
195 if (pin.action_set_len) {
196 ds_put_cstr(string, " continuation.action_set=");
197 ofpacts_format(pin.action_set, pin.action_set_len, string);
198 ds_put_char(string, '\n');
199 }
200
201 if (verbosity > 0) {
202 char *packet = ofp_packet_to_string(public->packet,
203 public->packet_len);
204 ds_put_cstr(string, packet);
205 free(packet);
206 }
207 if (verbosity > 2) {
208 ds_put_hex_dump(string, public->packet, public->packet_len, 0, false);
209 }
210
211 ofputil_packet_in_private_destroy(&pin);
212 }
213
214 static void
215 ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
216 int verbosity)
217 {
218 struct ofputil_packet_out po;
219 struct ofpbuf ofpacts;
220 enum ofperr error;
221
222 ofpbuf_init(&ofpacts, 64);
223 error = ofputil_decode_packet_out(&po, oh, &ofpacts);
224 if (error) {
225 ofpbuf_uninit(&ofpacts);
226 ofp_print_error(string, error);
227 return;
228 }
229
230 ds_put_cstr(string, " in_port=");
231 ofputil_format_port(po.in_port, string);
232
233 ds_put_cstr(string, " actions=");
234 ofpacts_format(po.ofpacts, po.ofpacts_len, string);
235
236 if (po.buffer_id == UINT32_MAX) {
237 ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len);
238 if (verbosity > 0 && po.packet_len > 0) {
239 char *packet = ofp_packet_to_string(po.packet, po.packet_len);
240 ds_put_char(string, '\n');
241 ds_put_cstr(string, packet);
242 free(packet);
243 }
244 if (verbosity > 2) {
245 ds_put_hex_dump(string, po.packet, po.packet_len, 0, false);
246 }
247 } else {
248 ds_put_format(string, " buffer=0x%08"PRIx32, po.buffer_id);
249 }
250
251 ofpbuf_uninit(&ofpacts);
252 }
253
254 /* qsort comparison function. */
255 static int
256 compare_ports(const void *a_, const void *b_)
257 {
258 const struct ofputil_phy_port *a = a_;
259 const struct ofputil_phy_port *b = b_;
260 uint16_t ap = ofp_to_u16(a->port_no);
261 uint16_t bp = ofp_to_u16(b->port_no);
262
263 return ap < bp ? -1 : ap > bp;
264 }
265
266 static void
267 ofp_print_bit_names(struct ds *string, uint32_t bits,
268 const char *(*bit_to_name)(uint32_t bit),
269 char separator)
270 {
271 int n = 0;
272 int i;
273
274 if (!bits) {
275 ds_put_cstr(string, "0");
276 return;
277 }
278
279 for (i = 0; i < 32; i++) {
280 uint32_t bit = UINT32_C(1) << i;
281
282 if (bits & bit) {
283 const char *name = bit_to_name(bit);
284 if (name) {
285 if (n++) {
286 ds_put_char(string, separator);
287 }
288 ds_put_cstr(string, name);
289 bits &= ~bit;
290 }
291 }
292 }
293
294 if (bits) {
295 if (n) {
296 ds_put_char(string, separator);
297 }
298 ds_put_format(string, "0x%"PRIx32, bits);
299 }
300 }
301
302 static const char *
303 netdev_feature_to_name(uint32_t bit)
304 {
305 enum netdev_features f = bit;
306
307 switch (f) {
308 case NETDEV_F_10MB_HD: return "10MB-HD";
309 case NETDEV_F_10MB_FD: return "10MB-FD";
310 case NETDEV_F_100MB_HD: return "100MB-HD";
311 case NETDEV_F_100MB_FD: return "100MB-FD";
312 case NETDEV_F_1GB_HD: return "1GB-HD";
313 case NETDEV_F_1GB_FD: return "1GB-FD";
314 case NETDEV_F_10GB_FD: return "10GB-FD";
315 case NETDEV_F_40GB_FD: return "40GB-FD";
316 case NETDEV_F_100GB_FD: return "100GB-FD";
317 case NETDEV_F_1TB_FD: return "1TB-FD";
318 case NETDEV_F_OTHER: return "OTHER";
319 case NETDEV_F_COPPER: return "COPPER";
320 case NETDEV_F_FIBER: return "FIBER";
321 case NETDEV_F_AUTONEG: return "AUTO_NEG";
322 case NETDEV_F_PAUSE: return "AUTO_PAUSE";
323 case NETDEV_F_PAUSE_ASYM: return "AUTO_PAUSE_ASYM";
324 }
325
326 return NULL;
327 }
328
329 static void
330 ofp_print_port_features(struct ds *string, enum netdev_features features)
331 {
332 ofp_print_bit_names(string, features, netdev_feature_to_name, ' ');
333 ds_put_char(string, '\n');
334 }
335
336 static const char *
337 ofputil_port_config_to_name(uint32_t bit)
338 {
339 enum ofputil_port_config pc = bit;
340
341 switch (pc) {
342 case OFPUTIL_PC_PORT_DOWN: return "PORT_DOWN";
343 case OFPUTIL_PC_NO_STP: return "NO_STP";
344 case OFPUTIL_PC_NO_RECV: return "NO_RECV";
345 case OFPUTIL_PC_NO_RECV_STP: return "NO_RECV_STP";
346 case OFPUTIL_PC_NO_FLOOD: return "NO_FLOOD";
347 case OFPUTIL_PC_NO_FWD: return "NO_FWD";
348 case OFPUTIL_PC_NO_PACKET_IN: return "NO_PACKET_IN";
349 }
350
351 return NULL;
352 }
353
354 static void
355 ofp_print_port_config(struct ds *string, enum ofputil_port_config config)
356 {
357 ofp_print_bit_names(string, config, ofputil_port_config_to_name, ' ');
358 ds_put_char(string, '\n');
359 }
360
361 static const char *
362 ofputil_port_state_to_name(uint32_t bit)
363 {
364 enum ofputil_port_state ps = bit;
365
366 switch (ps) {
367 case OFPUTIL_PS_LINK_DOWN: return "LINK_DOWN";
368 case OFPUTIL_PS_BLOCKED: return "BLOCKED";
369 case OFPUTIL_PS_LIVE: return "LIVE";
370
371 case OFPUTIL_PS_STP_LISTEN:
372 case OFPUTIL_PS_STP_LEARN:
373 case OFPUTIL_PS_STP_FORWARD:
374 case OFPUTIL_PS_STP_BLOCK:
375 /* Handled elsewhere. */
376 return NULL;
377 }
378
379 return NULL;
380 }
381
382 static void
383 ofp_print_port_state(struct ds *string, enum ofputil_port_state state)
384 {
385 enum ofputil_port_state stp_state;
386
387 /* The STP state is a 2-bit field so it doesn't fit in with the bitmask
388 * pattern. We have to special case it.
389 *
390 * OVS doesn't support STP, so this field will always be 0 if we are
391 * talking to OVS, so we'd always print STP_LISTEN in that case.
392 * Therefore, we don't print anything at all if the value is STP_LISTEN, to
393 * avoid confusing users. */
394 stp_state = state & OFPUTIL_PS_STP_MASK;
395 if (stp_state) {
396 ds_put_cstr(string,
397 (stp_state == OFPUTIL_PS_STP_LEARN ? "STP_LEARN"
398 : stp_state == OFPUTIL_PS_STP_FORWARD ? "STP_FORWARD"
399 : "STP_BLOCK"));
400 state &= ~OFPUTIL_PS_STP_MASK;
401 if (state) {
402 ofp_print_bit_names(string, state, ofputil_port_state_to_name,
403 ' ');
404 }
405 } else {
406 ofp_print_bit_names(string, state, ofputil_port_state_to_name, ' ');
407 }
408 ds_put_char(string, '\n');
409 }
410
411 static void
412 ofp_print_phy_port(struct ds *string, const struct ofputil_phy_port *port)
413 {
414 char name[sizeof port->name];
415 int j;
416
417 memcpy(name, port->name, sizeof name);
418 for (j = 0; j < sizeof name - 1; j++) {
419 if (!isprint((unsigned char) name[j])) {
420 break;
421 }
422 }
423 name[j] = '\0';
424
425 ds_put_char(string, ' ');
426 ofputil_format_port(port->port_no, string);
427 ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT"\n",
428 name, ETH_ADDR_ARGS(port->hw_addr));
429
430 ds_put_cstr(string, " config: ");
431 ofp_print_port_config(string, port->config);
432
433 ds_put_cstr(string, " state: ");
434 ofp_print_port_state(string, port->state);
435
436 if (port->curr) {
437 ds_put_format(string, " current: ");
438 ofp_print_port_features(string, port->curr);
439 }
440 if (port->advertised) {
441 ds_put_format(string, " advertised: ");
442 ofp_print_port_features(string, port->advertised);
443 }
444 if (port->supported) {
445 ds_put_format(string, " supported: ");
446 ofp_print_port_features(string, port->supported);
447 }
448 if (port->peer) {
449 ds_put_format(string, " peer: ");
450 ofp_print_port_features(string, port->peer);
451 }
452 ds_put_format(string, " speed: %"PRIu32" Mbps now, "
453 "%"PRIu32" Mbps max\n",
454 port->curr_speed / UINT32_C(1000),
455 port->max_speed / UINT32_C(1000));
456 }
457
458 /* Given a buffer 'b' that contains an array of OpenFlow ports of type
459 * 'ofp_version', writes a detailed description of each port into
460 * 'string'. */
461 static void
462 ofp_print_phy_ports(struct ds *string, uint8_t ofp_version,
463 struct ofpbuf *b)
464 {
465 struct ofputil_phy_port *ports;
466 size_t allocated_ports, n_ports;
467 int retval;
468 size_t i;
469
470 ports = NULL;
471 allocated_ports = 0;
472 for (n_ports = 0; ; n_ports++) {
473 if (n_ports >= allocated_ports) {
474 ports = x2nrealloc(ports, &allocated_ports, sizeof *ports);
475 }
476
477 retval = ofputil_pull_phy_port(ofp_version, b, &ports[n_ports]);
478 if (retval) {
479 break;
480 }
481 }
482
483 qsort(ports, n_ports, sizeof *ports, compare_ports);
484 for (i = 0; i < n_ports; i++) {
485 ofp_print_phy_port(string, &ports[i]);
486 }
487 free(ports);
488
489 if (retval != EOF) {
490 ofp_print_error(string, retval);
491 }
492 }
493
494 static const char *
495 ofputil_capabilities_to_name(uint32_t bit)
496 {
497 enum ofputil_capabilities capabilities = bit;
498
499 switch (capabilities) {
500 case OFPUTIL_C_FLOW_STATS: return "FLOW_STATS";
501 case OFPUTIL_C_TABLE_STATS: return "TABLE_STATS";
502 case OFPUTIL_C_PORT_STATS: return "PORT_STATS";
503 case OFPUTIL_C_IP_REASM: return "IP_REASM";
504 case OFPUTIL_C_QUEUE_STATS: return "QUEUE_STATS";
505 case OFPUTIL_C_ARP_MATCH_IP: return "ARP_MATCH_IP";
506 case OFPUTIL_C_STP: return "STP";
507 case OFPUTIL_C_GROUP_STATS: return "GROUP_STATS";
508 case OFPUTIL_C_PORT_BLOCKED: return "PORT_BLOCKED";
509 }
510
511 return NULL;
512 }
513
514 static void
515 ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
516 {
517 struct ofputil_switch_features features;
518 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
519 enum ofperr error = ofputil_pull_switch_features(&b, &features);
520 if (error) {
521 ofp_print_error(string, error);
522 return;
523 }
524
525 ds_put_format(string, " dpid:%016"PRIx64"\n", features.datapath_id);
526
527 ds_put_format(string, "n_tables:%"PRIu8", n_buffers:%"PRIu32,
528 features.n_tables, features.n_buffers);
529 if (features.auxiliary_id) {
530 ds_put_format(string, ", auxiliary_id:%"PRIu8, features.auxiliary_id);
531 }
532 ds_put_char(string, '\n');
533
534 ds_put_cstr(string, "capabilities: ");
535 ofp_print_bit_names(string, features.capabilities,
536 ofputil_capabilities_to_name, ' ');
537 ds_put_char(string, '\n');
538
539 switch ((enum ofp_version)oh->version) {
540 case OFP10_VERSION:
541 ds_put_cstr(string, "actions: ");
542 ofpact_bitmap_format(features.ofpacts, string);
543 ds_put_char(string, '\n');
544 break;
545 case OFP11_VERSION:
546 case OFP12_VERSION:
547 break;
548 case OFP13_VERSION:
549 case OFP14_VERSION:
550 case OFP15_VERSION:
551 case OFP16_VERSION:
552 return; /* no ports in ofp13_switch_features */
553 default:
554 OVS_NOT_REACHED();
555 }
556
557 ofp_print_phy_ports(string, oh->version, &b);
558 }
559
560 static void
561 ofp_print_switch_config(struct ds *string,
562 const struct ofputil_switch_config *config)
563 {
564 ds_put_format(string, " frags=%s",
565 ofputil_frag_handling_to_string(config->frag));
566
567 if (config->invalid_ttl_to_controller > 0) {
568 ds_put_format(string, " invalid_ttl_to_controller");
569 }
570
571 ds_put_format(string, " miss_send_len=%"PRIu16"\n", config->miss_send_len);
572 }
573
574 static void
575 ofp_print_set_config(struct ds *string, const struct ofp_header *oh)
576 {
577 struct ofputil_switch_config config;
578 enum ofperr error;
579
580 error = ofputil_decode_set_config(oh, &config);
581 if (error) {
582 ofp_print_error(string, error);
583 return;
584 }
585 ofp_print_switch_config(string, &config);
586 }
587
588 static void
589 ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh)
590 {
591 struct ofputil_switch_config config;
592 ofputil_decode_get_config_reply(oh, &config);
593 ofp_print_switch_config(string, &config);
594 }
595
596 static void print_wild(struct ds *string, const char *leader, int is_wild,
597 int verbosity, const char *format, ...)
598 OVS_PRINTF_FORMAT(5, 6);
599
600 static void print_wild(struct ds *string, const char *leader, int is_wild,
601 int verbosity, const char *format, ...)
602 {
603 if (is_wild && verbosity < 2) {
604 return;
605 }
606 ds_put_cstr(string, leader);
607 if (!is_wild) {
608 va_list args;
609
610 va_start(args, format);
611 ds_put_format_valist(string, format, args);
612 va_end(args);
613 } else {
614 ds_put_char(string, '*');
615 }
616 ds_put_char(string, ',');
617 }
618
619 static void
620 print_wild_port(struct ds *string, const char *leader, int is_wild,
621 int verbosity, ofp_port_t port)
622 {
623 if (is_wild && verbosity < 2) {
624 return;
625 }
626 ds_put_cstr(string, leader);
627 if (!is_wild) {
628 ofputil_format_port(port, string);
629 } else {
630 ds_put_char(string, '*');
631 }
632 ds_put_char(string, ',');
633 }
634
635 static void
636 print_ip_netmask(struct ds *string, const char *leader, ovs_be32 ip,
637 uint32_t wild_bits, int verbosity)
638 {
639 if (wild_bits >= 32 && verbosity < 2) {
640 return;
641 }
642 ds_put_cstr(string, leader);
643 if (wild_bits < 32) {
644 ds_put_format(string, IP_FMT, IP_ARGS(ip));
645 if (wild_bits) {
646 ds_put_format(string, "/%d", 32 - wild_bits);
647 }
648 } else {
649 ds_put_char(string, '*');
650 }
651 ds_put_char(string, ',');
652 }
653
654 void
655 ofp10_match_print(struct ds *f, const struct ofp10_match *om, int verbosity)
656 {
657 char *s = ofp10_match_to_string(om, verbosity);
658 ds_put_cstr(f, s);
659 free(s);
660 }
661
662 char *
663 ofp10_match_to_string(const struct ofp10_match *om, int verbosity)
664 {
665 struct ds f = DS_EMPTY_INITIALIZER;
666 uint32_t w = ntohl(om->wildcards);
667 bool skip_type = false;
668 bool skip_proto = false;
669
670 if (!(w & OFPFW10_DL_TYPE)) {
671 skip_type = true;
672 if (om->dl_type == htons(ETH_TYPE_IP)) {
673 if (!(w & OFPFW10_NW_PROTO)) {
674 skip_proto = true;
675 if (om->nw_proto == IPPROTO_ICMP) {
676 ds_put_cstr(&f, "icmp,");
677 } else if (om->nw_proto == IPPROTO_TCP) {
678 ds_put_cstr(&f, "tcp,");
679 } else if (om->nw_proto == IPPROTO_UDP) {
680 ds_put_cstr(&f, "udp,");
681 } else if (om->nw_proto == IPPROTO_SCTP) {
682 ds_put_cstr(&f, "sctp,");
683 } else {
684 ds_put_cstr(&f, "ip,");
685 skip_proto = false;
686 }
687 } else {
688 ds_put_cstr(&f, "ip,");
689 }
690 } else if (om->dl_type == htons(ETH_TYPE_ARP)) {
691 ds_put_cstr(&f, "arp,");
692 } else if (om->dl_type == htons(ETH_TYPE_RARP)){
693 ds_put_cstr(&f, "rarp,");
694 } else if (om->dl_type == htons(ETH_TYPE_MPLS)) {
695 ds_put_cstr(&f, "mpls,");
696 } else if (om->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
697 ds_put_cstr(&f, "mplsm,");
698 } else {
699 skip_type = false;
700 }
701 }
702 print_wild_port(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity,
703 u16_to_ofp(ntohs(om->in_port)));
704 print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity,
705 "%d", ntohs(om->dl_vlan));
706 print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity,
707 "%d", om->dl_vlan_pcp);
708 print_wild(&f, "dl_src=", w & OFPFW10_DL_SRC, verbosity,
709 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
710 print_wild(&f, "dl_dst=", w & OFPFW10_DL_DST, verbosity,
711 ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
712 if (!skip_type) {
713 print_wild(&f, "dl_type=", w & OFPFW10_DL_TYPE, verbosity,
714 "0x%04x", ntohs(om->dl_type));
715 }
716 print_ip_netmask(&f, "nw_src=", om->nw_src,
717 (w & OFPFW10_NW_SRC_MASK) >> OFPFW10_NW_SRC_SHIFT,
718 verbosity);
719 print_ip_netmask(&f, "nw_dst=", om->nw_dst,
720 (w & OFPFW10_NW_DST_MASK) >> OFPFW10_NW_DST_SHIFT,
721 verbosity);
722 if (!skip_proto) {
723 if (om->dl_type == htons(ETH_TYPE_ARP) ||
724 om->dl_type == htons(ETH_TYPE_RARP)) {
725 print_wild(&f, "arp_op=", w & OFPFW10_NW_PROTO, verbosity,
726 "%u", om->nw_proto);
727 } else {
728 print_wild(&f, "nw_proto=", w & OFPFW10_NW_PROTO, verbosity,
729 "%u", om->nw_proto);
730 }
731 }
732 print_wild(&f, "nw_tos=", w & OFPFW10_NW_TOS, verbosity,
733 "%u", om->nw_tos);
734 if (om->nw_proto == IPPROTO_ICMP) {
735 print_wild(&f, "icmp_type=", w & OFPFW10_ICMP_TYPE, verbosity,
736 "%d", ntohs(om->tp_src));
737 print_wild(&f, "icmp_code=", w & OFPFW10_ICMP_CODE, verbosity,
738 "%d", ntohs(om->tp_dst));
739 } else {
740 print_wild(&f, "tp_src=", w & OFPFW10_TP_SRC, verbosity,
741 "%d", ntohs(om->tp_src));
742 print_wild(&f, "tp_dst=", w & OFPFW10_TP_DST, verbosity,
743 "%d", ntohs(om->tp_dst));
744 }
745 ds_chomp(&f, ',');
746 return ds_cstr(&f);
747 }
748
749 static void
750 ofp_print_flow_flags(struct ds *s, enum ofputil_flow_mod_flags flags)
751 {
752 if (flags & OFPUTIL_FF_SEND_FLOW_REM) {
753 ds_put_cstr(s, "send_flow_rem ");
754 }
755 if (flags & OFPUTIL_FF_CHECK_OVERLAP) {
756 ds_put_cstr(s, "check_overlap ");
757 }
758 if (flags & OFPUTIL_FF_RESET_COUNTS) {
759 ds_put_cstr(s, "reset_counts ");
760 }
761 if (flags & OFPUTIL_FF_NO_PKT_COUNTS) {
762 ds_put_cstr(s, "no_packet_counts ");
763 }
764 if (flags & OFPUTIL_FF_NO_BYT_COUNTS) {
765 ds_put_cstr(s, "no_byte_counts ");
766 }
767 if (flags & OFPUTIL_FF_HIDDEN_FIELDS) {
768 ds_put_cstr(s, "allow_hidden_fields ");
769 }
770 if (flags & OFPUTIL_FF_NO_READONLY) {
771 ds_put_cstr(s, "no_readonly_table ");
772 }
773 }
774
775 static void
776 ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity)
777 {
778 struct ofputil_flow_mod fm;
779 struct ofpbuf ofpacts;
780 bool need_priority;
781 enum ofperr error;
782 enum ofpraw raw;
783 enum ofputil_protocol protocol;
784
785 protocol = ofputil_protocol_from_ofp_version(oh->version);
786 protocol = ofputil_protocol_set_tid(protocol, true);
787
788 ofpbuf_init(&ofpacts, 64);
789 error = ofputil_decode_flow_mod(&fm, oh, protocol, NULL, &ofpacts,
790 OFPP_MAX, 255);
791 if (error) {
792 ofpbuf_uninit(&ofpacts);
793 ofp_print_error(s, error);
794 return;
795 }
796
797 ds_put_char(s, ' ');
798 switch (fm.command) {
799 case OFPFC_ADD:
800 ds_put_cstr(s, "ADD");
801 break;
802 case OFPFC_MODIFY:
803 ds_put_cstr(s, "MOD");
804 break;
805 case OFPFC_MODIFY_STRICT:
806 ds_put_cstr(s, "MOD_STRICT");
807 break;
808 case OFPFC_DELETE:
809 ds_put_cstr(s, "DEL");
810 break;
811 case OFPFC_DELETE_STRICT:
812 ds_put_cstr(s, "DEL_STRICT");
813 break;
814 default:
815 ds_put_format(s, "cmd:%d", fm.command);
816 }
817 if (fm.table_id != 0) {
818 ds_put_format(s, " table:%d", fm.table_id);
819 }
820
821 ds_put_char(s, ' ');
822 ofpraw_decode(&raw, oh);
823 if (verbosity >= 3 && raw == OFPRAW_OFPT10_FLOW_MOD) {
824 const struct ofp10_flow_mod *ofm = ofpmsg_body(oh);
825 ofp10_match_print(s, &ofm->match, verbosity);
826
827 /* ofp_print_match() doesn't print priority. */
828 need_priority = true;
829 } else if (verbosity >= 3 && raw == OFPRAW_NXT_FLOW_MOD) {
830 const struct nx_flow_mod *nfm = ofpmsg_body(oh);
831 const void *nxm = nfm + 1;
832 char *nxm_s;
833
834 nxm_s = nx_match_to_string(nxm, ntohs(nfm->match_len));
835 ds_put_cstr(s, nxm_s);
836 free(nxm_s);
837
838 /* nx_match_to_string() doesn't print priority. */
839 need_priority = true;
840 } else {
841 match_format(&fm.match, s, fm.priority);
842
843 /* match_format() does print priority. */
844 need_priority = false;
845 }
846
847 if (ds_last(s) != ' ') {
848 ds_put_char(s, ' ');
849 }
850 if (fm.new_cookie != htonll(0) && fm.new_cookie != OVS_BE64_MAX) {
851 ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.new_cookie));
852 }
853 if (fm.cookie_mask != htonll(0)) {
854 ds_put_format(s, "cookie:0x%"PRIx64"/0x%"PRIx64" ",
855 ntohll(fm.cookie), ntohll(fm.cookie_mask));
856 }
857 if (fm.idle_timeout != OFP_FLOW_PERMANENT) {
858 ds_put_format(s, "idle:%"PRIu16" ", fm.idle_timeout);
859 }
860 if (fm.hard_timeout != OFP_FLOW_PERMANENT) {
861 ds_put_format(s, "hard:%"PRIu16" ", fm.hard_timeout);
862 }
863 if (fm.importance != 0) {
864 ds_put_format(s, "importance:%"PRIu16" ", fm.importance);
865 }
866 if (fm.priority != OFP_DEFAULT_PRIORITY && need_priority) {
867 ds_put_format(s, "pri:%"PRIu16" ", fm.priority);
868 }
869 if (fm.buffer_id != UINT32_MAX) {
870 ds_put_format(s, "buf:0x%"PRIx32" ", fm.buffer_id);
871 }
872 if (fm.out_port != OFPP_ANY) {
873 ds_put_format(s, "out_port:");
874 ofputil_format_port(fm.out_port, s);
875 ds_put_char(s, ' ');
876 }
877
878 if (oh->version == OFP10_VERSION || oh->version == OFP11_VERSION) {
879 /* Don't print the reset_counts flag for OF1.0 and OF1.1 because those
880 * versions don't really have such a flag and printing one is likely to
881 * confuse people. */
882 fm.flags &= ~OFPUTIL_FF_RESET_COUNTS;
883 }
884 ofp_print_flow_flags(s, fm.flags);
885
886 ds_put_cstr(s, "actions=");
887 ofpacts_format(fm.ofpacts, fm.ofpacts_len, s);
888 ofpbuf_uninit(&ofpacts);
889 }
890
891 static void
892 ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
893 {
894 ds_put_format(string, "%u", sec);
895
896 /* If there are no fractional seconds, don't print any decimals.
897 *
898 * If the fractional seconds can be expressed exactly as milliseconds,
899 * print 3 decimals. Open vSwitch provides millisecond precision for most
900 * time measurements, so printing 3 decimals every time makes it easier to
901 * spot real changes in flow dumps that refresh themselves quickly.
902 *
903 * If the fractional seconds are more precise than milliseconds, print the
904 * number of decimals needed to express them exactly.
905 */
906 if (nsec > 0) {
907 unsigned int msec = nsec / 1000000;
908 if (msec * 1000000 == nsec) {
909 ds_put_format(string, ".%03u", msec);
910 } else {
911 ds_put_format(string, ".%09u", nsec);
912 while (string->string[string->length - 1] == '0') {
913 string->length--;
914 }
915 }
916 }
917 ds_put_char(string, 's');
918 }
919
920 /* Returns a string form of 'reason'. The return value is either a statically
921 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
922 * 'bufsize' should be at least OFP_FLOW_REMOVED_REASON_BUFSIZE. */
923 #define OFP_FLOW_REMOVED_REASON_BUFSIZE (INT_STRLEN(int) + 1)
924 static const char *
925 ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason,
926 char *reasonbuf, size_t bufsize)
927 {
928 switch (reason) {
929 case OFPRR_IDLE_TIMEOUT:
930 return "idle";
931 case OFPRR_HARD_TIMEOUT:
932 return "hard";
933 case OFPRR_DELETE:
934 return "delete";
935 case OFPRR_GROUP_DELETE:
936 return "group_delete";
937 case OFPRR_EVICTION:
938 return "eviction";
939 case OFPRR_METER_DELETE:
940 return "meter_delete";
941 case OVS_OFPRR_NONE:
942 default:
943 snprintf(reasonbuf, bufsize, "%d", (int) reason);
944 return reasonbuf;
945 }
946 }
947
948 static void
949 ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh)
950 {
951 char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
952 struct ofputil_flow_removed fr;
953 enum ofperr error;
954
955 error = ofputil_decode_flow_removed(&fr, oh);
956 if (error) {
957 ofp_print_error(string, error);
958 return;
959 }
960
961 ds_put_char(string, ' ');
962 match_format(&fr.match, string, fr.priority);
963
964 ds_put_format(string, " reason=%s",
965 ofp_flow_removed_reason_to_string(fr.reason, reasonbuf,
966 sizeof reasonbuf));
967
968 if (fr.table_id != 255) {
969 ds_put_format(string, " table_id=%"PRIu8, fr.table_id);
970 }
971
972 if (fr.cookie != htonll(0)) {
973 ds_put_format(string, " cookie:0x%"PRIx64, ntohll(fr.cookie));
974 }
975 ds_put_cstr(string, " duration");
976 ofp_print_duration(string, fr.duration_sec, fr.duration_nsec);
977 ds_put_format(string, " idle%"PRIu16, fr.idle_timeout);
978 if (fr.hard_timeout) {
979 /* The hard timeout was only added in OF1.2, so only print it if it is
980 * actually in use to avoid gratuitous change to the formatting. */
981 ds_put_format(string, " hard%"PRIu16, fr.hard_timeout);
982 }
983 ds_put_format(string, " pkts%"PRIu64" bytes%"PRIu64"\n",
984 fr.packet_count, fr.byte_count);
985 }
986
987 static void
988 ofp_print_port_mod(struct ds *string, const struct ofp_header *oh)
989 {
990 struct ofputil_port_mod pm;
991 enum ofperr error;
992
993 error = ofputil_decode_port_mod(oh, &pm, true);
994 if (error) {
995 ofp_print_error(string, error);
996 return;
997 }
998
999 ds_put_cstr(string, " port: ");
1000 ofputil_format_port(pm.port_no, string);
1001 ds_put_format(string, ": addr:"ETH_ADDR_FMT"\n",
1002 ETH_ADDR_ARGS(pm.hw_addr));
1003
1004 ds_put_cstr(string, " config: ");
1005 ofp_print_port_config(string, pm.config);
1006
1007 ds_put_cstr(string, " mask: ");
1008 ofp_print_port_config(string, pm.mask);
1009
1010 ds_put_cstr(string, " advertise: ");
1011 if (pm.advertise) {
1012 ofp_print_port_features(string, pm.advertise);
1013 } else {
1014 ds_put_cstr(string, "UNCHANGED\n");
1015 }
1016 }
1017
1018 static const char *
1019 ofputil_table_miss_to_string(enum ofputil_table_miss miss)
1020 {
1021 switch (miss) {
1022 case OFPUTIL_TABLE_MISS_DEFAULT: return "default";
1023 case OFPUTIL_TABLE_MISS_CONTROLLER: return "controller";
1024 case OFPUTIL_TABLE_MISS_CONTINUE: return "continue";
1025 case OFPUTIL_TABLE_MISS_DROP: return "drop";
1026 default: return "***error***";
1027 }
1028 }
1029
1030 static const char *
1031 ofputil_table_eviction_to_string(enum ofputil_table_eviction eviction)
1032 {
1033 switch (eviction) {
1034 case OFPUTIL_TABLE_EVICTION_DEFAULT: return "default";
1035 case OFPUTIL_TABLE_EVICTION_ON: return "on";
1036 case OFPUTIL_TABLE_EVICTION_OFF: return "off";
1037 default: return "***error***";
1038 }
1039
1040 }
1041
1042 static const char *
1043 ofputil_eviction_flag_to_string(uint32_t bit)
1044 {
1045 enum ofp14_table_mod_prop_eviction_flag eviction_flag = bit;
1046
1047 switch (eviction_flag) {
1048 case OFPTMPEF14_OTHER: return "OTHER";
1049 case OFPTMPEF14_IMPORTANCE: return "IMPORTANCE";
1050 case OFPTMPEF14_LIFETIME: return "LIFETIME";
1051 }
1052
1053 return NULL;
1054 }
1055
1056 /* Appends to 'string' a description of the bitmap of OFPTMPEF14_* values in
1057 * 'eviction_flags'. */
1058 static void
1059 ofputil_put_eviction_flags(struct ds *string, uint32_t eviction_flags)
1060 {
1061 if (eviction_flags != UINT32_MAX) {
1062 ofp_print_bit_names(string, eviction_flags,
1063 ofputil_eviction_flag_to_string, '|');
1064 } else {
1065 ds_put_cstr(string, "(default)");
1066 }
1067 }
1068
1069 static const char *
1070 ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy)
1071 {
1072 switch (vacancy) {
1073 case OFPUTIL_TABLE_VACANCY_DEFAULT: return "default";
1074 case OFPUTIL_TABLE_VACANCY_ON: return "on";
1075 case OFPUTIL_TABLE_VACANCY_OFF: return "off";
1076 default: return "***error***";
1077 }
1078
1079 }
1080
1081 static void
1082 ofp_print_table_mod(struct ds *string, const struct ofp_header *oh)
1083 {
1084 struct ofputil_table_mod pm;
1085 enum ofperr error;
1086
1087 error = ofputil_decode_table_mod(oh, &pm);
1088 if (error) {
1089 ofp_print_error(string, error);
1090 return;
1091 }
1092
1093 if (pm.table_id == 0xff) {
1094 ds_put_cstr(string, " table_id: ALL_TABLES");
1095 } else {
1096 ds_put_format(string, " table_id=%"PRIu8, pm.table_id);
1097 }
1098
1099 if (pm.miss != OFPUTIL_TABLE_MISS_DEFAULT) {
1100 ds_put_format(string, ", flow_miss_config=%s",
1101 ofputil_table_miss_to_string(pm.miss));
1102 }
1103 if (pm.eviction != OFPUTIL_TABLE_EVICTION_DEFAULT) {
1104 ds_put_format(string, ", eviction=%s",
1105 ofputil_table_eviction_to_string(pm.eviction));
1106 }
1107 if (pm.eviction_flags != UINT32_MAX) {
1108 ds_put_cstr(string, "eviction_flags=");
1109 ofputil_put_eviction_flags(string, pm.eviction_flags);
1110 }
1111 if (pm.vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
1112 ds_put_format(string, ", vacancy=%s",
1113 ofputil_table_vacancy_to_string(pm.vacancy));
1114 if (pm.vacancy == OFPUTIL_TABLE_VACANCY_ON) {
1115 ds_put_format(string, " vacancy:%"PRIu8""
1116 ",%"PRIu8"", pm.table_vacancy.vacancy_down,
1117 pm.table_vacancy.vacancy_up);
1118 }
1119 }
1120 }
1121
1122 /* This function will print the Table description properties. */
1123 static void
1124 ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td)
1125 {
1126 ds_put_format(string, "\n table %"PRIu8, td->table_id);
1127 ds_put_cstr(string, ":\n");
1128 ds_put_format(string, " eviction=%s eviction_flags=",
1129 ofputil_table_eviction_to_string(td->eviction));
1130 ofputil_put_eviction_flags(string, td->eviction_flags);
1131 ds_put_char(string, '\n');
1132 ds_put_format(string, " vacancy=%s",
1133 ofputil_table_vacancy_to_string(td->vacancy));
1134 if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
1135 ds_put_format(string, " vacancy_down=%"PRIu8"%%",
1136 td->table_vacancy.vacancy_down);
1137 ds_put_format(string, " vacancy_up=%"PRIu8"%%",
1138 td->table_vacancy.vacancy_up);
1139 ds_put_format(string, " vacancy=%"PRIu8"%%",
1140 td->table_vacancy.vacancy);
1141 }
1142 ds_put_char(string, '\n');
1143 }
1144
1145 static void
1146 ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh)
1147 {
1148 struct ofputil_table_status ts;
1149 enum ofperr error;
1150
1151 error = ofputil_decode_table_status(oh, &ts);
1152 if (error) {
1153 ofp_print_error(string, error);
1154 return;
1155 }
1156
1157 if (ts.reason == OFPTR_VACANCY_DOWN) {
1158 ds_put_format(string, " reason=VACANCY_DOWN");
1159 } else if (ts.reason == OFPTR_VACANCY_UP) {
1160 ds_put_format(string, " reason=VACANCY_UP");
1161 }
1162
1163 ds_put_format(string, "\ntable_desc:-");
1164 ofp_print_table_desc(string, &ts.desc);
1165 }
1166
1167 static void
1168 ofp_print_queue_get_config_request(struct ds *string,
1169 const struct ofp_header *oh)
1170 {
1171 enum ofperr error;
1172 ofp_port_t port;
1173 uint32_t queue;
1174
1175 error = ofputil_decode_queue_get_config_request(oh, &port, &queue);
1176 if (error) {
1177 ofp_print_error(string, error);
1178 return;
1179 }
1180
1181 ds_put_cstr(string, " port=");
1182 ofputil_format_port(port, string);
1183
1184 if (queue != OFPQ_ALL) {
1185 ds_put_cstr(string, " queue=");
1186 ofp_print_queue_name(string, queue);
1187 }
1188 }
1189
1190 static void
1191 print_queue_rate(struct ds *string, const char *name, unsigned int rate)
1192 {
1193 if (rate <= 1000) {
1194 ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10);
1195 } else if (rate < UINT16_MAX) {
1196 ds_put_format(string, " %s:(disabled)", name);
1197 }
1198 }
1199
1200 /* qsort comparison function. */
1201 static int
1202 compare_queues(const void *a_, const void *b_)
1203 {
1204 const struct ofputil_queue_config *a = a_;
1205 const struct ofputil_queue_config *b = b_;
1206
1207 uint16_t ap = ofp_to_u16(a->port);
1208 uint16_t bp = ofp_to_u16(b->port);
1209 if (ap != bp) {
1210 return ap < bp ? -1 : 1;
1211 }
1212
1213 uint32_t aq = a->queue;
1214 uint32_t bq = b->queue;
1215 return aq < bq ? -1 : aq > bq;
1216 }
1217
1218 static void
1219 ofp_print_queue_get_config_reply(struct ds *string,
1220 const struct ofp_header *oh)
1221 {
1222 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1223
1224 struct ofputil_queue_config *queues = NULL;
1225 size_t allocated_queues = 0;
1226 size_t n = 0;
1227
1228 int retval = 0;
1229 for (;;) {
1230 if (n >= allocated_queues) {
1231 queues = x2nrealloc(queues, &allocated_queues, sizeof *queues);
1232 }
1233 retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]);
1234 if (retval) {
1235 break;
1236 }
1237 n++;
1238 }
1239
1240 qsort(queues, n, sizeof *queues, compare_queues);
1241
1242 ds_put_char(string, ' ');
1243
1244 ofp_port_t port = 0;
1245 for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) {
1246 if (q->port != port) {
1247 port = q->port;
1248
1249 ds_put_cstr(string, "port=");
1250 ofputil_format_port(port, string);
1251 ds_put_char(string, '\n');
1252 }
1253
1254 ds_put_format(string, "queue %"PRIu32":", q->queue);
1255 print_queue_rate(string, "min_rate", q->min_rate);
1256 print_queue_rate(string, "max_rate", q->max_rate);
1257 ds_put_char(string, '\n');
1258 }
1259
1260 if (retval != EOF) {
1261 ofp_print_error(string, retval);
1262 }
1263 ds_chomp(string, ' ');
1264 }
1265
1266 static void
1267 ofp_print_meter_flags(struct ds *s, uint16_t flags)
1268 {
1269 if (flags & OFPMF13_KBPS) {
1270 ds_put_cstr(s, "kbps ");
1271 }
1272 if (flags & OFPMF13_PKTPS) {
1273 ds_put_cstr(s, "pktps ");
1274 }
1275 if (flags & OFPMF13_BURST) {
1276 ds_put_cstr(s, "burst ");
1277 }
1278 if (flags & OFPMF13_STATS) {
1279 ds_put_cstr(s, "stats ");
1280 }
1281
1282 flags &= ~(OFPMF13_KBPS | OFPMF13_PKTPS | OFPMF13_BURST | OFPMF13_STATS);
1283 if (flags) {
1284 ds_put_format(s, "flags:0x%"PRIx16" ", flags);
1285 }
1286 }
1287
1288 static void
1289 ofp_print_meter_band(struct ds *s, uint16_t flags,
1290 const struct ofputil_meter_band *mb)
1291 {
1292 ds_put_cstr(s, "\ntype=");
1293 switch (mb->type) {
1294 case OFPMBT13_DROP:
1295 ds_put_cstr(s, "drop");
1296 break;
1297 case OFPMBT13_DSCP_REMARK:
1298 ds_put_cstr(s, "dscp_remark");
1299 break;
1300 default:
1301 ds_put_format(s, "%u", mb->type);
1302 }
1303
1304 ds_put_format(s, " rate=%"PRIu32, mb->rate);
1305
1306 if (flags & OFPMF13_BURST) {
1307 ds_put_format(s, " burst_size=%"PRIu32, mb->burst_size);
1308 }
1309 if (mb->type == OFPMBT13_DSCP_REMARK) {
1310 ds_put_format(s, " prec_level=%"PRIu8, mb->prec_level);
1311 }
1312 }
1313
1314 static void
1315 ofp_print_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms)
1316 {
1317 uint16_t i;
1318
1319 ds_put_format(s, "meter:%"PRIu32" ", ms->meter_id);
1320 ds_put_format(s, "flow_count:%"PRIu32" ", ms->flow_count);
1321 ds_put_format(s, "packet_in_count:%"PRIu64" ", ms->packet_in_count);
1322 ds_put_format(s, "byte_in_count:%"PRIu64" ", ms->byte_in_count);
1323 ds_put_cstr(s, "duration:");
1324 ofp_print_duration(s, ms->duration_sec, ms->duration_nsec);
1325 ds_put_char(s, ' ');
1326
1327 ds_put_cstr(s, "bands:\n");
1328 for (i = 0; i < ms->n_bands; ++i) {
1329 ds_put_format(s, "%d: ", i);
1330 ds_put_format(s, "packet_count:%"PRIu64" ", ms->bands[i].packet_count);
1331 ds_put_format(s, "byte_count:%"PRIu64"\n", ms->bands[i].byte_count);
1332 }
1333 }
1334
1335 static void
1336 ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc)
1337 {
1338 uint16_t i;
1339
1340 ds_put_format(s, "meter=%"PRIu32" ", mc->meter_id);
1341
1342 ofp_print_meter_flags(s, mc->flags);
1343
1344 ds_put_cstr(s, "bands=");
1345 for (i = 0; i < mc->n_bands; ++i) {
1346 ofp_print_meter_band(s, mc->flags, &mc->bands[i]);
1347 }
1348 ds_put_char(s, '\n');
1349 }
1350
1351 static void
1352 ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm)
1353 {
1354 switch (mm->command) {
1355 case OFPMC13_ADD:
1356 ds_put_cstr(s, " ADD ");
1357 break;
1358 case OFPMC13_MODIFY:
1359 ds_put_cstr(s, " MOD ");
1360 break;
1361 case OFPMC13_DELETE:
1362 ds_put_cstr(s, " DEL ");
1363 break;
1364 default:
1365 ds_put_format(s, " cmd:%d ", mm->command);
1366 }
1367
1368 ofp_print_meter_config(s, &mm->meter);
1369 }
1370
1371 static void
1372 ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh)
1373 {
1374 struct ofputil_meter_mod mm;
1375 struct ofpbuf bands;
1376 enum ofperr error;
1377
1378 ofpbuf_init(&bands, 64);
1379 error = ofputil_decode_meter_mod(oh, &mm, &bands);
1380 if (error) {
1381 ofp_print_error(s, error);
1382 } else {
1383 ofp_print_meter_mod__(s, &mm);
1384 }
1385 ofpbuf_uninit(&bands);
1386 }
1387
1388 static void
1389 ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh)
1390 {
1391 uint32_t meter_id;
1392
1393 ofputil_decode_meter_request(oh, &meter_id);
1394
1395 ds_put_format(s, " meter=%"PRIu32, meter_id);
1396 }
1397
1398 static const char *
1399 ofputil_meter_capabilities_to_name(uint32_t bit)
1400 {
1401 enum ofp13_meter_flags flag = bit;
1402
1403 switch (flag) {
1404 case OFPMF13_KBPS: return "kbps";
1405 case OFPMF13_PKTPS: return "pktps";
1406 case OFPMF13_BURST: return "burst";
1407 case OFPMF13_STATS: return "stats";
1408 }
1409
1410 return NULL;
1411 }
1412
1413 static const char *
1414 ofputil_meter_band_types_to_name(uint32_t bit)
1415 {
1416 switch (bit) {
1417 case 1 << OFPMBT13_DROP: return "drop";
1418 case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark";
1419 }
1420
1421 return NULL;
1422 }
1423
1424 static void
1425 ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
1426 {
1427 struct ofputil_meter_features mf;
1428
1429 ofputil_decode_meter_features(oh, &mf);
1430
1431 ds_put_format(s, "\nmax_meter:%"PRIu32, mf.max_meters);
1432 ds_put_format(s, " max_bands:%"PRIu8, mf.max_bands);
1433 ds_put_format(s, " max_color:%"PRIu8"\n", mf.max_color);
1434
1435 ds_put_cstr(s, "band_types: ");
1436 ofp_print_bit_names(s, mf.band_types,
1437 ofputil_meter_band_types_to_name, ' ');
1438 ds_put_char(s, '\n');
1439
1440 ds_put_cstr(s, "capabilities: ");
1441 ofp_print_bit_names(s, mf.capabilities,
1442 ofputil_meter_capabilities_to_name, ' ');
1443 ds_put_char(s, '\n');
1444 }
1445
1446 static void
1447 ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
1448 {
1449 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1450 struct ofpbuf bands;
1451
1452 ofpbuf_init(&bands, 64);
1453 for (;;) {
1454 struct ofputil_meter_config mc;
1455 int retval;
1456
1457 retval = ofputil_decode_meter_config(&b, &mc, &bands);
1458 if (retval) {
1459 if (retval != EOF) {
1460 ofp_print_error(s, retval);
1461 }
1462 break;
1463 }
1464 ds_put_char(s, '\n');
1465 ofp_print_meter_config(s, &mc);
1466 }
1467 ofpbuf_uninit(&bands);
1468 }
1469
1470 static void
1471 ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
1472 {
1473 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1474 struct ofpbuf bands;
1475
1476 ofpbuf_init(&bands, 64);
1477 for (;;) {
1478 struct ofputil_meter_stats ms;
1479 int retval;
1480
1481 retval = ofputil_decode_meter_stats(&b, &ms, &bands);
1482 if (retval) {
1483 if (retval != EOF) {
1484 ofp_print_error(s, retval);
1485 }
1486 break;
1487 }
1488 ds_put_char(s, '\n');
1489 ofp_print_meter_stats(s, &ms);
1490 }
1491 ofpbuf_uninit(&bands);
1492 }
1493
1494 static void
1495 ofp_print_error(struct ds *string, enum ofperr error)
1496 {
1497 if (string->length) {
1498 ds_put_char(string, ' ');
1499 }
1500 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
1501 }
1502
1503 static void
1504 ofp_print_hello(struct ds *string, const struct ofp_header *oh)
1505 {
1506 uint32_t allowed_versions;
1507 bool ok;
1508
1509 ok = ofputil_decode_hello(oh, &allowed_versions);
1510
1511 ds_put_cstr(string, "\n version bitmap: ");
1512 ofputil_format_version_bitmap(string, allowed_versions);
1513
1514 if (!ok) {
1515 ds_put_cstr(string, "\n unknown data in hello:\n");
1516 ds_put_hex_dump(string, oh, ntohs(oh->length), 0, true);
1517 }
1518 }
1519
1520 static void
1521 ofp_print_error_msg(struct ds *string, const struct ofp_header *oh)
1522 {
1523 size_t len = ntohs(oh->length);
1524 struct ofpbuf payload;
1525 enum ofperr error;
1526 char *s;
1527
1528 error = ofperr_decode_msg(oh, &payload);
1529 if (!error) {
1530 ds_put_cstr(string, "***decode error***");
1531 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
1532 return;
1533 }
1534
1535 ds_put_format(string, " %s\n", ofperr_get_name(error));
1536
1537 if (error == OFPERR_OFPHFC_INCOMPATIBLE || error == OFPERR_OFPHFC_EPERM) {
1538 ds_put_printable(string, payload.data, payload.size);
1539 } else {
1540 s = ofp_to_string(payload.data, payload.size, 1);
1541 ds_put_cstr(string, s);
1542 free(s);
1543 }
1544 ofpbuf_uninit(&payload);
1545 }
1546
1547 static void
1548 ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
1549 {
1550 struct ofputil_port_status ps;
1551 enum ofperr error;
1552
1553 error = ofputil_decode_port_status(oh, &ps);
1554 if (error) {
1555 ofp_print_error(string, error);
1556 return;
1557 }
1558
1559 if (ps.reason == OFPPR_ADD) {
1560 ds_put_format(string, " ADD:");
1561 } else if (ps.reason == OFPPR_DELETE) {
1562 ds_put_format(string, " DEL:");
1563 } else if (ps.reason == OFPPR_MODIFY) {
1564 ds_put_format(string, " MOD:");
1565 }
1566
1567 ofp_print_phy_port(string, &ps.desc);
1568 }
1569
1570 static void
1571 ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
1572 {
1573 const struct ofp_desc_stats *ods = ofpmsg_body(oh);
1574
1575 ds_put_char(string, '\n');
1576 ds_put_format(string, "Manufacturer: %.*s\n",
1577 (int) sizeof ods->mfr_desc, ods->mfr_desc);
1578 ds_put_format(string, "Hardware: %.*s\n",
1579 (int) sizeof ods->hw_desc, ods->hw_desc);
1580 ds_put_format(string, "Software: %.*s\n",
1581 (int) sizeof ods->sw_desc, ods->sw_desc);
1582 ds_put_format(string, "Serial Num: %.*s\n",
1583 (int) sizeof ods->serial_num, ods->serial_num);
1584 ds_put_format(string, "DP Description: %.*s\n",
1585 (int) sizeof ods->dp_desc, ods->dp_desc);
1586 }
1587
1588 static void
1589 ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh)
1590 {
1591 struct ofputil_flow_stats_request fsr;
1592 enum ofperr error;
1593
1594 error = ofputil_decode_flow_stats_request(&fsr, oh, NULL);
1595 if (error) {
1596 ofp_print_error(string, error);
1597 return;
1598 }
1599
1600 if (fsr.table_id != 0xff) {
1601 ds_put_format(string, " table=%"PRIu8, fsr.table_id);
1602 }
1603
1604 if (fsr.out_port != OFPP_ANY) {
1605 ds_put_cstr(string, " out_port=");
1606 ofputil_format_port(fsr.out_port, string);
1607 }
1608
1609 ds_put_char(string, ' ');
1610 match_format(&fsr.match, string, OFP_DEFAULT_PRIORITY);
1611 }
1612
1613 void
1614 ofp_print_flow_stats(struct ds *string, struct ofputil_flow_stats *fs)
1615 {
1616 ds_put_format(string, " %scookie=%s0x%"PRIx64", %sduration=%s",
1617 colors.param, colors.end, ntohll(fs->cookie),
1618 colors.param, colors.end);
1619
1620 ofp_print_duration(string, fs->duration_sec, fs->duration_nsec);
1621 ds_put_format(string, ", %stable=%s%"PRIu8", ",
1622 colors.special, colors.end, fs->table_id);
1623 ds_put_format(string, "%sn_packets=%s%"PRIu64", ",
1624 colors.param, colors.end, fs->packet_count);
1625 ds_put_format(string, "%sn_bytes=%s%"PRIu64", ",
1626 colors.param, colors.end, fs->byte_count);
1627 if (fs->idle_timeout != OFP_FLOW_PERMANENT) {
1628 ds_put_format(string, "%sidle_timeout=%s%"PRIu16", ",
1629 colors.param, colors.end, fs->idle_timeout);
1630 }
1631 if (fs->hard_timeout != OFP_FLOW_PERMANENT) {
1632 ds_put_format(string, "%shard_timeout=%s%"PRIu16", ",
1633 colors.param, colors.end, fs->hard_timeout);
1634 }
1635 if (fs->flags) {
1636 ofp_print_flow_flags(string, fs->flags);
1637 }
1638 if (fs->importance != 0) {
1639 ds_put_format(string, "%simportance=%s%"PRIu16", ",
1640 colors.param, colors.end, fs->importance);
1641 }
1642 if (fs->idle_age >= 0) {
1643 ds_put_format(string, "%sidle_age=%s%d, ",
1644 colors.param, colors.end, fs->idle_age);
1645 }
1646 if (fs->hard_age >= 0 && fs->hard_age != fs->duration_sec) {
1647 ds_put_format(string, "%shard_age=%s%d, ",
1648 colors.param, colors.end, fs->hard_age);
1649 }
1650
1651 match_format(&fs->match, string, fs->priority);
1652 if (string->string[string->length - 1] != ' ') {
1653 ds_put_char(string, ' ');
1654 }
1655
1656 ds_put_format(string, "%sactions=%s", colors.actions, colors.end);
1657 ofpacts_format(fs->ofpacts, fs->ofpacts_len, string);
1658 }
1659
1660 static void
1661 ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh)
1662 {
1663 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1664 struct ofpbuf ofpacts;
1665
1666 ofpbuf_init(&ofpacts, 64);
1667 for (;;) {
1668 struct ofputil_flow_stats fs;
1669 int retval;
1670
1671 retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
1672 if (retval) {
1673 if (retval != EOF) {
1674 ds_put_cstr(string, " ***parse error***");
1675 }
1676 break;
1677 }
1678 ds_put_char(string, '\n');
1679 ofp_print_flow_stats(string, &fs);
1680 }
1681 ofpbuf_uninit(&ofpacts);
1682 }
1683
1684 static void
1685 ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
1686 {
1687 struct ofputil_aggregate_stats as;
1688 enum ofperr error;
1689
1690 error = ofputil_decode_aggregate_stats_reply(&as, oh);
1691 if (error) {
1692 ofp_print_error(string, error);
1693 return;
1694 }
1695
1696 ds_put_format(string, " packet_count=%"PRIu64, as.packet_count);
1697 ds_put_format(string, " byte_count=%"PRIu64, as.byte_count);
1698 ds_put_format(string, " flow_count=%"PRIu32, as.flow_count);
1699 }
1700
1701 static void
1702 print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
1703 {
1704 ds_put_cstr(string, leader);
1705 if (stat != UINT64_MAX) {
1706 ds_put_format(string, "%"PRIu64, stat);
1707 } else {
1708 ds_put_char(string, '?');
1709 }
1710 if (more) {
1711 ds_put_cstr(string, ", ");
1712 } else {
1713 ds_put_cstr(string, "\n");
1714 }
1715 }
1716
1717 static void
1718 print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat)
1719 {
1720 if (stat != UINT64_MAX) {
1721 ds_put_format(string, "%s%"PRIu64", ", leader, stat);
1722 }
1723 }
1724
1725 static void
1726 ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
1727 {
1728 ofp_port_t ofp10_port;
1729 enum ofperr error;
1730
1731 error = ofputil_decode_port_stats_request(oh, &ofp10_port);
1732 if (error) {
1733 ofp_print_error(string, error);
1734 return;
1735 }
1736
1737 ds_put_cstr(string, " port_no=");
1738 ofputil_format_port(ofp10_port, string);
1739 }
1740
1741 static void
1742 ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
1743 int verbosity)
1744 {
1745 ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh));
1746 if (verbosity < 1) {
1747 return;
1748 }
1749
1750 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1751 for (;;) {
1752 struct ofputil_port_stats ps;
1753 int retval;
1754
1755 retval = ofputil_decode_port_stats(&ps, &b);
1756 if (retval) {
1757 if (retval != EOF) {
1758 ds_put_cstr(string, " ***parse error***");
1759 }
1760 return;
1761 }
1762
1763 ds_put_cstr(string, " port ");
1764 if (ofp_to_u16(ps.port_no) < 10) {
1765 ds_put_char(string, ' ');
1766 }
1767 ofputil_format_port(ps.port_no, string);
1768
1769 ds_put_cstr(string, ": rx ");
1770 print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
1771 print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
1772 print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
1773 print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
1774 print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
1775 print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
1776 print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
1777
1778 ds_put_cstr(string, " tx ");
1779 print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
1780 print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
1781 print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
1782 print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
1783 print_port_stat(string, "coll=", ps.stats.collisions, 0);
1784
1785 if (ps.duration_sec != UINT32_MAX) {
1786 ds_put_cstr(string, " duration=");
1787 ofp_print_duration(string, ps.duration_sec, ps.duration_nsec);
1788 ds_put_char(string, '\n');
1789 }
1790 struct ds string_ext_stats = DS_EMPTY_INITIALIZER;
1791
1792 ds_init(&string_ext_stats);
1793
1794 print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
1795 ps.stats.rx_1_to_64_packets);
1796 print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
1797 ps.stats.rx_65_to_127_packets);
1798 print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
1799 ps.stats.rx_128_to_255_packets);
1800 print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
1801 ps.stats.rx_256_to_511_packets);
1802 print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
1803 ps.stats.rx_512_to_1023_packets);
1804 print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
1805 ps.stats.rx_1024_to_1522_packets);
1806 print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
1807 ps.stats.rx_1523_to_max_packets);
1808 print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
1809 ps.stats.rx_broadcast_packets);
1810 print_port_stat_cond(&string_ext_stats, "undersized_errors=",
1811 ps.stats.rx_undersized_errors);
1812 print_port_stat_cond(&string_ext_stats, "oversize_errors=",
1813 ps.stats.rx_oversize_errors);
1814 print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=",
1815 ps.stats.rx_fragmented_errors);
1816 print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=",
1817 ps.stats.rx_jabber_errors);
1818
1819 if (string_ext_stats.length != 0) {
1820 /* If at least one statistics counter is reported: */
1821 ds_put_cstr(string, " rx rfc2819 ");
1822 ds_put_buffer(string, string_ext_stats.string,
1823 string_ext_stats.length);
1824 ds_put_cstr(string, "\n");
1825 ds_destroy(&string_ext_stats);
1826 }
1827
1828 ds_init(&string_ext_stats);
1829
1830 print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
1831 ps.stats.tx_1_to_64_packets);
1832 print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
1833 ps.stats.tx_65_to_127_packets);
1834 print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
1835 ps.stats.tx_128_to_255_packets);
1836 print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
1837 ps.stats.tx_256_to_511_packets);
1838 print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
1839 ps.stats.tx_512_to_1023_packets);
1840 print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
1841 ps.stats.tx_1024_to_1522_packets);
1842 print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
1843 ps.stats.tx_1523_to_max_packets);
1844 print_port_stat_cond(&string_ext_stats, "multicast_packets=",
1845 ps.stats.tx_multicast_packets);
1846 print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
1847 ps.stats.tx_broadcast_packets);
1848
1849 if (string_ext_stats.length != 0) {
1850 /* If at least one statistics counter is reported: */
1851 ds_put_cstr(string, " tx rfc2819 ");
1852 ds_put_buffer(string, string_ext_stats.string,
1853 string_ext_stats.length);
1854 ds_put_cstr(string, "\n");
1855 ds_destroy(&string_ext_stats);
1856 }
1857 }
1858 }
1859
1860 static void
1861 ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh)
1862 {
1863 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1864 ofpraw_pull_assert(&b);
1865
1866 struct ofputil_table_features prev_features;
1867 struct ofputil_table_stats prev_stats;
1868 for (int i = 0;; i++) {
1869 struct ofputil_table_features features;
1870 struct ofputil_table_stats stats;
1871 int retval;
1872
1873 retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
1874 if (retval) {
1875 if (retval != EOF) {
1876 ofp_print_error(string, retval);
1877 }
1878 return;
1879 }
1880
1881 ds_put_char(string, '\n');
1882 ofp_print_table_features(string,
1883 &features, i ? &prev_features : NULL,
1884 &stats, i ? &prev_stats : NULL);
1885 prev_features = features;
1886 prev_stats = stats;
1887 }
1888 }
1889
1890 static void
1891 ofp_print_queue_name(struct ds *string, uint32_t queue_id)
1892 {
1893 if (queue_id == OFPQ_ALL) {
1894 ds_put_cstr(string, "ALL");
1895 } else {
1896 ds_put_format(string, "%"PRIu32, queue_id);
1897 }
1898 }
1899
1900 static void
1901 ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh)
1902 {
1903 struct ofputil_queue_stats_request oqsr;
1904 enum ofperr error;
1905
1906 error = ofputil_decode_queue_stats_request(oh, &oqsr);
1907 if (error) {
1908 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
1909 return;
1910 }
1911
1912 ds_put_cstr(string, " port=");
1913 ofputil_format_port(oqsr.port_no, string);
1914
1915 ds_put_cstr(string, " queue=");
1916 ofp_print_queue_name(string, oqsr.queue_id);
1917 }
1918
1919 static void
1920 ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
1921 int verbosity)
1922 {
1923 ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh));
1924 if (verbosity < 1) {
1925 return;
1926 }
1927
1928 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1929 for (;;) {
1930 struct ofputil_queue_stats qs;
1931 int retval;
1932
1933 retval = ofputil_decode_queue_stats(&qs, &b);
1934 if (retval) {
1935 if (retval != EOF) {
1936 ds_put_cstr(string, " ***parse error***");
1937 }
1938 return;
1939 }
1940
1941 ds_put_cstr(string, " port ");
1942 ofputil_format_port(qs.port_no, string);
1943 ds_put_cstr(string, " queue ");
1944 ofp_print_queue_name(string, qs.queue_id);
1945 ds_put_cstr(string, ": ");
1946
1947 print_port_stat(string, "bytes=", qs.tx_bytes, 1);
1948 print_port_stat(string, "pkts=", qs.tx_packets, 1);
1949 print_port_stat(string, "errors=", qs.tx_errors, 1);
1950
1951 ds_put_cstr(string, "duration=");
1952 if (qs.duration_sec != UINT32_MAX) {
1953 ofp_print_duration(string, qs.duration_sec, qs.duration_nsec);
1954 } else {
1955 ds_put_char(string, '?');
1956 }
1957 ds_put_char(string, '\n');
1958 }
1959 }
1960
1961 static void
1962 ofp_print_ofpst_port_desc_request(struct ds *string,
1963 const struct ofp_header *oh)
1964 {
1965 enum ofperr error;
1966 ofp_port_t port;
1967
1968 error = ofputil_decode_port_desc_stats_request(oh, &port);
1969 if (error) {
1970 ofp_print_error(string, error);
1971 return;
1972 }
1973
1974 ds_put_cstr(string, " port=");
1975 ofputil_format_port(port, string);
1976 }
1977
1978 static void
1979 ofp_print_ofpst_port_desc_reply(struct ds *string,
1980 const struct ofp_header *oh)
1981 {
1982 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1983 ofpraw_pull_assert(&b);
1984 ds_put_char(string, '\n');
1985 ofp_print_phy_ports(string, oh->version, &b);
1986 }
1987
1988 static void
1989 ofp_print_stats(struct ds *string, const struct ofp_header *oh)
1990 {
1991 uint16_t flags = ofpmp_flags(oh);
1992
1993 if (flags) {
1994 ds_put_cstr(string, " flags=");
1995 if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
1996 && (flags & OFPSF_REPLY_MORE)) {
1997 ds_put_cstr(string, "[more]");
1998 flags &= ~OFPSF_REPLY_MORE;
1999 }
2000 if (flags) {
2001 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
2002 flags);
2003 }
2004 }
2005 }
2006
2007 static void
2008 ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
2009 {
2010 size_t len = ntohs(oh->length);
2011
2012 ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
2013 if (verbosity > 1) {
2014 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
2015 }
2016 }
2017
2018 static void
2019 ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role,
2020 uint64_t generation_id)
2021 {
2022 ds_put_cstr(string, " role=");
2023
2024 switch (role) {
2025 case OFPCR12_ROLE_NOCHANGE:
2026 ds_put_cstr(string, "nochange");
2027 break;
2028 case OFPCR12_ROLE_EQUAL:
2029 ds_put_cstr(string, "equal"); /* OF 1.2 wording */
2030 break;
2031 case OFPCR12_ROLE_MASTER:
2032 ds_put_cstr(string, "master");
2033 break;
2034 case OFPCR12_ROLE_SLAVE:
2035 ds_put_cstr(string, "slave");
2036 break;
2037 default:
2038 OVS_NOT_REACHED();
2039 }
2040
2041 if (generation_id != UINT64_MAX) {
2042 ds_put_format(string, " generation_id=%"PRIu64, generation_id);
2043 }
2044 }
2045
2046 static void
2047 ofp_print_role_message(struct ds *string, const struct ofp_header *oh)
2048 {
2049 struct ofputil_role_request rr;
2050 enum ofperr error;
2051
2052 error = ofputil_decode_role_message(oh, &rr);
2053 if (error) {
2054 ofp_print_error(string, error);
2055 return;
2056 }
2057
2058 ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX);
2059 }
2060
2061 static void
2062 ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh)
2063 {
2064 struct ofputil_role_status rs;
2065 enum ofperr error;
2066
2067 error = ofputil_decode_role_status(oh, &rs);
2068 if (error) {
2069 ofp_print_error(string, error);
2070 return;
2071 }
2072
2073 ofp_print_role_generic(string, rs.role, rs.generation_id);
2074
2075 ds_put_cstr(string, " reason=");
2076
2077 switch (rs.reason) {
2078 case OFPCRR_MASTER_REQUEST:
2079 ds_put_cstr(string, "master_request");
2080 break;
2081 case OFPCRR_CONFIG:
2082 ds_put_cstr(string, "configuration_changed");
2083 break;
2084 case OFPCRR_EXPERIMENTER:
2085 ds_put_cstr(string, "experimenter_data_changed");
2086 break;
2087 case OFPCRR_N_REASONS:
2088 default:
2089 OVS_NOT_REACHED();
2090 }
2091 }
2092
2093 static void
2094 ofp_print_nxt_flow_mod_table_id(struct ds *string,
2095 const struct nx_flow_mod_table_id *nfmti)
2096 {
2097 ds_put_format(string, " %s", nfmti->set ? "enable" : "disable");
2098 }
2099
2100 static void
2101 ofp_print_nxt_set_flow_format(struct ds *string,
2102 const struct nx_set_flow_format *nsff)
2103 {
2104 uint32_t format = ntohl(nsff->format);
2105
2106 ds_put_cstr(string, " format=");
2107 if (ofputil_nx_flow_format_is_valid(format)) {
2108 ds_put_cstr(string, ofputil_nx_flow_format_to_string(format));
2109 } else {
2110 ds_put_format(string, "%"PRIu32, format);
2111 }
2112 }
2113
2114 static void
2115 ofp_print_nxt_set_packet_in_format(struct ds *string,
2116 const struct nx_set_packet_in_format *nspf)
2117 {
2118 uint32_t format = ntohl(nspf->format);
2119
2120 ds_put_cstr(string, " format=");
2121 if (ofputil_packet_in_format_is_valid(format)) {
2122 ds_put_cstr(string, ofputil_packet_in_format_to_string(format));
2123 } else {
2124 ds_put_format(string, "%"PRIu32, format);
2125 }
2126 }
2127
2128 /* Returns a string form of 'reason'. The return value is either a statically
2129 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
2130 * 'bufsize' should be at least OFP_PORT_REASON_BUFSIZE. */
2131 #define OFP_PORT_REASON_BUFSIZE (INT_STRLEN(int) + 1)
2132 static const char *
2133 ofp_port_reason_to_string(enum ofp_port_reason reason,
2134 char *reasonbuf, size_t bufsize)
2135 {
2136 switch (reason) {
2137 case OFPPR_ADD:
2138 return "add";
2139
2140 case OFPPR_DELETE:
2141 return "delete";
2142
2143 case OFPPR_MODIFY:
2144 return "modify";
2145
2146 case OFPPR_N_REASONS:
2147 default:
2148 snprintf(reasonbuf, bufsize, "%d", (int) reason);
2149 return reasonbuf;
2150 }
2151 }
2152
2153 /* Returns a string form of 'reason'. The return value is either a statically
2154 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
2155 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
2156 static const char*
2157 ofp_role_reason_to_string(enum ofp14_controller_role_reason reason,
2158 char *reasonbuf, size_t bufsize)
2159 {
2160 switch (reason) {
2161 case OFPCRR_MASTER_REQUEST:
2162 return "master_request";
2163
2164 case OFPCRR_CONFIG:
2165 return "configuration_changed";
2166
2167 case OFPCRR_EXPERIMENTER:
2168 return "experimenter_data_changed";
2169
2170 case OFPCRR_N_REASONS:
2171 default:
2172 snprintf(reasonbuf, bufsize, "%d", (int) reason);
2173 return reasonbuf;
2174 }
2175 }
2176
2177 /* Returns a string form of 'reason'. The return value is either a statically
2178 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
2179 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
2180 static const char*
2181 ofp_table_reason_to_string(enum ofp14_table_reason reason,
2182 char *reasonbuf, size_t bufsize)
2183 {
2184 switch (reason) {
2185 case OFPTR_VACANCY_DOWN:
2186 return "vacancy_down";
2187
2188 case OFPTR_VACANCY_UP:
2189 return "vacancy_up";
2190
2191 default:
2192 snprintf(reasonbuf, bufsize, "%d", (int) reason);
2193 return reasonbuf;
2194 }
2195 }
2196
2197 /* Returns a string form of 'reason'. The return value is either a statically
2198 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
2199 * 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
2200 static const char*
2201 ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason,
2202 char *reasonbuf, size_t bufsize)
2203 {
2204 switch (reason) {
2205 case OFPRFR_GROUP_MOD:
2206 return "group_mod_request";
2207
2208 case OFPRFR_METER_MOD:
2209 return "meter_mod_request";
2210
2211 case OFPRFR_N_REASONS:
2212 default:
2213 snprintf(reasonbuf, bufsize, "%d", (int) reason);
2214 return reasonbuf;
2215 }
2216 }
2217
2218 static const char *
2219 ofp_async_config_reason_to_string(uint32_t reason,
2220 enum ofputil_async_msg_type type,
2221 char *reasonbuf, size_t bufsize)
2222 {
2223 switch (type) {
2224 case OAM_PACKET_IN:
2225 return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize);
2226
2227 case OAM_PORT_STATUS:
2228 return ofp_port_reason_to_string(reason, reasonbuf, bufsize);
2229
2230 case OAM_FLOW_REMOVED:
2231 return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize);
2232
2233 case OAM_ROLE_STATUS:
2234 return ofp_role_reason_to_string(reason, reasonbuf, bufsize);
2235
2236 case OAM_TABLE_STATUS:
2237 return ofp_table_reason_to_string(reason, reasonbuf, bufsize);
2238
2239 case OAM_REQUESTFORWARD:
2240 return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize);
2241
2242 case OAM_N_TYPES:
2243 default:
2244 return "Unknown asynchronous configuration message type";
2245 }
2246 }
2247
2248
2249 #define OFP_ASYNC_CONFIG_REASON_BUFSIZE (INT_STRLEN(int) + 1)
2250 static void
2251 ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
2252 enum ofptype type)
2253 {
2254 struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
2255 struct ofputil_async_cfg ac;
2256
2257 bool is_reply = type == OFPTYPE_GET_ASYNC_REPLY;
2258 enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
2259 &basis, &ac);
2260 if (error) {
2261 ofp_print_error(string, error);
2262 return;
2263 }
2264
2265 for (int i = 0; i < 2; i++) {
2266 ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
2267 for (uint32_t type = 0; type < OAM_N_TYPES; type++) {
2268 ds_put_format(string, "%16s:",
2269 ofputil_async_msg_type_to_string(type));
2270
2271 uint32_t role = i == 0 ? ac.master[type] : ac.slave[type];
2272 for (int j = 0; j < 32; j++) {
2273 if (role & (1u << j)) {
2274 char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE];
2275 const char *reason;
2276
2277 reason = ofp_async_config_reason_to_string(
2278 j, type, reasonbuf, sizeof reasonbuf);
2279 if (reason[0]) {
2280 ds_put_format(string, " %s", reason);
2281 }
2282 }
2283 }
2284 if (!role) {
2285 ds_put_cstr(string, " (off)");
2286 }
2287 ds_put_char(string, '\n');
2288 }
2289 }
2290 }
2291
2292 static void
2293 ofp_print_nxt_set_controller_id(struct ds *string,
2294 const struct nx_controller_id *nci)
2295 {
2296 ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
2297 }
2298
2299 static void
2300 ofp_print_nxt_flow_monitor_cancel(struct ds *string,
2301 const struct ofp_header *oh)
2302 {
2303 ds_put_format(string, " id=%"PRIu32,
2304 ofputil_decode_flow_monitor_cancel(oh));
2305 }
2306
2307 static const char *
2308 nx_flow_monitor_flags_to_name(uint32_t bit)
2309 {
2310 enum nx_flow_monitor_flags fmf = bit;
2311
2312 switch (fmf) {
2313 case NXFMF_INITIAL: return "initial";
2314 case NXFMF_ADD: return "add";
2315 case NXFMF_DELETE: return "delete";
2316 case NXFMF_MODIFY: return "modify";
2317 case NXFMF_ACTIONS: return "actions";
2318 case NXFMF_OWN: return "own";
2319 }
2320
2321 return NULL;
2322 }
2323
2324 static void
2325 ofp_print_nxst_flow_monitor_request(struct ds *string,
2326 const struct ofp_header *oh)
2327 {
2328 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2329 for (;;) {
2330 struct ofputil_flow_monitor_request request;
2331 int retval;
2332
2333 retval = ofputil_decode_flow_monitor_request(&request, &b);
2334 if (retval) {
2335 if (retval != EOF) {
2336 ofp_print_error(string, retval);
2337 }
2338 return;
2339 }
2340
2341 ds_put_format(string, "\n id=%"PRIu32" flags=", request.id);
2342 ofp_print_bit_names(string, request.flags,
2343 nx_flow_monitor_flags_to_name, ',');
2344
2345 if (request.out_port != OFPP_NONE) {
2346 ds_put_cstr(string, " out_port=");
2347 ofputil_format_port(request.out_port, string);
2348 }
2349
2350 if (request.table_id != 0xff) {
2351 ds_put_format(string, " table=%"PRIu8, request.table_id);
2352 }
2353
2354 ds_put_char(string, ' ');
2355 match_format(&request.match, string, OFP_DEFAULT_PRIORITY);
2356 ds_chomp(string, ' ');
2357 }
2358 }
2359
2360 static void
2361 ofp_print_nxst_flow_monitor_reply(struct ds *string,
2362 const struct ofp_header *oh)
2363 {
2364 uint64_t ofpacts_stub[1024 / 8];
2365 struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
2366 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2367
2368 for (;;) {
2369 char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
2370 struct ofputil_flow_update update;
2371 struct match match;
2372 int retval;
2373
2374 update.match = &match;
2375 retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
2376 if (retval) {
2377 if (retval != EOF) {
2378 ofp_print_error(string, retval);
2379 }
2380 ofpbuf_uninit(&ofpacts);
2381 return;
2382 }
2383
2384 ds_put_cstr(string, "\n event=");
2385 switch (update.event) {
2386 case NXFME_ADDED:
2387 ds_put_cstr(string, "ADDED");
2388 break;
2389
2390 case NXFME_DELETED:
2391 ds_put_format(string, "DELETED reason=%s",
2392 ofp_flow_removed_reason_to_string(update.reason,
2393 reasonbuf,
2394 sizeof reasonbuf));
2395 break;
2396
2397 case NXFME_MODIFIED:
2398 ds_put_cstr(string, "MODIFIED");
2399 break;
2400
2401 case NXFME_ABBREV:
2402 ds_put_format(string, "ABBREV xid=0x%"PRIx32, ntohl(update.xid));
2403 continue;
2404 }
2405
2406 ds_put_format(string, " table=%"PRIu8, update.table_id);
2407 if (update.idle_timeout != OFP_FLOW_PERMANENT) {
2408 ds_put_format(string, " idle_timeout=%"PRIu16,
2409 update.idle_timeout);
2410 }
2411 if (update.hard_timeout != OFP_FLOW_PERMANENT) {
2412 ds_put_format(string, " hard_timeout=%"PRIu16,
2413 update.hard_timeout);
2414 }
2415 ds_put_format(string, " cookie=%#"PRIx64, ntohll(update.cookie));
2416
2417 ds_put_char(string, ' ');
2418 match_format(update.match, string, OFP_DEFAULT_PRIORITY);
2419
2420 if (update.ofpacts_len) {
2421 if (string->string[string->length - 1] != ' ') {
2422 ds_put_char(string, ' ');
2423 }
2424 ds_put_cstr(string, "actions=");
2425 ofpacts_format(update.ofpacts, update.ofpacts_len, string);
2426 }
2427 }
2428 }
2429
2430 void
2431 ofp_print_version(const struct ofp_header *oh,
2432 struct ds *string)
2433 {
2434 switch (oh->version) {
2435 case OFP10_VERSION:
2436 break;
2437 case OFP11_VERSION:
2438 ds_put_cstr(string, " (OF1.1)");
2439 break;
2440 case OFP12_VERSION:
2441 ds_put_cstr(string, " (OF1.2)");
2442 break;
2443 case OFP13_VERSION:
2444 ds_put_cstr(string, " (OF1.3)");
2445 break;
2446 case OFP14_VERSION:
2447 ds_put_cstr(string, " (OF1.4)");
2448 break;
2449 case OFP15_VERSION:
2450 ds_put_cstr(string, " (OF1.5)");
2451 break;
2452 case OFP16_VERSION:
2453 ds_put_cstr(string, " (OF1.6)");
2454 break;
2455 default:
2456 ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
2457 break;
2458 }
2459 ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid));
2460 }
2461
2462 static void
2463 ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
2464 struct ds *string)
2465 {
2466 ds_put_cstr(string, ofpraw_get_name(raw));
2467 ofp_print_version(oh, string);
2468 }
2469
2470 static void
2471 ofp_print_bucket_id(struct ds *s, const char *label, uint32_t bucket_id,
2472 enum ofp_version ofp_version)
2473 {
2474 if (ofp_version < OFP15_VERSION) {
2475 return;
2476 }
2477
2478 ds_put_cstr(s, label);
2479
2480 switch (bucket_id) {
2481 case OFPG15_BUCKET_FIRST:
2482 ds_put_cstr(s, "first");
2483 break;
2484 case OFPG15_BUCKET_LAST:
2485 ds_put_cstr(s, "last");
2486 break;
2487 case OFPG15_BUCKET_ALL:
2488 ds_put_cstr(s, "all");
2489 break;
2490 default:
2491 ds_put_format(s, "%"PRIu32, bucket_id);
2492 break;
2493 }
2494
2495 ds_put_char(s, ',');
2496 }
2497
2498 static void
2499 ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type,
2500 const struct ovs_list *p_buckets,
2501 const struct ofputil_group_props *props,
2502 enum ofp_version ofp_version, bool suppress_type)
2503 {
2504 struct ofputil_bucket *bucket;
2505
2506 ds_put_format(s, "group_id=%"PRIu32, group_id);
2507
2508 if (!suppress_type) {
2509 static const char *type_str[] = { "all", "select", "indirect",
2510 "ff", "unknown" };
2511 ds_put_format(s, ",type=%s", type_str[type > 4 ? 4 : type]);
2512 }
2513
2514 if (props->selection_method[0]) {
2515 ds_put_format(s, ",selection_method=%s", props->selection_method);
2516 if (props->selection_method_param) {
2517 ds_put_format(s, ",selection_method_param=%"PRIu64,
2518 props->selection_method_param);
2519 }
2520
2521 size_t n = bitmap_count1(props->fields.used.bm, MFF_N_IDS);
2522 if (n == 1) {
2523 ds_put_cstr(s, ",fields=");
2524 oxm_format_field_array(s, &props->fields);
2525 } else if (n > 1) {
2526 ds_put_cstr(s, ",fields(");
2527 oxm_format_field_array(s, &props->fields);
2528 ds_put_char(s, ')');
2529 }
2530 }
2531
2532 if (!p_buckets) {
2533 return;
2534 }
2535
2536 ds_put_char(s, ',');
2537
2538 LIST_FOR_EACH (bucket, list_node, p_buckets) {
2539 ds_put_cstr(s, "bucket=");
2540
2541 ofp_print_bucket_id(s, "bucket_id:", bucket->bucket_id, ofp_version);
2542 if (bucket->weight != (type == OFPGT11_SELECT ? 1 : 0)) {
2543 ds_put_format(s, "weight:%"PRIu16",", bucket->weight);
2544 }
2545 if (bucket->watch_port != OFPP_NONE) {
2546 ds_put_format(s, "watch_port:%"PRIu32",", bucket->watch_port);
2547 }
2548 if (bucket->watch_group != OFPG_ANY) {
2549 ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group);
2550 }
2551
2552 ds_put_cstr(s, "actions=");
2553 ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, s);
2554 ds_put_char(s, ',');
2555 }
2556
2557 ds_chomp(s, ',');
2558 }
2559
2560 static void
2561 ofp_print_ofpst_group_desc_request(struct ds *string,
2562 const struct ofp_header *oh)
2563 {
2564 uint32_t group_id = ofputil_decode_group_desc_request(oh);
2565 ds_put_cstr(string, " group_id=");
2566 ofputil_format_group(group_id, string);
2567 }
2568
2569 static void
2570 ofp_print_group_desc(struct ds *s, const struct ofp_header *oh)
2571 {
2572 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2573 for (;;) {
2574 struct ofputil_group_desc gd;
2575 int retval;
2576
2577 retval = ofputil_decode_group_desc_reply(&gd, &b, oh->version);
2578 if (retval) {
2579 if (retval != EOF) {
2580 ds_put_cstr(s, " ***parse error***");
2581 }
2582 break;
2583 }
2584
2585 ds_put_char(s, '\n');
2586 ds_put_char(s, ' ');
2587 ofp_print_group(s, gd.group_id, gd.type, &gd.buckets, &gd.props,
2588 oh->version, false);
2589 ofputil_uninit_group_desc(&gd);
2590 }
2591 }
2592
2593 static void
2594 ofp_print_ofpst_group_request(struct ds *string, const struct ofp_header *oh)
2595 {
2596 enum ofperr error;
2597 uint32_t group_id;
2598
2599 error = ofputil_decode_group_stats_request(oh, &group_id);
2600 if (error) {
2601 ofp_print_error(string, error);
2602 return;
2603 }
2604
2605 ds_put_cstr(string, " group_id=");
2606 ofputil_format_group(group_id, string);
2607 }
2608
2609 static void
2610 ofp_print_group_stats(struct ds *s, const struct ofp_header *oh)
2611 {
2612 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2613 for (;;) {
2614 struct ofputil_group_stats gs;
2615 int retval;
2616
2617 retval = ofputil_decode_group_stats_reply(&b, &gs);
2618 if (retval) {
2619 if (retval != EOF) {
2620 ds_put_cstr(s, " ***parse error***");
2621 }
2622 break;
2623 }
2624
2625 ds_put_char(s, '\n');
2626
2627 ds_put_char(s, ' ');
2628 ds_put_format(s, "group_id=%"PRIu32",", gs.group_id);
2629
2630 if (gs.duration_sec != UINT32_MAX) {
2631 ds_put_cstr(s, "duration=");
2632 ofp_print_duration(s, gs.duration_sec, gs.duration_nsec);
2633 ds_put_char(s, ',');
2634 }
2635 ds_put_format(s, "ref_count=%"PRIu32",", gs.ref_count);
2636 ds_put_format(s, "packet_count=%"PRIu64",", gs.packet_count);
2637 ds_put_format(s, "byte_count=%"PRIu64"", gs.byte_count);
2638
2639 for (uint32_t bucket_i = 0; bucket_i < gs.n_buckets; bucket_i++) {
2640 if (gs.bucket_stats[bucket_i].packet_count != UINT64_MAX) {
2641 ds_put_format(s, ",bucket%"PRIu32":", bucket_i);
2642 ds_put_format(s, "packet_count=%"PRIu64",", gs.bucket_stats[bucket_i].packet_count);
2643 ds_put_format(s, "byte_count=%"PRIu64"", gs.bucket_stats[bucket_i].byte_count);
2644 }
2645 }
2646
2647 free(gs.bucket_stats);
2648 }
2649 }
2650
2651 static const char *
2652 group_type_to_string(enum ofp11_group_type type)
2653 {
2654 switch (type) {
2655 case OFPGT11_ALL: return "all";
2656 case OFPGT11_SELECT: return "select";
2657 case OFPGT11_INDIRECT: return "indirect";
2658 case OFPGT11_FF: return "fast failover";
2659 default: OVS_NOT_REACHED();
2660 }
2661 }
2662
2663 static void
2664 ofp_print_group_features(struct ds *string, const struct ofp_header *oh)
2665 {
2666 struct ofputil_group_features features;
2667 int i;
2668
2669 ofputil_decode_group_features_reply(oh, &features);
2670
2671 ds_put_format(string, "\n Group table:\n");
2672 ds_put_format(string, " Types: 0x%"PRIx32"\n", features.types);
2673 ds_put_format(string, " Capabilities: 0x%"PRIx32"\n",
2674 features.capabilities);
2675
2676 for (i = 0; i < OFPGT12_N_TYPES; i++) {
2677 if (features.types & (1u << i)) {
2678 ds_put_format(string, " %s group:\n", group_type_to_string(i));
2679 ds_put_format(string, " max_groups=%#"PRIx32"\n",
2680 features.max_groups[i]);
2681 ds_put_format(string, " actions: ");
2682 ofpact_bitmap_format(features.ofpacts[i], string);
2683 ds_put_char(string, '\n');
2684 }
2685 }
2686 }
2687
2688 static void
2689 ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version,
2690 const struct ofputil_group_mod *gm)
2691 {
2692 bool bucket_command = false;
2693
2694 ds_put_char(s, '\n');
2695
2696 ds_put_char(s, ' ');
2697 switch (gm->command) {
2698 case OFPGC11_ADD:
2699 ds_put_cstr(s, "ADD");
2700 break;
2701
2702 case OFPGC11_MODIFY:
2703 ds_put_cstr(s, "MOD");
2704 break;
2705
2706 case OFPGC11_ADD_OR_MOD:
2707 ds_put_cstr(s, "ADD_OR_MOD");
2708 break;
2709
2710 case OFPGC11_DELETE:
2711 ds_put_cstr(s, "DEL");
2712 break;
2713
2714 case OFPGC15_INSERT_BUCKET:
2715 ds_put_cstr(s, "INSERT_BUCKET");
2716 bucket_command = true;
2717 break;
2718
2719 case OFPGC15_REMOVE_BUCKET:
2720 ds_put_cstr(s, "REMOVE_BUCKET");
2721 bucket_command = true;
2722 break;
2723
2724 default:
2725 ds_put_format(s, "cmd:%"PRIu16"", gm->command);
2726 }
2727 ds_put_char(s, ' ');
2728
2729 if (bucket_command) {
2730 ofp_print_bucket_id(s, "command_bucket_id:",
2731 gm->command_bucket_id, ofp_version);
2732 }
2733
2734 ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props,
2735 ofp_version, bucket_command);
2736 }
2737
2738 static void
2739 ofp_print_group_mod(struct ds *s, const struct ofp_header *oh)
2740 {
2741 struct ofputil_group_mod gm;
2742 int error;
2743
2744 error = ofputil_decode_group_mod(oh, &gm);
2745 if (error) {
2746 ofp_print_error(s, error);
2747 return;
2748 }
2749 ofp_print_group_mod__(s, oh->version, &gm);
2750 ofputil_uninit_group_mod(&gm);
2751 }
2752
2753 static void
2754 print_table_action_features(struct ds *s,
2755 const struct ofputil_table_action_features *taf)
2756 {
2757 if (taf->ofpacts) {
2758 ds_put_cstr(s, " actions: ");
2759 ofpact_bitmap_format(taf->ofpacts, s);
2760 ds_put_char(s, '\n');
2761 }
2762
2763 if (!bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS)) {
2764 int i;
2765
2766 ds_put_cstr(s, " supported on Set-Field:");
2767 BITMAP_FOR_EACH_1 (i, MFF_N_IDS, taf->set_fields.bm) {
2768 ds_put_format(s, " %s", mf_from_id(i)->name);
2769 }
2770 ds_put_char(s, '\n');
2771 }
2772 }
2773
2774 static bool
2775 table_action_features_equal(const struct ofputil_table_action_features *a,
2776 const struct ofputil_table_action_features *b)
2777 {
2778 return (a->ofpacts == b->ofpacts
2779 && bitmap_equal(a->set_fields.bm, b->set_fields.bm, MFF_N_IDS));
2780 }
2781
2782 static bool
2783 table_action_features_empty(const struct ofputil_table_action_features *taf)
2784 {
2785 return !taf->ofpacts && bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS);
2786 }
2787
2788 static void
2789 print_table_instruction_features(
2790 struct ds *s,
2791 const struct ofputil_table_instruction_features *tif,
2792 const struct ofputil_table_instruction_features *prev_tif)
2793 {
2794 int start, end;
2795
2796 if (!bitmap_is_all_zeros(tif->next, 255)) {
2797 ds_put_cstr(s, " next tables: ");
2798 for (start = bitmap_scan(tif->next, 1, 0, 255); start < 255;
2799 start = bitmap_scan(tif->next, 1, end, 255)) {
2800 end = bitmap_scan(tif->next, 0, start + 1, 255);
2801 if (end == start + 1) {
2802 ds_put_format(s, "%d,", start);
2803 } else {
2804 ds_put_format(s, "%d-%d,", start, end - 1);
2805 }
2806 }
2807 ds_chomp(s, ',');
2808 if (ds_last(s) == ' ') {
2809 ds_put_cstr(s, "none");
2810 }
2811 ds_put_char(s, '\n');
2812 }
2813
2814 if (tif->instructions) {
2815 if (prev_tif && tif->instructions == prev_tif->instructions) {
2816 ds_put_cstr(s, " (same instructions)\n");
2817 } else {
2818 ds_put_cstr(s, " instructions: ");
2819 int i;
2820
2821 for (i = 0; i < 32; i++) {
2822 if (tif->instructions & (1u << i)) {
2823 ds_put_format(s, "%s,", ovs_instruction_name_from_type(i));
2824 }
2825 }
2826 ds_chomp(s, ',');
2827 ds_put_char(s, '\n');
2828 }
2829 }
2830
2831 if (prev_tif
2832 && table_action_features_equal(&tif->write, &prev_tif->write)
2833 && table_action_features_equal(&tif->apply, &prev_tif->apply)
2834 && !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
2835 ds_put_cstr(s, " (same actions)\n");
2836 } else if (!table_action_features_equal(&tif->write, &tif->apply)) {
2837 ds_put_cstr(s, " Write-Actions features:\n");
2838 print_table_action_features(s, &tif->write);
2839 ds_put_cstr(s, " Apply-Actions features:\n");
2840 print_table_action_features(s, &tif->apply);
2841 } else if (tif->write.ofpacts
2842 || !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
2843 ds_put_cstr(s, " Write-Actions and Apply-Actions features:\n");
2844 print_table_action_features(s, &tif->write);
2845 }
2846 }
2847
2848 static bool
2849 table_instruction_features_equal(
2850 const struct ofputil_table_instruction_features *a,
2851 const struct ofputil_table_instruction_features *b)
2852 {
2853 return (bitmap_equal(a->next, b->next, 255)
2854 && a->instructions == b->instructions
2855 && table_action_features_equal(&a->write, &b->write)
2856 && table_action_features_equal(&a->apply, &b->apply));
2857 }
2858
2859 static bool
2860 table_instruction_features_empty(
2861 const struct ofputil_table_instruction_features *tif)
2862 {
2863 return (bitmap_is_all_zeros(tif->next, 255)
2864 && !tif->instructions
2865 && table_action_features_empty(&tif->write)
2866 && table_action_features_empty(&tif->apply));
2867 }
2868
2869 static bool
2870 table_features_equal(const struct ofputil_table_features *a,
2871 const struct ofputil_table_features *b)
2872 {
2873 return (a->metadata_match == b->metadata_match
2874 && a->metadata_write == b->metadata_write
2875 && a->miss_config == b->miss_config
2876 && a->supports_eviction == b->supports_eviction
2877 && a->supports_vacancy_events == b->supports_vacancy_events
2878 && a->max_entries == b->max_entries
2879 && table_instruction_features_equal(&a->nonmiss, &b->nonmiss)
2880 && table_instruction_features_equal(&a->miss, &b->miss)
2881 && bitmap_equal(a->match.bm, b->match.bm, MFF_N_IDS));
2882 }
2883
2884 static bool
2885 table_features_empty(const struct ofputil_table_features *tf)
2886 {
2887 return (!tf->metadata_match
2888 && !tf->metadata_write
2889 && tf->miss_config == OFPUTIL_TABLE_MISS_DEFAULT
2890 && tf->supports_eviction < 0
2891 && tf->supports_vacancy_events < 0
2892 && !tf->max_entries
2893 && table_instruction_features_empty(&tf->nonmiss)
2894 && table_instruction_features_empty(&tf->miss)
2895 && bitmap_is_all_zeros(tf->match.bm, MFF_N_IDS));
2896 }
2897
2898 static bool
2899 table_stats_equal(const struct ofputil_table_stats *a,
2900 const struct ofputil_table_stats *b)
2901 {
2902 return (a->active_count == b->active_count
2903 && a->lookup_count == b->lookup_count
2904 && a->matched_count == b->matched_count);
2905 }
2906
2907 void
2908 ofp_print_table_features(struct ds *s,
2909 const struct ofputil_table_features *features,
2910 const struct ofputil_table_features *prev_features,
2911 const struct ofputil_table_stats *stats,
2912 const struct ofputil_table_stats *prev_stats)
2913 {
2914 int i;
2915
2916 ds_put_format(s, " table %"PRIu8, features->table_id);
2917 if (features->name[0]) {
2918 ds_put_format(s, " (\"%s\")", features->name);
2919 }
2920 ds_put_char(s, ':');
2921
2922 bool same_stats = prev_stats && table_stats_equal(stats, prev_stats);
2923 bool same_features = prev_features && table_features_equal(features,
2924 prev_features);
2925 if ((!stats || same_stats) && same_features) {
2926 ds_put_cstr(s, " ditto");
2927 return;
2928 }
2929 ds_put_char(s, '\n');
2930 if (stats) {
2931 ds_put_format(s, " active=%"PRIu32", ", stats->active_count);
2932 ds_put_format(s, "lookup=%"PRIu64", ", stats->lookup_count);
2933 ds_put_format(s, "matched=%"PRIu64"\n", stats->matched_count);
2934 }
2935 if (same_features) {
2936 if (!table_features_empty(features)) {
2937 ds_put_cstr(s, " (same features)\n");
2938 }
2939 return;
2940 }
2941 if (features->metadata_match || features->metadata_write) {
2942 ds_put_format(s, " metadata: match=%#"PRIx64" write=%#"PRIx64"\n",
2943 ntohll(features->metadata_match),
2944 ntohll(features->metadata_write));
2945 }
2946
2947 if (features->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
2948 ds_put_format(s, " config=%s\n",
2949 ofputil_table_miss_to_string(features->miss_config));
2950 }
2951
2952 if (features->supports_eviction >= 0) {
2953 ds_put_format(s, " eviction: %ssupported\n",
2954 features->supports_eviction ? "" : "not ");
2955
2956 }
2957 if (features->supports_vacancy_events >= 0) {
2958 ds_put_format(s, " vacancy events: %ssupported\n",
2959 features->supports_vacancy_events ? "" : "not ");
2960
2961 }
2962
2963 if (features->max_entries) {
2964 ds_put_format(s, " max_entries=%"PRIu32"\n", features->max_entries);
2965 }
2966
2967 const struct ofputil_table_instruction_features *prev_nonmiss
2968 = prev_features ? &prev_features->nonmiss : NULL;
2969 const struct ofputil_table_instruction_features *prev_miss
2970 = prev_features ? &prev_features->miss : NULL;
2971 if (prev_features
2972 && table_instruction_features_equal(&features->nonmiss, prev_nonmiss)
2973 && table_instruction_features_equal(&features->miss, prev_miss)) {
2974 if (!table_instruction_features_empty(&features->nonmiss)) {
2975 ds_put_cstr(s, " (same instructions)\n");
2976 }
2977 } else if (!table_instruction_features_equal(&features->nonmiss,
2978 &features->miss)) {
2979 ds_put_cstr(s, " instructions (other than table miss):\n");
2980 print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
2981 ds_put_cstr(s, " instructions (table miss):\n");
2982 print_table_instruction_features(s, &features->miss, prev_miss);
2983 } else if (!table_instruction_features_empty(&features->nonmiss)) {
2984 ds_put_cstr(s, " instructions (table miss and others):\n");
2985 print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
2986 }
2987
2988 if (!bitmap_is_all_zeros(features->match.bm, MFF_N_IDS)) {
2989 if (prev_features
2990 && bitmap_equal(features->match.bm, prev_features->match.bm,
2991 MFF_N_IDS)) {
2992 ds_put_cstr(s, " (same matching)\n");
2993 } else {
2994 ds_put_cstr(s, " matching:\n");
2995 BITMAP_FOR_EACH_1 (i, MFF_N_IDS, features->match.bm) {
2996 const struct mf_field *f = mf_from_id(i);
2997 bool mask = bitmap_is_set(features->mask.bm, i);
2998 bool wildcard = bitmap_is_set(features->wildcard.bm, i);
2999
3000 ds_put_format(s, " %s: %s\n",
3001 f->name,
3002 (mask ? "arbitrary mask"
3003 : wildcard ? "exact match or wildcard"
3004 : "must exact match"));
3005 }
3006 }
3007 }
3008 }
3009
3010 static void
3011 ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh)
3012 {
3013 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3014
3015 struct ofputil_table_features prev;
3016 for (int i = 0; ; i++) {
3017 struct ofputil_table_features tf;
3018 int retval;
3019
3020 retval = ofputil_decode_table_features(&b, &tf, true);
3021 if (retval) {
3022 if (retval != EOF) {
3023 ofp_print_error(s, retval);
3024 }
3025 return;
3026 }
3027
3028 ds_put_char(s, '\n');
3029 ofp_print_table_features(s, &tf, i ? &prev : NULL, NULL, NULL);
3030 prev = tf;
3031 }
3032 }
3033
3034 static void
3035 ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh)
3036 {
3037 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3038 for (;;) {
3039 struct ofputil_table_desc td;
3040 int retval;
3041
3042 retval = ofputil_decode_table_desc(&b, &td, oh->version);
3043 if (retval) {
3044 if (retval != EOF) {
3045 ofp_print_error(s, retval);
3046 }
3047 return;
3048 }
3049 ofp_print_table_desc(s, &td);
3050 }
3051 }
3052
3053 static const char *
3054 bundle_flags_to_name(uint32_t bit)
3055 {
3056 switch (bit) {
3057 case OFPBF_ATOMIC:
3058 return "atomic";
3059 case OFPBF_ORDERED:
3060 return "ordered";
3061 default:
3062 return NULL;
3063 }
3064 }
3065
3066 static void
3067 ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
3068 {
3069 int error;
3070 struct ofputil_bundle_ctrl_msg bctrl;
3071
3072 error = ofputil_decode_bundle_ctrl(oh, &bctrl);
3073 if (error) {
3074 ofp_print_error(s, error);
3075 return;
3076 }
3077
3078 ds_put_char(s, '\n');
3079
3080 ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id);
3081 switch (bctrl.type) {
3082 case OFPBCT_OPEN_REQUEST:
3083 ds_put_cstr(s, "OPEN_REQUEST");
3084 break;
3085 case OFPBCT_OPEN_REPLY:
3086 ds_put_cstr(s, "OPEN_REPLY");
3087 break;
3088 case OFPBCT_CLOSE_REQUEST:
3089 ds_put_cstr(s, "CLOSE_REQUEST");
3090 break;
3091 case OFPBCT_CLOSE_REPLY:
3092 ds_put_cstr(s, "CLOSE_REPLY");
3093 break;
3094 case OFPBCT_COMMIT_REQUEST:
3095 ds_put_cstr(s, "COMMIT_REQUEST");
3096 break;
3097 case OFPBCT_COMMIT_REPLY:
3098 ds_put_cstr(s, "COMMIT_REPLY");
3099 break;
3100 case OFPBCT_DISCARD_REQUEST:
3101 ds_put_cstr(s, "DISCARD_REQUEST");
3102 break;
3103 case OFPBCT_DISCARD_REPLY:
3104 ds_put_cstr(s, "DISCARD_REPLY");
3105 break;
3106 }
3107
3108 ds_put_cstr(s, " flags=");
3109 ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' ');
3110 }
3111
3112 static void
3113 ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity)
3114 {
3115 int error;
3116 struct ofputil_bundle_add_msg badd;
3117
3118 error = ofputil_decode_bundle_add(oh, &badd, NULL);
3119 if (error) {
3120 ofp_print_error(s, error);
3121 return;
3122 }
3123
3124 ds_put_char(s, '\n');
3125 ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id);
3126 ds_put_cstr(s, " flags=");
3127 ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' ');
3128
3129 ds_put_char(s, '\n');
3130 char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), verbosity);
3131 ds_put_and_free_cstr(s, msg);
3132 }
3133
3134 static void
3135 print_tlv_table(struct ds *s, struct ovs_list *mappings)
3136 {
3137 struct ofputil_tlv_map *map;
3138
3139 ds_put_cstr(s, " mapping table:\n");
3140 ds_put_cstr(s, " class\ttype\tlength\tmatch field\n");
3141 ds_put_cstr(s, " -----\t----\t------\t-----------");
3142
3143 LIST_FOR_EACH (map, list_node, mappings) {
3144 ds_put_char(s, '\n');
3145 ds_put_format(s, " 0x%"PRIx16"\t0x%"PRIx8"\t%"PRIu8"\ttun_metadata%"PRIu16,
3146 map->option_class, map->option_type, map->option_len,
3147 map->index);
3148 }
3149 }
3150
3151 static void
3152 ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
3153 {
3154 int error;
3155 struct ofputil_tlv_table_mod ttm;
3156
3157 error = ofputil_decode_tlv_table_mod(oh, &ttm);
3158 if (error) {
3159 ofp_print_error(s, error);
3160 return;
3161 }
3162
3163 ds_put_cstr(s, "\n ");
3164
3165 switch (ttm.command) {
3166 case NXTTMC_ADD:
3167 ds_put_cstr(s, "ADD");
3168 break;
3169 case NXTTMC_DELETE:
3170 ds_put_cstr(s, "DEL");
3171 break;
3172 case NXTTMC_CLEAR:
3173 ds_put_cstr(s, "CLEAR");
3174 break;
3175 }
3176
3177 if (ttm.command != NXTTMC_CLEAR) {
3178 print_tlv_table(s, &ttm.mappings);
3179 }
3180
3181 ofputil_uninit_tlv_table(&ttm.mappings);
3182 }
3183
3184 static void
3185 ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
3186 {
3187 int error;
3188 struct ofputil_tlv_table_reply ttr;
3189 struct ofputil_tlv_map *map;
3190 int allocated_space = 0;
3191
3192 error = ofputil_decode_tlv_table_reply(oh, &ttr);
3193 if (error) {
3194 ofp_print_error(s, error);
3195 return;
3196 }
3197
3198 ds_put_char(s, '\n');
3199
3200 LIST_FOR_EACH (map, list_node, &ttr.mappings) {
3201 allocated_space += map->option_len;
3202 }
3203
3204 ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
3205 ttr.max_option_space, ttr.max_fields);
3206 ds_put_format(s, " allocated option space=%d\n", allocated_space);
3207 ds_put_char(s, '\n');
3208 print_tlv_table(s, &ttr.mappings);
3209
3210 ofputil_uninit_tlv_table(&ttr.mappings);
3211 }
3212
3213 /* This function will print the request forward message. The reason for
3214 * request forward is taken from rf.request.type */
3215 static void
3216 ofp_print_requestforward(struct ds *string, const struct ofp_header *oh)
3217 {
3218 struct ofputil_requestforward rf;
3219 enum ofperr error;
3220
3221 error = ofputil_decode_requestforward(oh, &rf);
3222 if (error) {
3223 ofp_print_error(string, error);
3224 return;
3225 }
3226
3227 ds_put_cstr(string, " reason=");
3228
3229 switch (rf.reason) {
3230 case OFPRFR_GROUP_MOD:
3231 ds_put_cstr(string, "group_mod");
3232 ofp_print_group_mod__(string, oh->version, rf.group_mod);
3233 break;
3234
3235 case OFPRFR_METER_MOD:
3236 ds_put_cstr(string, "meter_mod");
3237 ofp_print_meter_mod__(string, rf.meter_mod);
3238 break;
3239
3240 case OFPRFR_N_REASONS:
3241 OVS_NOT_REACHED();
3242 }
3243 ofputil_destroy_requestforward(&rf);
3244 }
3245
3246 static void
3247 print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, int more)
3248 {
3249 ds_put_cstr(string, leader);
3250 if (stat != UINT64_MAX) {
3251 ds_put_format(string, "%"PRIu64, stat);
3252 } else {
3253 ds_put_char(string, '?');
3254 }
3255 if (more) {
3256 ds_put_cstr(string, ", ");
3257 } else {
3258 ds_put_cstr(string, "\n");
3259 }
3260 }
3261
3262 static void
3263 ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
3264 {
3265 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3266 for (;;) {
3267 struct ofputil_ipfix_stats is;
3268 int retval;
3269
3270 retval = ofputil_pull_ipfix_stats(&is, &b);
3271 if (retval) {
3272 if (retval != EOF) {
3273 ds_put_cstr(string, " ***parse error***");
3274 }
3275 return;
3276 }
3277
3278 ds_put_cstr(string, "\n bridge ipfix: ");
3279 print_ipfix_stat(string, "flows=", is.total_flows, 1);
3280 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
3281 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
3282 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
3283 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
3284 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
3285 ds_put_cstr(string, " ");
3286 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
3287 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
3288 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
3289 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
3290 }
3291 }
3292
3293 static void
3294 ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
3295 {
3296 ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
3297
3298 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
3299 for (;;) {
3300 struct ofputil_ipfix_stats is;
3301 int retval;
3302
3303 retval = ofputil_pull_ipfix_stats(&is, &b);
3304 if (retval) {
3305 if (retval != EOF) {
3306 ds_put_cstr(string, " ***parse error***");
3307 }
3308 return;
3309 }
3310
3311 ds_put_cstr(string, " id");
3312 ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is.collector_set_id);
3313 print_ipfix_stat(string, "flows=", is.total_flows, 1);
3314 print_ipfix_stat(string, "current flows=", is.current_flows, 1);
3315 print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
3316 print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
3317 print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
3318 print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
3319 ds_put_cstr(string, " ");
3320 print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
3321 print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
3322 print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
3323 print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
3324 }
3325 }
3326
3327 static void
3328 ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
3329 {
3330 ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
3331 }
3332
3333
3334 static void
3335 ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
3336 struct ds *string, int verbosity)
3337 {
3338 const void *msg = oh;
3339
3340 ofp_header_to_string__(oh, raw, string);
3341
3342 enum ofptype type = ofptype_from_ofpraw(raw);
3343 switch (type) {
3344 case OFPTYPE_GROUP_STATS_REQUEST:
3345 ofp_print_stats(string, oh);
3346 ofp_print_ofpst_group_request(string, oh);
3347 break;
3348
3349 case OFPTYPE_GROUP_STATS_REPLY:
3350 ofp_print_group_stats(string, oh);
3351 break;
3352
3353 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
3354 ofp_print_stats(string, oh);
3355 ofp_print_ofpst_group_desc_request(string, oh);
3356 break;
3357
3358 case OFPTYPE_GROUP_DESC_STATS_REPLY:
3359 ofp_print_group_desc(string, oh);
3360 break;
3361
3362 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
3363 ofp_print_stats(string, oh);
3364 break;
3365
3366 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
3367 ofp_print_group_features(string, oh);
3368 break;
3369
3370 case OFPTYPE_GROUP_MOD:
3371 ofp_print_group_mod(string, oh);
3372 break;
3373
3374 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
3375 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
3376 ofp_print_table_features_reply(string, oh);
3377 break;
3378
3379 case OFPTYPE_TABLE_DESC_REQUEST:
3380 case OFPTYPE_TABLE_DESC_REPLY:
3381 ofp_print_table_desc_reply(string, oh);
3382 break;
3383
3384 case OFPTYPE_HELLO:
3385 ofp_print_hello(string, oh);
3386 break;
3387
3388 case OFPTYPE_ERROR:
3389 ofp_print_error_msg(string, oh);
3390 break;
3391
3392 case OFPTYPE_ECHO_REQUEST:
3393 case OFPTYPE_ECHO_REPLY:
3394 ofp_print_echo(string, oh, verbosity);
3395 break;
3396
3397 case OFPTYPE_FEATURES_REQUEST:
3398 break;
3399
3400 case OFPTYPE_FEATURES_REPLY:
3401 ofp_print_switch_features(string, oh);
3402 break;
3403
3404 case OFPTYPE_GET_CONFIG_REQUEST:
3405 break;
3406
3407 case OFPTYPE_GET_CONFIG_REPLY:
3408 ofp_print_get_config_reply(string, oh);
3409 break;
3410
3411 case OFPTYPE_SET_CONFIG:
3412 ofp_print_set_config(string, oh);
3413 break;
3414
3415 case OFPTYPE_PACKET_IN:
3416 ofp_print_packet_in(string, oh, verbosity);
3417 break;
3418
3419 case OFPTYPE_FLOW_REMOVED:
3420 ofp_print_flow_removed(string, oh);
3421 break;
3422
3423 case OFPTYPE_PORT_STATUS:
3424 ofp_print_port_status(string, oh);
3425 break;
3426
3427 case OFPTYPE_PACKET_OUT:
3428 ofp_print_packet_out(string, oh, verbosity);
3429 break;
3430
3431 case OFPTYPE_FLOW_MOD:
3432 ofp_print_flow_mod(string, oh, verbosity);
3433 break;
3434
3435 case OFPTYPE_PORT_MOD:
3436 ofp_print_port_mod(string, oh);
3437 break;
3438
3439 case OFPTYPE_TABLE_MOD:
3440 ofp_print_table_mod(string, oh);
3441 break;
3442
3443 case OFPTYPE_METER_MOD:
3444 ofp_print_meter_mod(string, oh);
3445 break;
3446
3447 case OFPTYPE_BARRIER_REQUEST:
3448 case OFPTYPE_BARRIER_REPLY:
3449 break;
3450
3451 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
3452 ofp_print_queue_get_config_request(string, oh);
3453 break;
3454
3455 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
3456 ofp_print_queue_get_config_reply(string, oh);
3457 break;
3458
3459 case OFPTYPE_ROLE_REQUEST:
3460 case OFPTYPE_ROLE_REPLY:
3461 ofp_print_role_message(string, oh);
3462 break;
3463 case OFPTYPE_ROLE_STATUS:
3464 ofp_print_role_status_message(string, oh);
3465 break;
3466
3467 case OFPTYPE_REQUESTFORWARD:
3468 ofp_print_requestforward(string, oh);
3469 break;
3470
3471 case OFPTYPE_TABLE_STATUS:
3472 ofp_print_table_status_message(string, oh);
3473 break;
3474
3475 case OFPTYPE_METER_STATS_REQUEST:
3476 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
3477 ofp_print_stats(string, oh);
3478 ofp_print_meter_stats_request(string, oh);
3479 break;
3480
3481 case OFPTYPE_METER_STATS_REPLY:
3482 ofp_print_stats(string, oh);
3483 ofp_print_meter_stats_reply(string, oh);
3484 break;
3485
3486 case OFPTYPE_METER_CONFIG_STATS_REPLY:
3487 ofp_print_stats(string, oh);
3488 ofp_print_meter_config_reply(string, oh);
3489 break;
3490
3491 case OFPTYPE_METER_FEATURES_STATS_REPLY:
3492 ofp_print_stats(string, oh);
3493 ofp_print_meter_features_reply(string, oh);
3494 break;
3495
3496 case OFPTYPE_DESC_STATS_REQUEST:
3497 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
3498 ofp_print_stats(string, oh);
3499 break;
3500
3501 case OFPTYPE_FLOW_STATS_REQUEST:
3502 case OFPTYPE_AGGREGATE_STATS_REQUEST:
3503 ofp_print_stats(string, oh);
3504 ofp_print_flow_stats_request(string, oh);
3505 break;
3506
3507 case OFPTYPE_TABLE_STATS_REQUEST:
3508 ofp_print_stats(string, oh);
3509 break;
3510
3511 case OFPTYPE_PORT_STATS_REQUEST:
3512 ofp_print_stats(string, oh);
3513 ofp_print_ofpst_port_request(string, oh);
3514 break;
3515
3516 case OFPTYPE_QUEUE_STATS_REQUEST:
3517 ofp_print_stats(string, oh);
3518 ofp_print_ofpst_queue_request(string, oh);
3519 break;
3520
3521 case OFPTYPE_DESC_STATS_REPLY:
3522 ofp_print_stats(string, oh);
3523 ofp_print_ofpst_desc_reply(string, oh);
3524 break;
3525
3526 case OFPTYPE_FLOW_STATS_REPLY:
3527 ofp_print_stats(string, oh);
3528 ofp_print_flow_stats_reply(string, oh);
3529 break;
3530
3531 case OFPTYPE_QUEUE_STATS_REPLY:
3532 ofp_print_stats(string, oh);
3533 ofp_print_ofpst_queue_reply(string, oh, verbosity);
3534 break;
3535
3536 case OFPTYPE_PORT_STATS_REPLY:
3537 ofp_print_stats(string, oh);
3538 ofp_print_ofpst_port_reply(string, oh, verbosity);
3539 break;
3540
3541 case OFPTYPE_TABLE_STATS_REPLY:
3542 ofp_print_stats(string, oh);
3543 ofp_print_table_stats_reply(string, oh);
3544 break;
3545
3546 case OFPTYPE_AGGREGATE_STATS_REPLY:
3547 ofp_print_stats(string, oh);
3548 ofp_print_aggregate_stats_reply(string, oh);
3549 break;
3550
3551 case OFPTYPE_PORT_DESC_STATS_REQUEST:
3552 ofp_print_stats(string, oh);
3553 ofp_print_ofpst_port_desc_request(string, oh);
3554 break;
3555
3556 case OFPTYPE_PORT_DESC_STATS_REPLY:
3557 ofp_print_stats(string, oh);
3558 ofp_print_ofpst_port_desc_reply(string, oh);
3559 break;
3560
3561 case OFPTYPE_FLOW_MOD_TABLE_ID:
3562 ofp_print_nxt_flow_mod_table_id(string, ofpmsg_body(oh));
3563 break;
3564
3565 case OFPTYPE_SET_FLOW_FORMAT:
3566 ofp_print_nxt_set_flow_format(string, ofpmsg_body(oh));
3567 break;
3568
3569 case OFPTYPE_SET_PACKET_IN_FORMAT:
3570 ofp_print_nxt_set_packet_in_format(string, ofpmsg_body(oh));
3571 break;
3572
3573 case OFPTYPE_FLOW_AGE:
3574 break;
3575
3576 case OFPTYPE_SET_CONTROLLER_ID:
3577 ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
3578 break;
3579
3580 case OFPTYPE_GET_ASYNC_REPLY:
3581 case OFPTYPE_SET_ASYNC_CONFIG:
3582 ofp_print_set_async_config(string, oh, type);
3583 break;
3584 case OFPTYPE_GET_ASYNC_REQUEST:
3585 break;
3586 case OFPTYPE_FLOW_MONITOR_CANCEL:
3587 ofp_print_nxt_flow_monitor_cancel(string, msg);
3588 break;
3589
3590 case OFPTYPE_FLOW_MONITOR_PAUSED:
3591 case OFPTYPE_FLOW_MONITOR_RESUMED:
3592 break;
3593
3594 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
3595 ofp_print_nxst_flow_monitor_request(string, msg);
3596 break;
3597
3598 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
3599 ofp_print_nxst_flow_monitor_reply(string, msg);
3600 break;
3601
3602 case OFPTYPE_BUNDLE_CONTROL:
3603 ofp_print_bundle_ctrl(string, msg);
3604 break;
3605
3606 case OFPTYPE_BUNDLE_ADD_MESSAGE:
3607 ofp_print_bundle_add(string, msg, verbosity);
3608 break;
3609
3610 case OFPTYPE_NXT_TLV_TABLE_MOD:
3611 ofp_print_tlv_table_mod(string, msg);
3612 break;
3613
3614 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
3615 break;
3616
3617 case OFPTYPE_NXT_TLV_TABLE_REPLY:
3618 ofp_print_tlv_table_reply(string, msg);
3619 break;
3620
3621 case OFPTYPE_NXT_RESUME:
3622 ofp_print_packet_in(string, msg, verbosity);
3623 break;
3624 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
3625 break;
3626 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
3627 ofp_print_nxst_ipfix_bridge_reply(string, oh);
3628 break;
3629 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
3630 break;
3631 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
3632 ofp_print_nxst_ipfix_flow_reply(string, oh);
3633 break;
3634
3635 case OFPTYPE_CT_FLUSH_ZONE:
3636 ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
3637 break;
3638 }
3639 }
3640
3641 /* Composes and returns a string representing the OpenFlow packet of 'len'
3642 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
3643 * verbosity and higher numbers increase verbosity. The caller is responsible
3644 * for freeing the string. */
3645 char *
3646 ofp_to_string(const void *oh_, size_t len, int verbosity)
3647 {
3648 struct ds string = DS_EMPTY_INITIALIZER;
3649 const struct ofp_header *oh = oh_;
3650
3651 if (!len) {
3652 ds_put_cstr(&string, "OpenFlow message is empty\n");
3653 } else if (len < sizeof(struct ofp_header)) {
3654 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
3655 len);
3656 } else if (ntohs(oh->length) > len) {
3657 enum ofperr error;
3658 enum ofpraw raw;
3659
3660 error = ofpraw_decode_partial(&raw, oh, len);
3661 if (!error) {
3662 ofp_header_to_string__(oh, raw, &string);
3663 ds_put_char(&string, '\n');
3664 }
3665
3666 ds_put_format(&string,
3667 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
3668 len, ntohs(oh->length));
3669 } else if (ntohs(oh->length) < len) {
3670 ds_put_format(&string,
3671 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
3672 ntohs(oh->length), len);
3673 } else {
3674 enum ofperr error;
3675 enum ofpraw raw;
3676
3677 error = ofpraw_decode(&raw, oh);
3678 if (!error) {
3679 ofp_to_string__(oh, raw, &string, verbosity);
3680 if (verbosity >= 5) {
3681 if (ds_last(&string) != '\n') {
3682 ds_put_char(&string, '\n');
3683 }
3684 ds_put_hex_dump(&string, oh, len, 0, true);
3685 }
3686 if (ds_last(&string) != '\n') {
3687 ds_put_char(&string, '\n');
3688 }
3689 return ds_steal_cstr(&string);
3690 }
3691
3692 ofp_print_error(&string, error);
3693 }
3694 ds_put_hex_dump(&string, oh, len, 0, true);
3695 return ds_steal_cstr(&string);
3696 }
3697 \f
3698 static void
3699 print_and_free(FILE *stream, char *string)
3700 {
3701 fputs(string, stream);
3702 free(string);
3703 }
3704
3705 /* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
3706 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
3707 * numbers increase verbosity. */
3708 void
3709 ofp_print(FILE *stream, const void *oh, size_t len, int verbosity)
3710 {
3711 print_and_free(stream, ofp_to_string(oh, len, verbosity));
3712 }
3713
3714 /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
3715 * 'data' to 'stream'. */
3716 void
3717 ofp_print_packet(FILE *stream, const void *data, size_t len)
3718 {
3719 print_and_free(stream, ofp_packet_to_string(data, len));
3720 }