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