]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-print.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / ofp-print.c
CommitLineData
064af421 1/*
04f48a68 2 * Copyright (c) 2008-2017 Nicira, Inc.
064af421 3 *
a14bc59f
BP
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
064af421 7 *
a14bc59f
BP
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
064af421
BP
15 */
16
17#include <config.h>
064af421 18
0c24b0ba
BP
19#include "openvswitch/ofp-print.h"
20
064af421
BP
21#include <errno.h>
22#include <inttypes.h>
7f3adc00 23#include <sys/types.h>
064af421
BP
24#include <netinet/in.h>
25#include <sys/wait.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <ctype.h>
29
daff3353 30#include "bundle.h"
10a24935 31#include "byte-order.h"
ab8e7f7d 32#include "colors.h"
064af421 33#include "compiler.h"
25d436fb 34#include "dp-packet.h"
064af421 35#include "flow.h"
75a75043 36#include "learn.h"
53ddd40a 37#include "multipath.h"
9e1fd49b 38#include "netdev.h"
7fa91113 39#include "nx-match.h"
25d436fb 40#include "odp-util.h"
064af421 41#include "openflow/nicira-ext.h"
b598f214 42#include "openflow/openflow.h"
d271907f
BW
43#include "openvswitch/dynamic-string.h"
44#include "openvswitch/meta-flow.h"
b598f214 45#include "openvswitch/ofp-actions.h"
0d71302e
BP
46#include "openvswitch/ofp-bundle.h"
47#include "openvswitch/ofp-connection.h"
e03c096d 48#include "openvswitch/ofp-errors.h"
0d71302e
BP
49#include "openvswitch/ofp-group.h"
50#include "openvswitch/ofp-ipfix.h"
51#include "openvswitch/ofp-match.h"
52#include "openvswitch/ofp-meter.h"
53#include "openvswitch/ofp-monitor.h"
d271907f 54#include "openvswitch/ofp-msgs.h"
0d71302e
BP
55#include "openvswitch/ofp-port.h"
56#include "openvswitch/ofp-queue.h"
57#include "openvswitch/ofp-switch.h"
58#include "openvswitch/ofp-table.h"
d271907f
BW
59#include "openvswitch/ofp-util.h"
60#include "openvswitch/ofpbuf.h"
61#include "openvswitch/type-props.h"
064af421 62#include "packets.h"
c4617b3c 63#include "unaligned.h"
064af421 64#include "util.h"
d5dc60f0 65#include "uuid.h"
064af421 66
90bf1e07 67static void ofp_print_error(struct ds *, enum ofperr);
064af421
BP
68
69/* Returns a string that represents the contents of the Ethernet frame in the
897a8e07 70 * 'len' bytes starting at 'data'. The caller must free the returned string.*/
064af421 71char *
2482b0b0 72ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
064af421
BP
73{
74 struct ds ds = DS_EMPTY_INITIALIZER;
cf62fa4c 75 struct dp_packet buf;
897a8e07 76 struct flow flow;
5a51b2cd 77 size_t l4_size;
064af421 78
cf62fa4c 79 dp_packet_use_const(&buf, data, len);
2482b0b0 80 buf.packet_type = packet_type;
cf62fa4c 81 flow_extract(&buf, &flow);
50f96b10 82 flow_format(&ds, &flow, NULL);
e50abca5 83
cf62fa4c 84 l4_size = dp_packet_l4_size(&buf);
5a51b2cd
JR
85
86 if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
cf62fa4c 87 struct tcp_header *th = dp_packet_l4(&buf);
5a51b2cd
JR
88 ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum));
89 } else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
cf62fa4c 90 struct udp_header *uh = dp_packet_l4(&buf);
5a51b2cd
JR
91 ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum));
92 } else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) {
cf62fa4c 93 struct sctp_header *sh = dp_packet_l4(&buf);
5fa008d4
BP
94 ds_put_format(&ds, " sctp_csum:%"PRIx32,
95 ntohl(get_16aligned_be32(&sh->sctp_csum)));
e60e935b 96 } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
cf62fa4c 97 struct icmp_header *icmph = dp_packet_l4(&buf);
e60e935b
SRCSA
98 ds_put_format(&ds, " icmp_csum:%"PRIx16,
99 ntohs(icmph->icmp_csum));
100 } else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= ICMP6_HEADER_LEN) {
cf62fa4c 101 struct icmp6_header *icmp6h = dp_packet_l4(&buf);
e60e935b
SRCSA
102 ds_put_format(&ds, " icmp6_csum:%"PRIx16,
103 ntohs(icmp6h->icmp6_cksum));
e50abca5
EJ
104 }
105
897a8e07 106 ds_put_char(&ds, '\n');
064af421 107
064af421
BP
108 return ds_cstr(&ds);
109}
110
2482b0b0
JS
111char *
112ofp_dp_packet_to_string(const struct dp_packet *packet)
113{
114 return ofp_packet_to_string(dp_packet_data(packet),
115 dp_packet_size(packet),
116 packet->packet_type);
117}
118
2d071a32 119static enum ofperr
65120a8a 120ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
121 const struct ofputil_port_map *port_map,
122 const struct ofputil_table_map *table_map, int verbosity)
064af421 123{
77ab5fd2 124 struct ofputil_packet_in_private pin;
9bfe9334
BP
125 uint32_t buffer_id;
126 size_t total_len;
dfc77282
BP
127 enum ofperr error = ofputil_decode_packet_in_private(oh, true, NULL, NULL,
128 &pin, &total_len,
129 &buffer_id);
130 if (!error) {
131 ofputil_packet_in_private_format(string, &pin, total_len, buffer_id,
132 port_map, table_map, verbosity);
133 ofputil_packet_in_private_destroy(&pin);
b4ccee75 134 }
dfc77282 135 return error;
064af421
BP
136}
137
2d071a32 138static enum ofperr
982697a4 139ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
140 const struct ofputil_port_map *port_map,
141 const struct ofputil_table_map *table_map, int verbosity)
064af421 142{
c6a93eb7 143 struct ofputil_packet_out po;
f25d0cf3 144 struct ofpbuf ofpacts;
c6a93eb7 145 enum ofperr error;
064af421 146
f25d0cf3 147 ofpbuf_init(&ofpacts, 64);
89d7927b 148 error = ofputil_decode_packet_out(&po, oh, NULL, &ofpacts);
dfc77282
BP
149 if (!error) {
150 ofputil_packet_out_format(string, &po, port_map, table_map, verbosity);
064af421 151 }
f25d0cf3 152 ofpbuf_uninit(&ofpacts);
dfc77282 153 return error;
064af421
BP
154}
155
dfc77282 156void
0ab14c8e 157ofp_print_bit_names(struct ds *string, uint32_t bits,
e8fa940e
BP
158 const char *(*bit_to_name)(uint32_t bit),
159 char separator)
064af421 160{
0ab14c8e 161 int n = 0;
9e1fd49b 162 int i;
0ab14c8e
BP
163
164 if (!bits) {
165 ds_put_cstr(string, "0");
064af421
BP
166 return;
167 }
0ab14c8e 168
9e1fd49b
BP
169 for (i = 0; i < 32; i++) {
170 uint32_t bit = UINT32_C(1) << i;
171
172 if (bits & bit) {
173 const char *name = bit_to_name(bit);
174 if (name) {
175 if (n++) {
e8fa940e 176 ds_put_char(string, separator);
9e1fd49b
BP
177 }
178 ds_put_cstr(string, name);
179 bits &= ~bit;
0ab14c8e 180 }
0ab14c8e 181 }
064af421 182 }
0ab14c8e
BP
183
184 if (bits) {
f5cd6874 185 if (n) {
e8fa940e 186 ds_put_char(string, separator);
0ab14c8e
BP
187 }
188 ds_put_format(string, "0x%"PRIx32, bits);
064af421 189 }
0ab14c8e
BP
190}
191
2d071a32 192static enum ofperr
982697a4 193ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
064af421 194{
9e1fd49b 195 struct ofputil_switch_features features;
0a2869d5
BP
196 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
197 enum ofperr error = ofputil_pull_switch_features(&b, &features);
dfc77282
BP
198 if (!error) {
199 ofputil_switch_features_format(string, &features);
200 error = ofputil_phy_ports_format(string, oh->version, &b);
f0fd1a17 201 }
dfc77282 202 return error;
ad99e2ed
BP
203}
204
2d071a32 205static enum ofperr
ad99e2ed
BP
206ofp_print_set_config(struct ds *string, const struct ofp_header *oh)
207{
208 struct ofputil_switch_config config;
209 enum ofperr error;
210
211 error = ofputil_decode_set_config(oh, &config);
212 if (error) {
2d071a32 213 return error;
064af421 214 }
dfc77282 215 ofputil_switch_config_format(string, &config);
2d071a32 216 return 0;
ad99e2ed 217}
064af421 218
2d071a32 219static enum ofperr
ad99e2ed
BP
220ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh)
221{
222 struct ofputil_switch_config config;
223 ofputil_decode_get_config_reply(oh, &config);
dfc77282 224 ofputil_switch_config_format(string, &config);
2d071a32 225 return 0;
064af421
BP
226}
227
2d071a32 228static enum ofperr
b47e7e2b 229ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh)
064af421 230{
dfc77282 231 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
f904747b 232
dfc77282 233 struct ofputil_table_features prev;
9d36d7d7 234 int first_ditto = -1, last_ditto = -1;
dfc77282
BP
235 for (int i = 0; ; i++) {
236 struct ofputil_table_features tf;
4e413ac8
BP
237 struct ofpbuf raw_properties;
238 int retval = ofputil_decode_table_features(&b, &tf, &raw_properties);
dfc77282 239 if (retval) {
9d36d7d7 240 ofputil_table_features_format_finish(s, first_ditto, last_ditto);
dfc77282
BP
241 return retval != EOF ? retval : 0;
242 }
0fb88c18 243
dfc77282 244 ofputil_table_features_format(s, &tf, i ? &prev : NULL, NULL, NULL,
b47e7e2b 245 &first_ditto, &last_ditto);
dfc77282 246 prev = tf;
7fa91113 247 }
064af421
BP
248}
249
dfc77282 250void
09862ec6
BP
251ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
252{
253 ds_put_format(string, "%u", sec);
b1634591
BP
254
255 /* If there are no fractional seconds, don't print any decimals.
256 *
257 * If the fractional seconds can be expressed exactly as milliseconds,
258 * print 3 decimals. Open vSwitch provides millisecond precision for most
259 * time measurements, so printing 3 decimals every time makes it easier to
dfc77282
BP
260 * spot real changes in flow dumps that refresh themselves quickly.
261 *
262 * If the fractional seconds are more precise than milliseconds, print the
263 * number of decimals needed to express them exactly.
264 */
265 if (nsec > 0) {
266 unsigned int msec = nsec / 1000000;
267 if (msec * 1000000 == nsec) {
268 ds_put_format(string, ".%03u", msec);
269 } else {
270 ds_put_format(string, ".%09u", nsec);
271 while (string->string[string->length - 1] == '0') {
272 string->length--;
273 }
274 }
82c22d34 275 }
dfc77282 276 ds_put_char(string, 's');
82c22d34
BP
277}
278
dfc77282
BP
279static enum ofperr
280ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh,
281 const struct ofputil_port_map *port_map,
282 const struct ofputil_table_map *table_map)
82c22d34 283{
dfc77282
BP
284 struct ofputil_flow_removed fr;
285 enum ofperr error = ofputil_decode_flow_removed(&fr, oh);
286 if (!error) {
287 ofputil_flow_removed_format(string, &fr, port_map, table_map);
918f2b82 288 }
dfc77282 289 return error;
918f2b82
AZ
290}
291
dfc77282
BP
292static enum ofperr
293ofp_print_port_mod(struct ds *string, const struct ofp_header *oh,
294 const struct ofputil_port_map *port_map)
de7d3c07 295{
dfc77282
BP
296 struct ofputil_port_mod pm;
297 enum ofperr error = ofputil_decode_port_mod(oh, &pm, true);
298 if (!error) {
299 ofputil_port_mod_format(string, &pm, port_map);
de7d3c07 300 }
dfc77282 301 return error;
de7d3c07
SJ
302}
303
2d071a32 304static enum ofperr
4bc938cc
BP
305ofp_print_table_mod(struct ds *string, const struct ofp_header *oh,
306 const struct ofputil_table_map *table_map)
918f2b82 307{
dfc77282
BP
308 struct ofputil_table_mod tm;
309 enum ofperr error = ofputil_decode_table_mod(oh, &tm);
310 if (!error) {
311 ofputil_table_mod_format(string, &tm, table_map);
bab86012 312 }
dfc77282 313 return error;
03c72922
BP
314}
315
2d071a32 316static enum ofperr
4bc938cc
BP
317ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh,
318 const struct ofputil_table_map *table_map)
6c6eedc5
SJ
319{
320 struct ofputil_table_status ts;
fe2c69f4
BP
321 enum ofperr error = ofputil_decode_table_status(oh, &ts);
322 if (!error) {
323 ofputil_format_table_status(string, &ts, table_map);
638a19b0 324 }
fe2c69f4 325 return error;
3c35db62
NR
326}
327
2d071a32 328static enum ofperr
3c35db62
NR
329ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh)
330{
331 struct ofputil_meter_mod mm;
332 struct ofpbuf bands;
3c35db62
NR
333
334 ofpbuf_init(&bands, 64);
fe2c69f4 335 enum ofperr error = ofputil_decode_meter_mod(oh, &mm, &bands);
2d071a32 336 if (!error) {
fe2c69f4 337 ofputil_format_meter_mod(s, &mm);
3c35db62 338 }
638a19b0 339 ofpbuf_uninit(&bands);
2d071a32
BP
340
341 return error;
638a19b0
JR
342}
343
2d071a32 344static enum ofperr
638a19b0
JR
345ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh)
346{
347 uint32_t meter_id;
348
349 ofputil_decode_meter_request(oh, &meter_id);
9e638f22 350 ds_put_char(s, ' ');
638a19b0 351
fe2c69f4 352 ofputil_format_meter_id(s, meter_id, '=');
2d071a32
BP
353
354 return 0;
638a19b0
JR
355}
356
2d071a32 357static enum ofperr
638a19b0
JR
358ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
359{
360 struct ofputil_meter_features mf;
638a19b0 361 ofputil_decode_meter_features(oh, &mf);
fe2c69f4 362 ofputil_format_meter_features(s, &mf);
2d071a32 363 return 0;
638a19b0
JR
364}
365
2d071a32 366static enum ofperr
638a19b0
JR
367ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
368{
0a2869d5 369 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
638a19b0 370 struct ofpbuf bands;
2d071a32 371 int retval;
638a19b0 372
638a19b0
JR
373 ofpbuf_init(&bands, 64);
374 for (;;) {
375 struct ofputil_meter_config mc;
638a19b0
JR
376
377 retval = ofputil_decode_meter_config(&b, &mc, &bands);
378 if (retval) {
638a19b0
JR
379 break;
380 }
381 ds_put_char(s, '\n');
fe2c69f4 382 ofputil_format_meter_config(s, &mc);
638a19b0
JR
383 }
384 ofpbuf_uninit(&bands);
2d071a32
BP
385
386 return retval != EOF ? retval : 0;
638a19b0
JR
387}
388
2d071a32 389static enum ofperr
638a19b0
JR
390ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
391{
0a2869d5 392 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
638a19b0 393 struct ofpbuf bands;
2d071a32 394 int retval;
638a19b0 395
638a19b0
JR
396 ofpbuf_init(&bands, 64);
397 for (;;) {
398 struct ofputil_meter_stats ms;
638a19b0
JR
399
400 retval = ofputil_decode_meter_stats(&b, &ms, &bands);
401 if (retval) {
638a19b0
JR
402 break;
403 }
404 ds_put_char(s, '\n');
fe2c69f4 405 ofputil_format_meter_stats(s, &ms);
638a19b0
JR
406 }
407 ofpbuf_uninit(&bands);
2d071a32
BP
408
409 return retval != EOF ? retval : 0;
638a19b0
JR
410}
411
7fa91113 412static void
90bf1e07 413ofp_print_error(struct ds *string, enum ofperr error)
7fa91113 414{
90bf1e07 415 ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
f74be05a
JP
416}
417
2d071a32 418static enum ofperr
de6c85b0
SH
419ofp_print_hello(struct ds *string, const struct ofp_header *oh)
420{
dfc77282 421 ofputil_hello_format(string, oh);
2d071a32 422 return 0;
de6c85b0
SH
423}
424
2d071a32 425static enum ofperr
50f96b10 426ofp_print_error_msg(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
427 const struct ofputil_port_map *port_map,
428 const struct ofputil_table_map *table_map)
064af421 429{
982697a4 430 struct ofpbuf payload;
dfc77282 431 enum ofperr error = ofperr_decode_msg(oh, &payload);
90bf1e07 432 if (!error) {
2d071a32 433 return OFPERR_OFPBRC_BAD_LEN;
f74be05a 434 }
dfc77282 435 ofperr_msg_format(string, error, &payload, port_map, table_map);
dea241f1 436 ofpbuf_uninit(&payload);
2d071a32
BP
437
438 return 0;
064af421
BP
439}
440
2d071a32 441static enum ofperr
982697a4 442ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
064af421 443{
9e1fd49b 444 struct ofputil_port_status ps;
dfc77282
BP
445 enum ofperr error = ofputil_decode_port_status(oh, &ps);
446 if (!error) {
447 ofputil_port_status_format(string, &ps);
064af421 448 }
dfc77282 449 return error;
064af421
BP
450}
451
2d071a32 452static enum ofperr
982697a4 453ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
064af421 454{
982697a4
BP
455 const struct ofp_desc_stats *ods = ofpmsg_body(oh);
456
fbd76b2e 457 ds_put_char(string, '\n');
d295e8e9 458 ds_put_format(string, "Manufacturer: %.*s\n",
dd70b475
JP
459 (int) sizeof ods->mfr_desc, ods->mfr_desc);
460 ds_put_format(string, "Hardware: %.*s\n",
461 (int) sizeof ods->hw_desc, ods->hw_desc);
462 ds_put_format(string, "Software: %.*s\n",
463 (int) sizeof ods->sw_desc, ods->sw_desc);
464 ds_put_format(string, "Serial Num: %.*s\n",
465 (int) sizeof ods->serial_num, ods->serial_num);
466 ds_put_format(string, "DP Description: %.*s\n",
467 (int) sizeof ods->dp_desc, ods->dp_desc);
2d071a32
BP
468
469 return 0;
064af421
BP
470}
471
2d071a32 472static enum ofperr
50f96b10 473ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
474 const struct ofputil_port_map *port_map,
475 const struct ofputil_table_map *table_map)
064af421 476{
81d1ea94 477 struct ofputil_flow_stats_request fsr;
dfc77282
BP
478 enum ofperr error = ofputil_decode_flow_stats_request(&fsr, oh, NULL,
479 NULL);
480 if (!error) {
481 ofputil_flow_stats_request_format(string, &fsr, port_map, table_map);
bdcc5925 482 }
dfc77282 483 return error;
bdcc5925
BP
484}
485
2d071a32 486static enum ofperr
50f96b10 487ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
488 const struct ofputil_port_map *port_map,
489 const struct ofputil_table_map *table_map)
064af421 490{
0a2869d5 491 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
f25d0cf3 492 struct ofpbuf ofpacts;
2d071a32 493 int retval;
064af421 494
f25d0cf3 495 ofpbuf_init(&ofpacts, 64);
4ffd1b43
BP
496 for (;;) {
497 struct ofputil_flow_stats fs;
fab8fadb 498
f25d0cf3 499 retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
4ffd1b43 500 if (retval) {
064af421
BP
501 break;
502 }
1b3758c3 503 ds_put_cstr(string, "\n ");
dfc77282 504 ofputil_flow_stats_format(string, &fs, port_map, table_map, true);
bdcc5925 505 }
cb80d803 506 ofpbuf_uninit(&ofpacts);
2d071a32
BP
507
508 return retval != EOF ? retval : 0;
c6430da5
BP
509}
510
2d071a32 511static enum ofperr
982697a4 512ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
064af421 513{
982697a4
BP
514 struct ofputil_aggregate_stats as;
515 enum ofperr error;
064af421 516
982697a4 517 error = ofputil_decode_aggregate_stats_reply(&as, oh);
dfc77282
BP
518 if (!error) {
519 ofputil_aggregate_stats_format(string, &as);
982697a4 520 }
dfc77282 521 return error;
a2ad9ecd
BP
522}
523
2d071a32 524static enum ofperr
50f96b10
BP
525ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh,
526 const struct ofputil_port_map *port_map)
abaad8cf 527{
4e022ec0 528 ofp_port_t ofp10_port;
f8e4867e
SH
529 enum ofperr error;
530
531 error = ofputil_decode_port_stats_request(oh, &ofp10_port);
532 if (error) {
2d071a32 533 return error;
f8e4867e
SH
534 }
535
e1db42d6 536 ds_put_cstr(string, " port_no=");
50f96b10 537 ofputil_format_port(ofp10_port, port_map, string);
2d071a32
BP
538
539 return 0;
abaad8cf
JP
540}
541
2d071a32 542static enum ofperr
d1e2cf21 543ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
50f96b10 544 const struct ofputil_port_map *port_map,
d1e2cf21 545 int verbosity)
064af421 546{
fe2c69f4
BP
547 ds_put_format(string, " %"PRIuSIZE" ports\n",
548 ofputil_count_port_stats(oh));
064af421 549 if (verbosity < 1) {
2d071a32 550 return 0;
064af421
BP
551 }
552
0a2869d5 553 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 554 for (;;) {
f8e4867e
SH
555 struct ofputil_port_stats ps;
556 int retval;
557
558 retval = ofputil_decode_port_stats(&ps, &b);
559 if (retval) {
2d071a32 560 return retval != EOF ? retval : 0;
982697a4 561 }
fe2c69f4 562 ofputil_format_port_stats(string, &ps, port_map);
49b21677 563 netdev_free_custom_stats_counters(&ps.custom_stats);
064af421
BP
564 }
565}
566
2d071a32 567static enum ofperr
b47e7e2b 568ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh)
26df8b3e 569{
0a2869d5 570 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
26df8b3e
SH
571 ofpraw_pull_assert(&b);
572
8811fc0a
BP
573 struct ofputil_table_features prev_features;
574 struct ofputil_table_stats prev_stats;
9d36d7d7 575 int first_ditto = -1, last_ditto = -1;
8811fc0a 576 for (int i = 0;; i++) {
3c1bb396
BP
577 struct ofputil_table_features features;
578 struct ofputil_table_stats stats;
579 int retval;
982697a4 580
3c1bb396
BP
581 retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
582 if (retval) {
9d36d7d7
BP
583 ofputil_table_features_format_finish(string,
584 first_ditto, last_ditto);
2d071a32 585 return retval != EOF ? retval : 0;
982697a4
BP
586 }
587
dfc77282
BP
588 ofputil_table_features_format(string,
589 &features, i ? &prev_features : NULL,
590 &stats, i ? &prev_stats : NULL,
b47e7e2b 591 &first_ditto, &last_ditto);
8811fc0a
BP
592 prev_features = features;
593 prev_stats = stats;
26df8b3e
SH
594 }
595}
596
2d071a32 597static enum ofperr
70ae4f93 598ofp_print_ofpst_port_desc_request(struct ds *string,
50f96b10
BP
599 const struct ofp_header *oh,
600 const struct ofputil_port_map *port_map)
70ae4f93
BP
601{
602 enum ofperr error;
603 ofp_port_t port;
604
605 error = ofputil_decode_port_desc_stats_request(oh, &port);
606 if (error) {
2d071a32 607 return error;
70ae4f93
BP
608 }
609
610 ds_put_cstr(string, " port=");
50f96b10 611 ofputil_format_port(port, port_map, string);
2d071a32
BP
612
613 return 0;
70ae4f93
BP
614}
615
2d071a32 616static enum ofperr
2be393ed
JP
617ofp_print_ofpst_port_desc_reply(struct ds *string,
618 const struct ofp_header *oh)
619{
0a2869d5 620 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
982697a4 621 ofpraw_pull_assert(&b);
2be393ed 622 ds_put_char(string, '\n');
dfc77282 623 return ofputil_phy_ports_format(string, oh->version, &b);
2be393ed
JP
624}
625
064af421 626static void
5d40fc57 627ofp_print_stats(struct ds *string, const struct ofp_header *oh)
064af421 628{
982697a4 629 uint16_t flags = ofpmp_flags(oh);
d1e2cf21 630
982697a4 631 if (flags) {
d1e2cf21 632 ds_put_cstr(string, " flags=");
5d40fc57
SH
633 if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
634 && (flags & OFPSF_REPLY_MORE)) {
064af421
BP
635 ds_put_cstr(string, "[more]");
636 flags &= ~OFPSF_REPLY_MORE;
637 }
638 if (flags) {
d1e2cf21
BP
639 ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
640 flags);
064af421
BP
641 }
642 }
064af421
BP
643}
644
2d071a32 645static enum ofperr
d1e2cf21 646ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
064af421 647{
d1e2cf21 648 size_t len = ntohs(oh->length);
064af421 649
34582733 650 ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
064af421 651 if (verbosity > 1) {
d1e2cf21 652 ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
064af421 653 }
2d071a32
BP
654
655 return 0;
064af421
BP
656}
657
2d071a32 658static enum ofperr
00467f73
AC
659ofp_print_role_message(struct ds *string, const struct ofp_header *oh)
660{
661 struct ofputil_role_request rr;
fe2c69f4
BP
662 enum ofperr error = ofputil_decode_role_message(oh, &rr);
663 if (!error) {
664 ofputil_format_role_message(string, &rr);
00467f73 665 }
fe2c69f4 666 return error;
00467f73
AC
667}
668
2d071a32 669static enum ofperr
00467f73
AC
670ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh)
671{
672 struct ofputil_role_status rs;
fe2c69f4
BP
673 enum ofperr error = ofputil_decode_role_status(oh, &rs);
674 if (!error) {
675 ofputil_format_role_status(string, &rs);
61fe3a7b 676 }
fe2c69f4 677 return error;
61fe3a7b
BP
678}
679
2d071a32 680static enum ofperr
225c33ba 681ofp_print_nxt_flow_mod_table_id(struct ds *string, const struct ofp_header *oh)
6c1491fb 682{
225c33ba
BP
683 bool enable = ofputil_decode_nx_flow_mod_table_id(oh);
684 ds_put_format(string, " %s", enable ? "enable" : "disable");
2d071a32 685 return 0;
6c1491fb
BP
686}
687
2d071a32 688static enum ofperr
225c33ba 689ofp_print_nxt_set_flow_format(struct ds *string, const struct ofp_header *oh)
7fa91113 690{
225c33ba
BP
691 enum ofputil_protocol p = ofputil_decode_nx_set_flow_format(oh);
692 ds_put_format(string, " format=%s",
693 p == OFPUTIL_P_OF10_STD ? "openflow10"
694 : p == OFPUTIL_P_OF10_NXM ? "nxm"
695 : "(unknown)");
2d071a32 696 return 0;
7fa91113
BP
697}
698
2d071a32 699static enum ofperr
54834960 700ofp_print_nxt_set_packet_in_format(struct ds *string,
d8790c08 701 const struct ofp_header *oh)
54834960 702{
d8790c08
BP
703 enum ofputil_packet_in_format format;
704 enum ofperr error = ofputil_decode_set_packet_in_format(oh, &format);
705 if (!error) {
706 ds_put_format(string, " format=%s",
707 ofputil_packet_in_format_to_string(format));
54834960 708 }
d8790c08 709 return error;
54834960
EJ
710}
711
2d071a32 712static enum ofperr
904e5202 713ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
71f21279 714 enum ofptype ofptype)
80d5aefd 715{
904e5202
BP
716 struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
717 struct ofputil_async_cfg ac;
80d5aefd 718
71f21279 719 bool is_reply = ofptype == OFPTYPE_GET_ASYNC_REPLY;
904e5202
BP
720 enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
721 &basis, &ac);
722 if (error) {
2d071a32 723 return error;
904e5202 724 }
fe2c69f4 725 ofputil_format_set_async_config(string, &ac);
2d071a32 726 return 0;
80d5aefd
BP
727}
728
2d071a32 729static enum ofperr
a7349929
BP
730ofp_print_nxt_set_controller_id(struct ds *string,
731 const struct nx_controller_id *nci)
732{
733 ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
2d071a32 734 return 0;
a7349929
BP
735}
736
2d071a32 737static enum ofperr
2b07c8b1
BP
738ofp_print_nxt_flow_monitor_cancel(struct ds *string,
739 const struct ofp_header *oh)
740{
741 ds_put_format(string, " id=%"PRIu32,
742 ofputil_decode_flow_monitor_cancel(oh));
2d071a32 743 return 0;
2b07c8b1
BP
744}
745
2d071a32 746static enum ofperr
2b07c8b1 747ofp_print_nxst_flow_monitor_request(struct ds *string,
50f96b10 748 const struct ofp_header *oh,
4bc938cc
BP
749 const struct ofputil_port_map *port_map,
750 const struct ofputil_table_map *table_map)
2b07c8b1 751{
0a2869d5 752 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2b07c8b1
BP
753 for (;;) {
754 struct ofputil_flow_monitor_request request;
755 int retval;
756
757 retval = ofputil_decode_flow_monitor_request(&request, &b);
758 if (retval) {
2d071a32 759 return retval != EOF ? retval : 0;
2b07c8b1
BP
760 }
761
dfc77282
BP
762 ofputil_flow_monitor_request_format(string, &request,
763 port_map, table_map);
2b07c8b1
BP
764 }
765}
766
2d071a32 767static enum ofperr
2b07c8b1 768ofp_print_nxst_flow_monitor_reply(struct ds *string,
50f96b10 769 const struct ofp_header *oh,
4bc938cc
BP
770 const struct ofputil_port_map *port_map,
771 const struct ofputil_table_map *table_map)
2b07c8b1
BP
772{
773 uint64_t ofpacts_stub[1024 / 8];
0a2869d5
BP
774 struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
775 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
2b07c8b1 776
2b07c8b1
BP
777 for (;;) {
778 struct ofputil_flow_update update;
dfc77282 779 int retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
2b07c8b1 780 if (retval) {
2b07c8b1 781 ofpbuf_uninit(&ofpacts);
2d071a32 782 return retval != EOF ? retval : 0;
2b07c8b1 783 }
dfc77282 784 ofputil_flow_update_format(string, &update, port_map, table_map);
2b07c8b1
BP
785 }
786}
787
bdcc5925
BP
788void
789ofp_print_version(const struct ofp_header *oh,
790 struct ds *string)
d1e2cf21 791{
3811e66b
BP
792 switch (oh->version) {
793 case OFP10_VERSION:
794 break;
795 case OFP11_VERSION:
796 ds_put_cstr(string, " (OF1.1)");
4232ef77
SH
797 break;
798 case OFP12_VERSION:
799 ds_put_cstr(string, " (OF1.2)");
3811e66b 800 break;
2e1ae200
JR
801 case OFP13_VERSION:
802 ds_put_cstr(string, " (OF1.3)");
803 break;
9620f50c
AC
804 case OFP14_VERSION:
805 ds_put_cstr(string, " (OF1.4)");
806 break;
42dccab5
BP
807 case OFP15_VERSION:
808 ds_put_cstr(string, " (OF1.5)");
809 break;
3811e66b
BP
810 default:
811 ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
812 break;
813 }
814 ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid));
bdcc5925 815}
d1e2cf21 816
f25b4a81 817static void
982697a4
BP
818ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
819 struct ds *string)
f25b4a81 820{
982697a4 821 ds_put_cstr(string, ofpraw_get_name(raw));
f25b4a81
BP
822 ofp_print_version(oh, string);
823}
824
2d071a32 825static enum ofperr
4bc938cc
BP
826ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
827 const struct ofputil_table_map *table_map)
03c72922 828{
0a2869d5 829 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
03c72922
BP
830 for (;;) {
831 struct ofputil_table_desc td;
832 int retval;
833
834 retval = ofputil_decode_table_desc(&b, &td, oh->version);
835 if (retval) {
2d071a32 836 return retval != EOF ? retval : 0;
03c72922 837 }
dfc77282 838 ofputil_table_desc_format(s, &td, table_map);
03c72922
BP
839 }
840}
841
2d071a32 842static enum ofperr
777af88d
AC
843ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
844{
845 int error;
846 struct ofputil_bundle_ctrl_msg bctrl;
847
848 error = ofputil_decode_bundle_ctrl(oh, &bctrl);
849 if (error) {
2d071a32 850 return error;
777af88d 851 }
fe2c69f4 852 ofputil_format_bundle_ctrl_request(s, &bctrl);
2d071a32 853 return 0;
777af88d
AC
854}
855
2d071a32 856static enum ofperr
50f96b10 857ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
4bc938cc
BP
858 const struct ofputil_port_map *port_map,
859 const struct ofputil_table_map *table_map,
860 int verbosity)
777af88d 861{
777af88d 862 struct ofputil_bundle_add_msg badd;
fe2c69f4
BP
863 int error = ofputil_decode_bundle_add(oh, &badd, NULL);
864 if (!error) {
865 ofputil_format_bundle_add(s, &badd, port_map, table_map, verbosity);
6159c531 866 }
fe2c69f4 867 return error;
6159c531
JG
868}
869
2d071a32 870static enum ofperr
4e548ad9 871ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
6159c531 872{
4e548ad9 873 struct ofputil_tlv_table_mod ttm;
fe2c69f4
BP
874 int error = ofputil_decode_tlv_table_mod(oh, &ttm);
875 if (!error) {
876 ofputil_format_tlv_table_mod(s, &ttm);
877 ofputil_uninit_tlv_table(&ttm.mappings);
6159c531 878 }
fe2c69f4 879 return error;
6159c531
JG
880}
881
2d071a32 882static enum ofperr
4e548ad9 883ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
6159c531 884{
4e548ad9 885 struct ofputil_tlv_table_reply ttr;
fe2c69f4
BP
886 int error = ofputil_decode_tlv_table_reply(oh, &ttr);
887 if (!error) {
888 ofputil_format_tlv_table_reply(s, &ttr);
889 ofputil_uninit_tlv_table(&ttr.mappings);
6159c531 890 }
fe2c69f4 891 return error;
6159c531
JG
892}
893
3c35db62
NR
894/* This function will print the request forward message. The reason for
895 * request forward is taken from rf.request.type */
2d071a32 896static enum ofperr
50f96b10 897ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
4bc938cc
BP
898 const struct ofputil_port_map *port_map,
899 const struct ofputil_table_map *table_map)
3c35db62
NR
900{
901 struct ofputil_requestforward rf;
fe2c69f4
BP
902 enum ofperr error = ofputil_decode_requestforward(oh, &rf);
903 if (!error) {
904 ofputil_format_requestforward(string, oh->version,
905 &rf, port_map, table_map);
906 ofputil_destroy_requestforward(&rf);
fb8f22c1 907 }
fe2c69f4 908 return error;
fb8f22c1
BY
909}
910
2d071a32 911static enum ofperr
fb8f22c1
BY
912ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
913{
914 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
915 for (;;) {
916 struct ofputil_ipfix_stats is;
917 int retval;
918
919 retval = ofputil_pull_ipfix_stats(&is, &b);
920 if (retval) {
2d071a32 921 return retval != EOF ? retval : 0;
fb8f22c1 922 }
fe2c69f4 923 ofputil_format_ipfix_stats_bridge(string, &is);
fb8f22c1
BY
924 }
925}
926
2d071a32 927static enum ofperr
fb8f22c1
BY
928ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
929{
930 ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
931
932 struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
933 for (;;) {
934 struct ofputil_ipfix_stats is;
935 int retval;
936
937 retval = ofputil_pull_ipfix_stats(&is, &b);
938 if (retval) {
2d071a32 939 return retval != EOF ? retval : 0;
fb8f22c1 940 }
fe2c69f4 941 ofputil_format_ipfix_stats_flow(string, &is);
fb8f22c1
BY
942 }
943}
944
2d071a32 945static enum ofperr
2a7c4805
JP
946ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
947{
948 ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
2d071a32 949 return 0;
2a7c4805
JP
950}
951
2d071a32 952static enum ofperr
50f96b10 953ofp_to_string__(const struct ofp_header *oh,
4bc938cc
BP
954 const struct ofputil_port_map *port_map,
955 const struct ofputil_table_map *table_map, enum ofpraw raw,
982697a4 956 struct ds *string, int verbosity)
bdcc5925 957{
e428148a
BP
958 if (ofpmsg_is_stat(oh)) {
959 ofp_print_stats(string, oh);
960 }
961
bdcc5925 962 const void *msg = oh;
904e5202
BP
963 enum ofptype type = ofptype_from_ofpraw(raw);
964 switch (type) {
261bd854 965 case OFPTYPE_GROUP_STATS_REQUEST:
e9c9481f 966 return ofputil_group_stats_request_format(string, oh);
7395c052 967
261bd854 968 case OFPTYPE_GROUP_STATS_REPLY:
e9c9481f 969 return ofputil_group_stats_format(string, oh);
7395c052 970
261bd854 971 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
e9c9481f 972 return ofputil_group_desc_request_format(string, oh);
7395c052 973
261bd854 974 case OFPTYPE_GROUP_DESC_STATS_REPLY:
e9c9481f 975 return ofputil_group_desc_format(string, oh, port_map, table_map);
7395c052 976
261bd854 977 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
7395c052
NZ
978 break;
979
261bd854 980 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
e9c9481f 981 return ofputil_group_features_format(string, oh);
7395c052
NZ
982
983 case OFPTYPE_GROUP_MOD:
e9c9481f 984 return ofputil_group_mod_format(string, oh, port_map, table_map);
7395c052 985
261bd854
BP
986 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
987 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
b47e7e2b 988 return ofp_print_table_features_reply(string, oh);
2e1ae200 989
03c72922
BP
990 case OFPTYPE_TABLE_DESC_REQUEST:
991 case OFPTYPE_TABLE_DESC_REPLY:
4bc938cc 992 return ofp_print_table_desc_reply(string, oh, table_map);
03c72922 993
982697a4 994 case OFPTYPE_HELLO:
2d071a32 995 return ofp_print_hello(string, oh);
d1e2cf21 996
982697a4 997 case OFPTYPE_ERROR:
4bc938cc 998 return ofp_print_error_msg(string, oh, port_map, table_map);
d1e2cf21 999
982697a4
BP
1000 case OFPTYPE_ECHO_REQUEST:
1001 case OFPTYPE_ECHO_REPLY:
2d071a32 1002 return ofp_print_echo(string, oh, verbosity);
d1e2cf21 1003
982697a4 1004 case OFPTYPE_FEATURES_REQUEST:
d1e2cf21
BP
1005 break;
1006
982697a4 1007 case OFPTYPE_FEATURES_REPLY:
2d071a32 1008 return ofp_print_switch_features(string, oh);
d1e2cf21 1009
982697a4 1010 case OFPTYPE_GET_CONFIG_REQUEST:
d1e2cf21
BP
1011 break;
1012
982697a4 1013 case OFPTYPE_GET_CONFIG_REPLY:
2d071a32 1014 return ofp_print_get_config_reply(string, oh);
ad99e2ed 1015
982697a4 1016 case OFPTYPE_SET_CONFIG:
2d071a32 1017 return ofp_print_set_config(string, oh);
d1e2cf21 1018
982697a4 1019 case OFPTYPE_PACKET_IN:
4bc938cc 1020 return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
d1e2cf21 1021
982697a4 1022 case OFPTYPE_FLOW_REMOVED:
4bc938cc 1023 return ofp_print_flow_removed(string, oh, port_map, table_map);
d1e2cf21 1024
982697a4 1025 case OFPTYPE_PORT_STATUS:
2d071a32 1026 return ofp_print_port_status(string, oh);
d1e2cf21 1027
982697a4 1028 case OFPTYPE_PACKET_OUT:
4bc938cc
BP
1029 return ofp_print_packet_out(string, oh, port_map, table_map,
1030 verbosity);
d1e2cf21 1031
982697a4 1032 case OFPTYPE_FLOW_MOD:
dfc77282
BP
1033 return ofputil_flow_mod_format(string, oh, port_map, table_map,
1034 verbosity);
d1e2cf21 1035
982697a4 1036 case OFPTYPE_PORT_MOD:
2d071a32 1037 return ofp_print_port_mod(string, oh, port_map);
d1e2cf21 1038
918f2b82 1039 case OFPTYPE_TABLE_MOD:
4bc938cc 1040 return ofp_print_table_mod(string, oh, table_map);
918f2b82 1041
638a19b0 1042 case OFPTYPE_METER_MOD:
2d071a32 1043 return ofp_print_meter_mod(string, oh);
638a19b0 1044
982697a4
BP
1045 case OFPTYPE_BARRIER_REQUEST:
1046 case OFPTYPE_BARRIER_REPLY:
d1e2cf21
BP
1047 break;
1048
e8f9a7bb 1049 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
fe2c69f4 1050 return ofputil_queue_get_config_request_format(string, oh, port_map);
e8f9a7bb
VG
1051
1052 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
fe2c69f4 1053 return ofputil_queue_get_config_reply_format(string, oh, port_map);
e8f9a7bb 1054
6ea4776b
JR
1055 case OFPTYPE_ROLE_REQUEST:
1056 case OFPTYPE_ROLE_REPLY:
2d071a32 1057 return ofp_print_role_message(string, oh);
252f3411 1058 case OFPTYPE_ROLE_STATUS:
2d071a32 1059 return ofp_print_role_status_message(string, oh);
6ea4776b 1060
3c35db62 1061 case OFPTYPE_REQUESTFORWARD:
4bc938cc 1062 return ofp_print_requestforward(string, oh, port_map, table_map);
3c35db62 1063
6c6eedc5 1064 case OFPTYPE_TABLE_STATUS:
4bc938cc 1065 return ofp_print_table_status_message(string, oh, table_map);
6c6eedc5 1066
261bd854
BP
1067 case OFPTYPE_METER_STATS_REQUEST:
1068 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
2d071a32 1069 return ofp_print_meter_stats_request(string, oh);
638a19b0 1070
261bd854 1071 case OFPTYPE_METER_STATS_REPLY:
2d071a32 1072 return ofp_print_meter_stats_reply(string, oh);
638a19b0 1073
261bd854 1074 case OFPTYPE_METER_CONFIG_STATS_REPLY:
2d071a32 1075 return ofp_print_meter_config_reply(string, oh);
638a19b0 1076
261bd854 1077 case OFPTYPE_METER_FEATURES_STATS_REPLY:
2d071a32 1078 return ofp_print_meter_features_reply(string, oh);
638a19b0 1079
982697a4 1080 case OFPTYPE_DESC_STATS_REQUEST:
261bd854 1081 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
d1e2cf21
BP
1082 break;
1083
982697a4
BP
1084 case OFPTYPE_FLOW_STATS_REQUEST:
1085 case OFPTYPE_AGGREGATE_STATS_REQUEST:
4bc938cc 1086 return ofp_print_flow_stats_request(string, oh, port_map, table_map);
d1e2cf21 1087
982697a4 1088 case OFPTYPE_TABLE_STATS_REQUEST:
d1e2cf21
BP
1089 break;
1090
982697a4 1091 case OFPTYPE_PORT_STATS_REQUEST:
2d071a32 1092 return ofp_print_ofpst_port_request(string, oh, port_map);
d1e2cf21 1093
982697a4 1094 case OFPTYPE_QUEUE_STATS_REQUEST:
fe2c69f4 1095 return ofputil_queue_stats_request_format(string, oh, port_map);
d1e2cf21 1096
982697a4 1097 case OFPTYPE_DESC_STATS_REPLY:
2d071a32 1098 return ofp_print_ofpst_desc_reply(string, oh);
d1e2cf21 1099
982697a4 1100 case OFPTYPE_FLOW_STATS_REPLY:
4bc938cc 1101 return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
d1e2cf21 1102
982697a4 1103 case OFPTYPE_QUEUE_STATS_REPLY:
fe2c69f4
BP
1104 return ofputil_queue_stats_reply_format(string, oh, port_map,
1105 verbosity);
d1e2cf21 1106
982697a4 1107 case OFPTYPE_PORT_STATS_REPLY:
2d071a32 1108 return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
d1e2cf21 1109
982697a4 1110 case OFPTYPE_TABLE_STATS_REPLY:
b47e7e2b 1111 return ofp_print_table_stats_reply(string, oh);
d1e2cf21 1112
982697a4 1113 case OFPTYPE_AGGREGATE_STATS_REPLY:
2d071a32 1114 return ofp_print_aggregate_stats_reply(string, oh);
064af421 1115
70ae4f93 1116 case OFPTYPE_PORT_DESC_STATS_REQUEST:
2d071a32 1117 return ofp_print_ofpst_port_desc_request(string, oh, port_map);
70ae4f93 1118
982697a4 1119 case OFPTYPE_PORT_DESC_STATS_REPLY:
2d071a32 1120 return ofp_print_ofpst_port_desc_reply(string, oh);
2be393ed 1121
982697a4 1122 case OFPTYPE_FLOW_MOD_TABLE_ID:
225c33ba 1123 return ofp_print_nxt_flow_mod_table_id(string, oh);
6c1491fb 1124
982697a4 1125 case OFPTYPE_SET_FLOW_FORMAT:
225c33ba 1126 return ofp_print_nxt_set_flow_format(string, oh);
7fa91113 1127
982697a4 1128 case OFPTYPE_SET_PACKET_IN_FORMAT:
d8790c08 1129 return ofp_print_nxt_set_packet_in_format(string, oh);
54834960 1130
982697a4 1131 case OFPTYPE_FLOW_AGE:
f27f2134
BP
1132 break;
1133
982697a4 1134 case OFPTYPE_SET_CONTROLLER_ID:
2d071a32 1135 return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
a7349929 1136
db09e430 1137 case OFPTYPE_GET_ASYNC_REPLY:
982697a4 1138 case OFPTYPE_SET_ASYNC_CONFIG:
2d071a32 1139 return ofp_print_set_async_config(string, oh, type);
db09e430
AC
1140 case OFPTYPE_GET_ASYNC_REQUEST:
1141 break;
982697a4 1142 case OFPTYPE_FLOW_MONITOR_CANCEL:
2d071a32 1143 return ofp_print_nxt_flow_monitor_cancel(string, msg);
2b07c8b1 1144
982697a4
BP
1145 case OFPTYPE_FLOW_MONITOR_PAUSED:
1146 case OFPTYPE_FLOW_MONITOR_RESUMED:
2b07c8b1
BP
1147 break;
1148
982697a4 1149 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
4bc938cc
BP
1150 return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
1151 table_map);
2b07c8b1 1152
982697a4 1153 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
4bc938cc
BP
1154 return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
1155 table_map);
777af88d
AC
1156
1157 case OFPTYPE_BUNDLE_CONTROL:
2d071a32 1158 return ofp_print_bundle_ctrl(string, msg);
777af88d
AC
1159
1160 case OFPTYPE_BUNDLE_ADD_MESSAGE:
4bc938cc
BP
1161 return ofp_print_bundle_add(string, msg, port_map, table_map,
1162 verbosity);
6159c531 1163
4e548ad9 1164 case OFPTYPE_NXT_TLV_TABLE_MOD:
2d071a32 1165 return ofp_print_tlv_table_mod(string, msg);
6159c531 1166
4e548ad9 1167 case OFPTYPE_NXT_TLV_TABLE_REQUEST:
6159c531
JG
1168 break;
1169
4e548ad9 1170 case OFPTYPE_NXT_TLV_TABLE_REPLY:
2d071a32 1171 return ofp_print_tlv_table_reply(string, msg);
6159c531 1172
77ab5fd2 1173 case OFPTYPE_NXT_RESUME:
4bc938cc
BP
1174 return ofp_print_packet_in(string, msg, port_map, table_map,
1175 verbosity);
fb8f22c1
BY
1176 case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
1177 break;
1178 case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
2d071a32 1179 return ofp_print_nxst_ipfix_bridge_reply(string, oh);
fb8f22c1
BY
1180 case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
1181 break;
1182 case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
2d071a32 1183 return ofp_print_nxst_ipfix_flow_reply(string, oh);
2a7c4805
JP
1184
1185 case OFPTYPE_CT_FLUSH_ZONE:
2d071a32
BP
1186 return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
1187 }
1188
1189 return 0;
1190}
1191
1192static void
1193add_newline(struct ds *s)
1194{
1195 if (s->length && s->string[s->length - 1] != '\n') {
1196 ds_put_char(s, '\n');
246e61ea 1197 }
d1e2cf21 1198}
064af421
BP
1199
1200/* Composes and returns a string representing the OpenFlow packet of 'len'
1201 * bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
1202 * verbosity and higher numbers increase verbosity. The caller is responsible
1203 * for freeing the string. */
1204char *
50f96b10 1205ofp_to_string(const void *oh_, size_t len,
4bc938cc
BP
1206 const struct ofputil_port_map *port_map,
1207 const struct ofputil_table_map *table_map,
1208 int verbosity)
064af421
BP
1209{
1210 struct ds string = DS_EMPTY_INITIALIZER;
1211 const struct ofp_header *oh = oh_;
064af421 1212
49ad0403
BP
1213 if (!len) {
1214 ds_put_cstr(&string, "OpenFlow message is empty\n");
1215 } else if (len < sizeof(struct ofp_header)) {
34582733 1216 ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
49ad0403 1217 len);
d1e2cf21 1218 } else if (ntohs(oh->length) > len) {
f25b4a81 1219 enum ofperr error;
982697a4 1220 enum ofpraw raw;
f25b4a81 1221
982697a4 1222 error = ofpraw_decode_partial(&raw, oh, len);
f25b4a81 1223 if (!error) {
982697a4 1224 ofp_header_to_string__(oh, raw, &string);
f25b4a81
BP
1225 ds_put_char(&string, '\n');
1226 }
1227
d1e2cf21 1228 ds_put_format(&string,
34582733 1229 "(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
d1e2cf21
BP
1230 len, ntohs(oh->length));
1231 } else if (ntohs(oh->length) < len) {
1232 ds_put_format(&string,
34582733 1233 "(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
d1e2cf21
BP
1234 ntohs(oh->length), len);
1235 } else {
90bf1e07 1236 enum ofperr error;
982697a4 1237 enum ofpraw raw;
d1e2cf21 1238
982697a4 1239 error = ofpraw_decode(&raw, oh);
d1e2cf21 1240 if (!error) {
2d071a32
BP
1241 ofp_header_to_string__(oh, raw, &string);
1242 size_t header_len = string.length;
1243
4bc938cc
BP
1244 error = ofp_to_string__(oh, port_map, table_map,
1245 raw, &string, verbosity);
2d071a32
BP
1246 if (error) {
1247 if (string.length > header_len) {
1248 ds_chomp(&string, ' ');
1249 add_newline(&string);
1250 } else {
1251 ds_put_char(&string, ' ');
7fa91113 1252 }
2d071a32
BP
1253 ofp_print_error(&string, error);
1254 } else {
1255 ds_chomp(&string, ' ');
d1e2cf21 1256 }
2d071a32
BP
1257 } else {
1258 ofp_print_error(&string, error);
1259 }
1260
1261 if (verbosity >= 5 || error) {
1262 add_newline(&string);
1263 ds_put_hex_dump(&string, oh, len, 0, true);
064af421 1264 }
064af421 1265
2d071a32
BP
1266 add_newline(&string);
1267 return ds_steal_cstr(&string);
064af421 1268 }
d1e2cf21
BP
1269 ds_put_hex_dump(&string, oh, len, 0, true);
1270 return ds_steal_cstr(&string);
064af421 1271}
064af421
BP
1272\f
1273static void
d295e8e9 1274print_and_free(FILE *stream, char *string)
064af421
BP
1275{
1276 fputs(string, stream);
1277 free(string);
1278}
1279
1280/* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
1281 * given 'verbosity' level. 0 is a minimal amount of verbosity and higher
1282 * numbers increase verbosity. */
1283void
50f96b10 1284ofp_print(FILE *stream, const void *oh, size_t len,
4bc938cc
BP
1285 const struct ofputil_port_map *port_map,
1286 const struct ofputil_table_map *table_map, int verbosity)
064af421 1287{
4bc938cc
BP
1288 print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
1289 verbosity));
064af421
BP
1290}
1291
1292/* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
897a8e07 1293 * 'data' to 'stream'. */
064af421 1294void
2482b0b0
JS
1295ofp_print_packet(FILE *stream, const void *data, size_t len,
1296 ovs_be32 packet_type)
1297{
1298 print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
1299}
1300
1301void
1302ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
064af421 1303{
2482b0b0 1304 print_and_free(stream, ofp_dp_packet_to_string(packet));
064af421 1305}