Coverage Report

Created: 2025-10-10 06:39

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