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