Coverage Report

Created: 2025-07-11 06:12

/src/openvswitch/lib/ofp-monitor.c
Line
Count
Source (jump to first uncovered line)
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
#include "openvswitch/ofp-monitor.h"
19
#include "byte-order.h"
20
#include "nx-match.h"
21
#include "ovs-atomic.h"
22
#include "openvswitch/ofp-actions.h"
23
#include "openvswitch/ofp-errors.h"
24
#include "openvswitch/ofp-group.h"
25
#include "openvswitch/ofp-match.h"
26
#include "openvswitch/ofp-meter.h"
27
#include "openvswitch/ofp-msgs.h"
28
#include "openvswitch/ofp-parse.h"
29
#include "openvswitch/ofp-print.h"
30
#include "openvswitch/ofp-table.h"
31
#include "openvswitch/vlog.h"
32
#include "ox-stat.h"
33
34
VLOG_DEFINE_THIS_MODULE(ofp_monitor);
35
36
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
37
38
/* Returns a string form of 'reason'.  The return value is either a statically
39
 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
40
 * 'bufsize' should be at least OFP_FLOW_REMOVED_REASON_BUFSIZE. */
41
const char *
42
ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason,
43
                                  char *reasonbuf, size_t bufsize)
44
15.8k
{
45
15.8k
    switch (reason) {
46
3.53k
    case OFPRR_IDLE_TIMEOUT:
47
3.53k
        return "idle";
48
2.62k
    case OFPRR_HARD_TIMEOUT:
49
2.62k
        return "hard";
50
2.04k
    case OFPRR_DELETE:
51
2.04k
        return "delete";
52
1.36k
    case OFPRR_GROUP_DELETE:
53
1.36k
        return "group_delete";
54
2.20k
    case OFPRR_EVICTION:
55
2.20k
        return "eviction";
56
1.14k
    case OFPRR_METER_DELETE:
57
1.14k
        return "meter_delete";
58
3
    case OVS_OFPRR_NONE:
59
2.98k
    default:
60
2.98k
        snprintf(reasonbuf, bufsize, "%d", (int) reason);
61
2.98k
        return reasonbuf;
62
15.8k
    }
63
15.8k
}
64
65
/* Converts an OFPT_FLOW_REMOVED or NXT_FLOW_REMOVED message 'oh' into an
66
 * abstract ofputil_flow_removed in 'fr'.  Returns 0 if successful, otherwise
67
 * an OpenFlow error code. */
68
enum ofperr
69
ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
70
                            const struct ofp_header *oh)
71
16.4k
{
72
16.4k
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
73
16.4k
    enum ofpraw raw = ofpraw_pull_assert(&b);
74
16.4k
    if (raw == OFPRAW_OFPT15_FLOW_REMOVED) {
75
10.5k
        const struct ofp15_flow_removed *ofr;
76
10.5k
        enum ofperr error;
77
78
10.5k
        ofr = ofpbuf_pull(&b, sizeof *ofr);
79
80
10.5k
        error = ofputil_pull_ofp11_match(&b, NULL, NULL,  &fr->match, NULL);
81
10.5k
        if (error) {
82
1.62k
            return error;
83
1.62k
        }
84
85
8.91k
        struct oxs_stats stats;
86
8.91k
        uint16_t statlen;
87
8.91k
        uint8_t oxs_field_set;
88
8.91k
        error = oxs_pull_stat(&b, &stats, &statlen, &oxs_field_set);
89
8.91k
        if (error) {
90
8.08k
            return error;
91
8.08k
        }
92
93
826
        fr->cookie = ofr->cookie;
94
826
        fr->priority = ntohs(ofr->priority);
95
826
        fr->reason = ofr->reason;
96
826
        fr->table_id = ofr->table_id;
97
826
        fr->duration_sec = stats.duration_sec;
98
826
        fr->duration_nsec = stats.duration_nsec;
99
826
        fr->idle_timeout = ntohs(ofr->idle_timeout);
100
826
        fr->hard_timeout = ntohs(ofr->hard_timeout);
101
826
        fr->packet_count = stats.packet_count;
102
826
        fr->byte_count = stats.byte_count;
103
5.86k
    } else if (raw == OFPRAW_OFPT11_FLOW_REMOVED) {
104
4.13k
        const struct ofp12_flow_removed *ofr;
105
4.13k
        enum ofperr error;
106
107
4.13k
        ofr = ofpbuf_pull(&b, sizeof *ofr);
108
109
4.13k
        error = ofputil_pull_ofp11_match(&b, NULL, NULL, &fr->match, NULL);
110
4.13k
        if (error) {
111
1.88k
            return error;
112
1.88k
        }
113
114
2.25k
        fr->priority = ntohs(ofr->priority);
115
2.25k
        fr->cookie = ofr->cookie;
116
2.25k
        fr->reason = ofr->reason;
117
2.25k
        fr->table_id = ofr->table_id;
118
2.25k
        fr->duration_sec = ntohl(ofr->duration_sec);
119
2.25k
        fr->duration_nsec = ntohl(ofr->duration_nsec);
120
2.25k
        fr->idle_timeout = ntohs(ofr->idle_timeout);
121
2.25k
        fr->hard_timeout = ntohs(ofr->hard_timeout);
122
2.25k
        fr->packet_count = ntohll(ofr->packet_count);
123
2.25k
        fr->byte_count = ntohll(ofr->byte_count);
124
2.25k
    } else if (raw == OFPRAW_OFPT10_FLOW_REMOVED) {
125
1.46k
        const struct ofp10_flow_removed *ofr;
126
127
1.46k
        ofr = ofpbuf_pull(&b, sizeof *ofr);
128
129
1.46k
        ofputil_match_from_ofp10_match(&ofr->match, &fr->match);
130
1.46k
        fr->priority = ntohs(ofr->priority);
131
1.46k
        fr->cookie = ofr->cookie;
132
1.46k
        fr->reason = ofr->reason;
133
1.46k
        fr->table_id = 255;
134
1.46k
        fr->duration_sec = ntohl(ofr->duration_sec);
135
1.46k
        fr->duration_nsec = ntohl(ofr->duration_nsec);
136
1.46k
        fr->idle_timeout = ntohs(ofr->idle_timeout);
137
1.46k
        fr->hard_timeout = 0;
138
1.46k
        fr->packet_count = ntohll(ofr->packet_count);
139
1.46k
        fr->byte_count = ntohll(ofr->byte_count);
140
1.46k
    } else if (raw == OFPRAW_NXT_FLOW_REMOVED) {
141
260
        struct nx_flow_removed *nfr;
142
260
        enum ofperr error;
143
144
260
        nfr = ofpbuf_pull(&b, sizeof *nfr);
145
260
        error = nx_pull_match(&b, ntohs(nfr->match_len), &fr->match, NULL,
146
260
                              NULL, false, NULL, NULL);
147
260
        if (error) {
148
101
            return error;
149
101
        }
150
159
        if (b.size) {
151
99
            return OFPERR_OFPBRC_BAD_LEN;
152
99
        }
153
154
60
        fr->priority = ntohs(nfr->priority);
155
60
        fr->cookie = nfr->cookie;
156
60
        fr->reason = nfr->reason;
157
60
        fr->table_id = nfr->table_id ? nfr->table_id - 1 : 255;
158
60
        fr->duration_sec = ntohl(nfr->duration_sec);
159
60
        fr->duration_nsec = ntohl(nfr->duration_nsec);
160
60
        fr->idle_timeout = ntohs(nfr->idle_timeout);
161
60
        fr->hard_timeout = 0;
162
60
        fr->packet_count = ntohll(nfr->packet_count);
163
60
        fr->byte_count = ntohll(nfr->byte_count);
164
60
    } else {
165
0
        OVS_NOT_REACHED();
166
0
    }
167
168
4.60k
    return 0;
169
16.4k
}
170
171
/* Returns 'count' unchanged except that UINT64_MAX becomes 0.
172
 *
173
 * We use this in situations where OVS internally uses UINT64_MAX to mean
174
 * "value unknown" but OpenFlow 1.0 does not define any unknown value. */
175
static uint64_t
176
unknown_to_zero(uint64_t count)
177
0
{
178
0
    return count != UINT64_MAX ? count : 0;
179
0
}
180
181
/* Converts abstract ofputil_flow_removed 'fr' into an OFPT_FLOW_REMOVED or
182
 * NXT_FLOW_REMOVED message 'oh' according to 'protocol', and returns the
183
 * message. */
184
struct ofpbuf *
185
ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
186
                            enum ofputil_protocol protocol)
187
0
{
188
0
    struct ofpbuf *msg;
189
0
    enum ofp_flow_removed_reason reason = fr->reason;
190
191
0
    if (reason == OFPRR_METER_DELETE && !(protocol & OFPUTIL_P_OF14_UP)) {
192
0
        reason = OFPRR_DELETE;
193
0
    }
194
195
0
    switch (protocol) {
196
0
    case OFPUTIL_P_OF11_STD:
197
0
    case OFPUTIL_P_OF12_OXM:
198
0
    case OFPUTIL_P_OF13_OXM:
199
0
    case OFPUTIL_P_OF14_OXM: {
200
0
        struct ofp12_flow_removed *ofr;
201
202
0
        msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED,
203
0
                               ofputil_protocol_to_ofp_version(protocol),
204
0
                               htonl(0),
205
0
                               ofputil_match_typical_len(protocol));
206
0
        ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
207
0
        ofr->cookie = fr->cookie;
208
0
        ofr->priority = htons(fr->priority);
209
0
        ofr->reason = reason;
210
0
        ofr->table_id = fr->table_id;
211
0
        ofr->duration_sec = htonl(fr->duration_sec);
212
0
        ofr->duration_nsec = htonl(fr->duration_nsec);
213
0
        ofr->idle_timeout = htons(fr->idle_timeout);
214
0
        ofr->hard_timeout = htons(fr->hard_timeout);
215
0
        ofr->packet_count = htonll(fr->packet_count);
216
0
        ofr->byte_count = htonll(fr->byte_count);
217
0
        ofputil_put_ofp11_match(msg, &fr->match, protocol);
218
0
        break;
219
0
    }
220
0
    case OFPUTIL_P_OF15_OXM: {
221
0
        struct ofp15_flow_removed *ofr;
222
223
0
        msg = ofpraw_alloc_xid(OFPRAW_OFPT15_FLOW_REMOVED,
224
0
                               ofputil_protocol_to_ofp_version(protocol),
225
0
                               htonl(0),
226
0
                               ofputil_match_typical_len(protocol));
227
0
        ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
228
0
        ofr->cookie = fr->cookie;
229
0
        ofr->priority = htons(fr->priority);
230
0
        ofr->reason = reason;
231
0
        ofr->table_id = fr->table_id;
232
0
        ofr->idle_timeout = htons(fr->idle_timeout);
233
0
        ofr->hard_timeout = htons(fr->hard_timeout);
234
0
        ofputil_put_ofp11_match(msg, &fr->match, protocol);
235
236
0
        const struct oxs_stats oxs = {
237
0
            .duration_sec = fr->duration_sec,
238
0
            .duration_nsec = fr->duration_nsec,
239
0
            .idle_age = UINT32_MAX,
240
0
            .packet_count = fr->packet_count,
241
0
            .byte_count = fr->byte_count,
242
0
            .flow_count = UINT32_MAX,
243
0
        };
244
0
        oxs_put_stats(msg, &oxs);
245
0
        break;
246
0
    }
247
0
    case OFPUTIL_P_OF10_STD:
248
0
    case OFPUTIL_P_OF10_STD_TID: {
249
0
        struct ofp10_flow_removed *ofr;
250
251
0
        msg = ofpraw_alloc_xid(OFPRAW_OFPT10_FLOW_REMOVED, OFP10_VERSION,
252
0
                               htonl(0), 0);
253
0
        ofr = ofpbuf_put_zeros(msg, sizeof *ofr);
254
0
        ofputil_match_to_ofp10_match(&fr->match, &ofr->match);
255
0
        ofr->cookie = fr->cookie;
256
0
        ofr->priority = htons(fr->priority);
257
0
        ofr->reason = reason;
258
0
        ofr->duration_sec = htonl(fr->duration_sec);
259
0
        ofr->duration_nsec = htonl(fr->duration_nsec);
260
0
        ofr->idle_timeout = htons(fr->idle_timeout);
261
0
        ofr->packet_count = htonll(unknown_to_zero(fr->packet_count));
262
0
        ofr->byte_count = htonll(unknown_to_zero(fr->byte_count));
263
0
        break;
264
0
    }
265
266
0
    case OFPUTIL_P_OF10_NXM:
267
0
    case OFPUTIL_P_OF10_NXM_TID: {
268
0
        struct nx_flow_removed *nfr;
269
0
        int match_len;
270
271
0
        msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_REMOVED, OFP10_VERSION,
272
0
                               htonl(0), NXM_TYPICAL_LEN);
273
0
        ofpbuf_put_zeros(msg, sizeof *nfr);
274
0
        match_len = nx_put_match(msg, &fr->match, 0, 0);
275
276
0
        nfr = msg->msg;
277
0
        nfr->cookie = fr->cookie;
278
0
        nfr->priority = htons(fr->priority);
279
0
        nfr->reason = reason;
280
0
        nfr->table_id = fr->table_id + 1;
281
0
        nfr->duration_sec = htonl(fr->duration_sec);
282
0
        nfr->duration_nsec = htonl(fr->duration_nsec);
283
0
        nfr->idle_timeout = htons(fr->idle_timeout);
284
0
        nfr->match_len = htons(match_len);
285
0
        nfr->packet_count = htonll(fr->packet_count);
286
0
        nfr->byte_count = htonll(fr->byte_count);
287
0
        break;
288
0
    }
289
290
0
    default:
291
0
        OVS_NOT_REACHED();
292
0
    }
293
294
0
    return msg;
295
0
}
296
297
void
298
ofputil_flow_removed_format(struct ds *s,
299
                            const struct ofputil_flow_removed *fr,
300
                            const struct ofputil_port_map *port_map,
301
                            const struct ofputil_table_map *table_map)
302
4.60k
{
303
4.60k
    char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
304
305
4.60k
    ds_put_char(s, ' ');
306
4.60k
    match_format(&fr->match, port_map, s, fr->priority);
307
308
4.60k
    ds_put_format(s, " reason=%s",
309
4.60k
                  ofp_flow_removed_reason_to_string(fr->reason, reasonbuf,
310
4.60k
                                                    sizeof reasonbuf));
311
312
4.60k
    if (fr->table_id != 255) {
313
3.08k
        ds_put_format(s, " table_id=");
314
3.08k
        ofputil_format_table(fr->table_id, table_map, s);
315
3.08k
    }
316
317
4.60k
    if (fr->cookie != htonll(0)) {
318
4.46k
        ds_put_format(s, " cookie:0x%"PRIx64, ntohll(fr->cookie));
319
4.46k
    }
320
4.60k
    ds_put_cstr(s, " duration");
321
4.60k
    ofp_print_duration(s, fr->duration_sec, fr->duration_nsec);
322
4.60k
    ds_put_format(s, " idle%"PRIu16, fr->idle_timeout);
323
4.60k
    if (fr->hard_timeout) {
324
        /* The hard timeout was only added in OF1.2, so only print it if it is
325
         * actually in use to avoid gratuitous change to the formatting. */
326
1.00k
        ds_put_format(s, " hard%"PRIu16, fr->hard_timeout);
327
1.00k
    }
328
4.60k
    ds_put_format(s, " pkts%"PRIu64" bytes%"PRIu64"\n",
329
4.60k
                  fr->packet_count, fr->byte_count);
330
4.60k
}
331
332
static uint16_t
333
nx_to_ofp_flow_monitor_flags(uint16_t flags)
334
5.37k
{
335
5.37k
    uint16_t oxm_flags = 0;
336
337
5.37k
    if (flags & NXFMF_INITIAL) {
338
3.23k
        oxm_flags |= OFPFMF_INITIAL;
339
3.23k
    }
340
5.37k
    if (flags & NXFMF_ADD) {
341
2.69k
        oxm_flags |= OFPFMF_ADD;
342
2.69k
    }
343
5.37k
    if (flags & NXFMF_DELETE) {
344
2.14k
        oxm_flags |= OFPFMF_REMOVED;
345
2.14k
    }
346
5.37k
    if (flags & NXFMF_MODIFY) {
347
3.82k
        oxm_flags |= OFPFMF_MODIFY;
348
3.82k
    }
349
5.37k
    if (flags & NXFMF_ACTIONS) {
350
1.56k
        oxm_flags |= OFPFMF_INSTRUCTIONS;
351
1.56k
    }
352
5.37k
    if (flags & NXFMF_OWN) {
353
2.27k
        oxm_flags |= OFPFMF_ONLY_OWN;
354
2.27k
    }
355
356
5.37k
    return oxm_flags;
357
5.37k
}
358
359
static uint16_t
360
ofp_to_nx_flow_monitor_flags(uint16_t flags)
361
0
{
362
0
    uint16_t nx_flags = 0;
363
364
0
    if (flags & OFPFMF_INITIAL) {
365
0
        nx_flags |= NXFMF_INITIAL;
366
0
    }
367
0
    if (flags & OFPFMF_ADD) {
368
0
        nx_flags |= NXFMF_ADD;
369
0
    }
370
0
    if (flags & OFPFMF_REMOVED) {
371
0
        nx_flags |= NXFMF_DELETE;
372
0
    }
373
0
    if (flags & OFPFMF_MODIFY) {
374
0
        nx_flags |= NXFMF_MODIFY;
375
0
    }
376
0
    if (flags & OFPFMF_INSTRUCTIONS) {
377
0
        nx_flags |= NXFMF_ACTIONS;
378
0
    }
379
0
    if (flags & OFPFMF_ONLY_OWN) {
380
0
        nx_flags |= NXFMF_OWN;
381
0
    }
382
383
0
    return nx_flags;
384
0
}
385
386
static enum ofp_flow_update_event
387
nx_to_ofp_flow_update_event(enum nx_flow_update_event event)
388
1.82k
{
389
1.82k
    switch (event) {
390
181
    case NXFME_ADDED:
391
181
        return OFPFME_ADDED;
392
437
    case NXFME_DELETED:
393
437
        return OFPFME_REMOVED;
394
415
    case NXFME_MODIFIED:
395
415
        return OFPFME_MODIFIED;
396
789
    case NXFME_ABBREV:
397
789
        return OFPFME_ABBREV;
398
0
     default:
399
0
        OVS_NOT_REACHED();
400
1.82k
    }
401
1.82k
}
402
403
static enum nx_flow_update_event
404
ofp_to_nx_flow_update_event(enum ofp_flow_update_event event)
405
0
{
406
0
    switch (event) {
407
0
    case OFPFME_INITIAL:
408
0
    case OFPFME_ADDED:
409
0
        return NXFME_ADDED;
410
0
    case OFPFME_REMOVED:
411
0
        return NXFME_DELETED;
412
0
    case OFPFME_MODIFIED:
413
0
        return NXFME_MODIFIED;
414
0
    case OFPFME_ABBREV:
415
0
        return NXFME_ABBREV;
416
0
    default:
417
0
    case OFPFME_PAUSED:
418
0
    case OFPFME_RESUMED:
419
0
        OVS_NOT_REACHED();
420
0
    }
421
0
}
422
423

424
/* ofputil_flow_monitor_request */
425
426
/* Converts an NXST_FLOW_MONITOR request in 'msg' into an abstract
427
 * ofputil_flow_monitor_request in 'rq'.
428
 *
429
 * Multiple NXST_FLOW_MONITOR requests can be packed into a single OpenFlow
430
 * message.  Calling this function multiple times for a single 'msg' iterates
431
 * through the requests.  The caller must initially leave 'msg''s layer
432
 * pointers null and not modify them between calls.
433
 *
434
 * Returns 0 if successful, EOF if no requests were left in this 'msg',
435
 * otherwise an OFPERR_* value. */
436
int
437
ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
438
                                    struct ofpbuf *msg)
439
14.7k
{
440
14.7k
    uint16_t flags;
441
14.7k
    enum ofperr error;
442
14.7k
    enum ofpraw raw;
443
444
14.7k
    error = (msg->header ? ofpraw_decode(&raw, msg->header)
445
14.7k
             : ofpraw_pull(&raw, msg));
446
14.7k
    if (error) {
447
0
        return error;
448
0
    }
449
450
14.7k
    if (!msg->size) {
451
2.72k
        return EOF;
452
2.72k
    }
453
454
12.0k
    switch ((int) raw) {
455
8.92k
    case OFPRAW_NXST_FLOW_MONITOR_REQUEST: {
456
8.92k
        struct nx_flow_monitor_request *nfmr;
457
458
8.92k
        nfmr = ofpbuf_try_pull(msg, sizeof *nfmr);
459
8.92k
        if (!nfmr) {
460
1.59k
            VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR request has %"PRIu32" "
461
1.59k
                    "leftover bytes at end", msg->size);
462
1.59k
            return OFPERR_OFPBRC_BAD_LEN;
463
1.59k
        }
464
465
7.33k
        flags = ntohs(nfmr->flags);
466
7.33k
        if (!(flags & (NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY))
467
7.33k
            || flags & ~(NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE
468
6.67k
                         | NXFMF_MODIFY | NXFMF_ACTIONS | NXFMF_OWN)) {
469
1.37k
            VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR has bad flags %#"PRIx16,
470
1.37k
                         flags);
471
1.37k
            return OFPERR_OFPMOFC_BAD_FLAGS;
472
1.37k
        }
473
474
5.95k
        if (!is_all_zeros(nfmr->zeros, sizeof nfmr->zeros)) {
475
581
            return OFPERR_NXBRC_MUST_BE_ZERO;
476
581
        }
477
478
5.37k
        rq->id = ntohl(nfmr->id);
479
5.37k
        rq->command = OFPFMC_ADD;
480
5.37k
        rq->flags = nx_to_ofp_flow_monitor_flags(flags);
481
5.37k
        rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
482
5.37k
        rq->table_id = nfmr->table_id;
483
5.37k
        rq->out_group = OFPG_ANY;
484
485
5.37k
        return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL,
486
5.37k
                NULL, false, NULL, NULL);
487
5.95k
    }
488
0
    case OFPRAW_ONFST13_FLOW_MONITOR_REQUEST: {
489
0
        struct onf_flow_monitor_request *ofmr;
490
491
0
        ofmr = ofpbuf_try_pull(msg, sizeof *ofmr);
492
0
        if (!ofmr) {
493
0
            VLOG_WARN_RL(&rl, "ONFST_FLOW_MONITOR request has %"PRIu32" "
494
0
                         "leftover bytes at end", msg->size);
495
0
            return OFPERR_OFPBRC_BAD_LEN;
496
0
        }
497
498
0
        flags = ntohs(ofmr->flags);
499
0
        if (!(flags & (ONFFMF_ADD | ONFFMF_DELETE | ONFFMF_MODIFY))
500
0
            || flags & ~(ONFFMF_INITIAL | ONFFMF_ADD | ONFFMF_DELETE
501
0
                         | ONFFMF_MODIFY | ONFFMF_ACTIONS | ONFFMF_OWN)) {
502
0
            VLOG_WARN_RL(&rl, "ONFST_FLOW_MONITOR has bad flags %#"PRIx16,
503
0
                         flags);
504
0
            return OFPERR_OFPMOFC_BAD_FLAGS;
505
0
        }
506
507
0
        if (!is_all_zeros(ofmr->zeros, sizeof ofmr->zeros)) {
508
0
            return OFPERR_NXBRC_MUST_BE_ZERO;
509
0
        }
510
511
0
        rq->id = ntohl(ofmr->id);
512
0
        rq->command = OFPFMC_ADD;
513
0
        rq->flags = nx_to_ofp_flow_monitor_flags(flags);
514
0
        error = ofputil_port_from_ofp11(ofmr->out_port, &rq->out_port);
515
0
        if (error) {
516
0
            return error;
517
0
        }
518
0
        rq->table_id = ofmr->table_id;
519
0
        rq->out_group = OFPG_ANY;
520
521
0
        return ofputil_pull_ofp11_match(msg, NULL, NULL, &rq->match, NULL);
522
0
    }
523
3.12k
    case OFPRAW_OFPST14_FLOW_MONITOR_REQUEST: {
524
3.12k
        struct ofp14_flow_monitor_request *ofmr;
525
526
3.12k
        ofmr = ofpbuf_try_pull(msg, sizeof *ofmr);
527
3.12k
        if (!ofmr) {
528
77
            VLOG_WARN_RL(&rl, "OFPST_FLOW_MONITOR request has %"PRIu32" "
529
77
                    "leftover bytes at end", msg->size);
530
77
            return OFPERR_OFPBRC_BAD_LEN;
531
77
        }
532
533
3.04k
        flags = ntohs(ofmr->flags);
534
3.04k
        rq->id = ntohl(ofmr->monitor_id);
535
3.04k
        rq->command = ofmr->command;
536
537
3.04k
        if (ofmr->command == OFPFMC_DELETE) {
538
106
            return ofputil_pull_ofp11_match(msg, NULL, NULL, &rq->match, NULL);
539
106
        }
540
541
2.93k
        if (!(flags & (OFPFMF_ADD | OFPFMF_REMOVED | OFPFMF_MODIFY))
542
2.93k
                || flags & ~(OFPFMF_INITIAL | OFPFMF_ADD | OFPFMF_REMOVED
543
2.81k
                    | OFPFMF_MODIFY | OFPFMF_INSTRUCTIONS | OFPFMF_ONLY_OWN)) {
544
236
            VLOG_WARN_RL(&rl, "OFPST_FLOW_MONITOR has bad flags %#"PRIx16,
545
236
                         flags);
546
236
            return OFPERR_OFPMOFC_BAD_FLAGS;
547
236
        }
548
549
2.70k
        rq->command = ofmr->command;
550
2.70k
        rq->flags = flags;
551
2.70k
        error = ofputil_port_from_ofp11(ofmr->out_port, &rq->out_port);
552
2.70k
        if (error) {
553
328
            return error;
554
328
        }
555
2.37k
        rq->out_group = ntohl(ofmr->out_group);
556
2.37k
        rq->table_id = ofmr->table_id;
557
558
2.37k
        return ofputil_pull_ofp11_match(msg, NULL, NULL, &rq->match, NULL);
559
2.70k
    }
560
0
    default:
561
0
        OVS_NOT_REACHED();
562
12.0k
    }
563
12.0k
}
564
565
void
566
ofputil_append_flow_monitor_request(
567
    const struct ofputil_flow_monitor_request *rq, struct ofpbuf *msg,
568
    enum ofputil_protocol protocol)
569
0
{
570
0
    size_t start_ofs;
571
0
    int match_len;
572
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
573
574
0
    if (!msg->size) {
575
0
        switch (version) {
576
0
        case OFP10_VERSION:
577
0
        case OFP11_VERSION:
578
0
        case OFP12_VERSION: {
579
0
            struct nx_flow_monitor_request *nfmr;
580
581
0
            if (!msg->size) {
582
0
                ofpraw_put(OFPRAW_NXST_FLOW_MONITOR_REQUEST, version, msg);
583
0
            }
584
585
0
            start_ofs = msg->size;
586
0
            ofpbuf_put_zeros(msg, sizeof *nfmr);
587
0
            match_len = nx_put_match(msg, &rq->match, htonll(0), htonll(0));
588
589
0
            nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
590
0
            nfmr->id = htonl(rq->id);
591
0
            nfmr->flags = htons(ofp_to_nx_flow_monitor_flags(rq->flags));
592
0
            nfmr->out_port = htons(ofp_to_u16(rq->out_port));
593
0
            nfmr->match_len = htons(match_len);
594
0
            nfmr->table_id = rq->table_id;
595
0
            break;
596
0
        }
597
0
        case OFP13_VERSION: {
598
0
            struct onf_flow_monitor_request *ofmr;
599
600
0
            if (!msg->size) {
601
0
                ofpraw_put(OFPRAW_ONFST13_FLOW_MONITOR_REQUEST, version, msg);
602
0
            }
603
604
0
            start_ofs = msg->size;
605
0
            ofpbuf_put_zeros(msg, sizeof *ofmr);
606
0
            match_len = oxm_put_match(msg, &rq->match, version);
607
608
0
            ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
609
0
            ofmr->id = htonl(rq->id);
610
0
            ofmr->flags = htons(ofp_to_nx_flow_monitor_flags(rq->flags));
611
0
            ofmr->match_len = htons(match_len);
612
0
            ofmr->out_port = ofputil_port_to_ofp11(rq->out_port);
613
0
            ofmr->table_id = rq->table_id;
614
0
            break;
615
0
        }
616
0
        case OFP14_VERSION:
617
0
        case OFP15_VERSION: {
618
0
            struct ofp14_flow_monitor_request *ofmr;
619
620
0
            if (!msg->size) {
621
0
                ofpraw_put(OFPRAW_OFPST14_FLOW_MONITOR_REQUEST, version, msg);
622
0
            }
623
624
0
            start_ofs = msg->size;
625
0
            ofpbuf_put_zeros(msg, sizeof *ofmr);
626
0
            oxm_put_match(msg, &rq->match, version);
627
628
0
            ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
629
0
            ofmr->monitor_id = htonl(rq->id);
630
0
            ofmr->command = OFPFMC_ADD;
631
0
            ofmr->out_port = ofputil_port_to_ofp11(rq->out_port);
632
0
            ofmr->out_group = htonl(rq->out_group);
633
0
            ofmr->flags = htons(rq->flags);
634
0
            ofmr->table_id = rq->table_id;
635
0
            break;
636
0
        }
637
0
        default:
638
0
            OVS_NOT_REACHED();
639
0
        }
640
0
    }
641
0
}
642
643
static const char *
644
ofp_flow_monitor_flags_to_name(uint32_t bit)
645
24.8k
{
646
24.8k
    enum ofp14_flow_monitor_flags fmf = bit;
647
648
24.8k
    switch (fmf) {
649
5.01k
    case OFPFMF_INITIAL: return "initial";
650
2.85k
    case OFPFMF_ADD: return "add";
651
3.98k
    case OFPFMF_REMOVED: return "delete";
652
5.59k
    case OFPFMF_MODIFY: return "modify";
653
3.37k
    case OFPFMF_INSTRUCTIONS: return "actions";
654
0
    case OFPFMF_NO_ABBREV: return "no-abbrev";
655
4.00k
    case OFPFMF_ONLY_OWN: return "own";
656
24.8k
    }
657
658
0
    return NULL;
659
24.8k
}
660
661
static const char *
662
ofp_flow_monitor_command_to_string(enum ofp14_flow_monitor_command command)
663
82
{
664
82
    switch (command) {
665
0
    case OFPFMC_ADD: return "add";
666
0
    case OFPFMC_MODIFY: return "modify";
667
82
    case OFPFMC_DELETE: return "delete";
668
0
    default:
669
0
        OVS_NOT_REACHED();
670
82
    }
671
82
}
672
673
void
674
ofputil_flow_monitor_request_format(
675
    struct ds *s, const struct ofputil_flow_monitor_request *request,
676
    const struct ofputil_port_map *port_map,
677
    const struct ofputil_table_map *table_map)
678
7.32k
{
679
7.32k
    if (request->command == OFPFMC_DELETE) {
680
82
        ds_put_format(s, "\n id=%"PRIu32" command=%s", request->id,
681
82
                      ofp_flow_monitor_command_to_string(request->command));
682
82
        return;
683
82
    }
684
7.24k
    ds_put_format(s, "\n id=%"PRIu32" flags=", request->id);
685
7.24k
    ofp_print_bit_names(s, request->flags,
686
7.24k
                        ofp_flow_monitor_flags_to_name, ',');
687
688
7.24k
    if (request->out_port != OFPP_NONE) {
689
7.18k
        ds_put_cstr(s, " out_port=");
690
7.18k
        ofputil_format_port(request->out_port, port_map, s);
691
7.18k
    }
692
693
7.24k
    if (request->out_group && (request->out_group != OFPG_ANY)) {
694
1.87k
        ds_put_format(s, " out_group=%d", request->out_group);
695
1.87k
    }
696
697
7.24k
    if (request->table_id != 0xff) {
698
7.04k
        ds_put_format(s, " table=");
699
7.04k
        ofputil_format_table(request->table_id, table_map, s);
700
7.04k
    }
701
702
7.24k
    if (request->command != OFPFMC_DELETE) {
703
7.24k
        ds_put_char(s, ' ');
704
7.24k
        match_format(&request->match, port_map, s, OFP_DEFAULT_PRIORITY);
705
7.24k
        ds_chomp(s, ' ');
706
7.24k
    }
707
7.24k
}
708
709
static char * OVS_WARN_UNUSED_RESULT
710
parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
711
                             const char *str_,
712
                             const struct ofputil_port_map *port_map,
713
                             const struct ofputil_table_map *table_map,
714
                             char *string,
715
                             enum ofputil_protocol *usable_protocols)
716
0
{
717
0
    static atomic_count id = ATOMIC_COUNT_INIT(0);
718
0
    char *name, *value;
719
720
0
    fmr->id = atomic_count_inc(&id);
721
722
0
    fmr->flags = (OFPFMF_INITIAL | OFPFMF_ADD | OFPFMF_REMOVED | OFPFMF_MODIFY
723
0
                  | OFPFMF_ONLY_OWN | OFPFMF_INSTRUCTIONS);
724
0
    fmr->out_port = OFPP_NONE;
725
0
    fmr->out_group = OFPG_ANY;
726
0
    fmr->table_id = 0xff;
727
0
    match_init_catchall(&fmr->match);
728
729
0
    *usable_protocols = OFPUTIL_P_ANY;
730
0
    while (ofputil_parse_key_value(&string, &name, &value)) {
731
0
        const struct ofp_protocol *p;
732
0
        char *error = NULL;
733
734
0
        if (!strcmp(name, "!initial")) {
735
0
            fmr->flags &= ~OFPFMF_INITIAL;
736
0
        } else if (!strcmp(name, "!add")) {
737
0
            fmr->flags &= ~OFPFMF_ADD;
738
0
        } else if (!strcmp(name, "!delete")) {
739
0
            fmr->flags &= ~OFPFMF_REMOVED;
740
0
        } else if (!strcmp(name, "!modify")) {
741
0
            fmr->flags &= ~OFPFMF_MODIFY;
742
0
        } else if (!strcmp(name, "!actions")) {
743
0
            fmr->flags &= ~OFPFMF_INSTRUCTIONS;
744
0
        } else if (!strcmp(name, "!abbrev")) {
745
0
            fmr->flags &= ~OFPFMF_NO_ABBREV;
746
0
        } else if (!strcmp(name, "!own")) {
747
0
            fmr->flags &= ~OFPFMF_ONLY_OWN;
748
0
        } else if (ofp_parse_protocol(name, &p)) {
749
0
            match_set_dl_type(&fmr->match, htons(p->dl_type));
750
0
            if (p->nw_proto) {
751
0
                match_set_nw_proto(&fmr->match, p->nw_proto);
752
0
            }
753
0
        } else if (mf_from_name(name)) {
754
0
            error = ofp_parse_field(mf_from_name(name), value, port_map,
755
0
                                    &fmr->match, usable_protocols);
756
0
            if (!error && !(*usable_protocols & OFPUTIL_P_OF10_ANY)) {
757
0
                return xasprintf("%s: match field is not supported for "
758
0
                                 "flow monitor", name);
759
0
            }
760
0
        } else {
761
0
            if (!*value) {
762
0
                return xasprintf("%s: field %s missing value", str_, name);
763
0
            }
764
765
0
            if (!strcmp(name, "table")) {
766
0
                if (!ofputil_table_from_string(value, table_map,
767
0
                                               &fmr->table_id)) {
768
0
                    error = xasprintf("unknown table \"%s\"", value);
769
0
                }
770
0
            } else if (!strcmp(name, "out_port")) {
771
0
                fmr->out_port = u16_to_ofp(atoi(value));
772
0
            } else if (!strcmp(name, "out_group")) {
773
0
                fmr->out_group = atoi(value);
774
0
            } else {
775
0
                return xasprintf("%s: unknown keyword %s", str_, name);
776
0
            }
777
0
        }
778
779
0
        if (error) {
780
0
            return error;
781
0
        }
782
0
    }
783
0
    return NULL;
784
0
}
785
786
/* Convert 'str_' (as described in the documentation for the "monitor" command
787
 * in the ovs-ofctl man page) into 'fmr'.
788
 *
789
 * Returns NULL if successful, otherwise a malloc()'d string describing the
790
 * error.  The caller is responsible for freeing the returned string. */
791
char * OVS_WARN_UNUSED_RESULT
792
parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
793
                           const char *str_,
794
                           const struct ofputil_port_map *port_map,
795
                           const struct ofputil_table_map *table_map,
796
                           enum ofputil_protocol *usable_protocols)
797
0
{
798
0
    char *string = xstrdup(str_);
799
0
    char *error = parse_flow_monitor_request__(fmr, str_, port_map, table_map,
800
0
                                               string, usable_protocols);
801
0
    free(string);
802
0
    return error;
803
0
}
804
805
/* Converts an NXST_FLOW_MONITOR reply (also known as a flow update) in 'msg'
806
 * into an abstract ofputil_flow_update in 'update'.  The caller must have
807
 * initialized update->match to point to space allocated for a match.
808
 *
809
 * Uses 'ofpacts' to store the abstract OFPACT_* version of the update's
810
 * actions (except for NXFME_ABBREV, which never includes actions).  The caller
811
 * must initialize 'ofpacts' and retains ownership of it.  'update->ofpacts'
812
 * will point into the 'ofpacts' buffer.
813
 *
814
 * Multiple flow updates can be packed into a single OpenFlow message.  Calling
815
 * this function multiple times for a single 'msg' iterates through the
816
 * updates.  The caller must initially leave 'msg''s layer pointers null and
817
 * not modify them between calls.
818
 *
819
 * Returns 0 if successful, EOF if no updates were left in this 'msg',
820
 * otherwise an OFPERR_* value. */
821
int
822
ofputil_decode_flow_update(struct ofputil_flow_update *update,
823
                           struct ofpbuf *msg, struct ofpbuf *ofpacts)
824
52.1k
{
825
52.1k
    unsigned int length;
826
52.1k
    struct ofp_header *oh;
827
52.1k
    enum ofperr error;
828
52.1k
    enum ofpraw raw;
829
830
52.1k
    if (!msg->header) {
831
31.4k
        ofpraw_pull_assert(msg);
832
31.4k
    }
833
834
52.1k
    error = ofpraw_decode(&raw, msg->header);
835
52.1k
    if (error) {
836
0
        return error;
837
0
    }
838
839
52.1k
    ofpbuf_clear(ofpacts);
840
52.1k
    if (!msg->size) {
841
6.73k
        return EOF;
842
6.73k
    }
843
844
45.4k
    oh = msg->header;
845
846
45.4k
    switch ((int) raw) {
847
0
    case OFPRAW_ONFST13_FLOW_MONITOR_REPLY:
848
3.96k
    case OFPRAW_NXST_FLOW_MONITOR_REPLY: {
849
3.96k
        struct nx_flow_update_header *nfuh;
850
3.96k
        enum nx_flow_update_event nx_event;
851
852
3.96k
        if (msg->size < sizeof(struct nx_flow_update_header)) {
853
0
            goto bad_len;
854
0
        }
855
856
3.96k
        nfuh = msg->data;
857
3.96k
        length = ntohs(nfuh->length);
858
3.96k
        if (length > msg->size || length % 8) {
859
326
            goto bad_len;
860
326
        }
861
862
3.63k
        nx_event = ntohs(nfuh->event);
863
3.63k
        if (nx_event == NXFME_ABBREV) {
864
800
            struct nx_flow_update_abbrev *nfua;
865
866
800
            if (length != sizeof *nfua) {
867
11
                goto bad_len;
868
11
            }
869
870
789
            nfua = ofpbuf_pull(msg, sizeof *nfua);
871
789
            update->xid = nfua->xid;
872
2.83k
        } else if (nx_event == NXFME_ADDED
873
2.83k
                   || nx_event == NXFME_DELETED
874
2.83k
                   || nx_event == NXFME_MODIFIED) {
875
2.15k
            struct nx_flow_update_full *nfuf;
876
2.15k
            unsigned int actions_len;
877
2.15k
            unsigned int match_len;
878
879
2.15k
            if (length < sizeof *nfuf) {
880
921
                goto bad_len;
881
921
            }
882
883
1.23k
            nfuf = ofpbuf_pull(msg, sizeof *nfuf);
884
1.23k
            match_len = ntohs(nfuf->match_len);
885
1.23k
            if (sizeof *nfuf + match_len > length) {
886
64
                goto bad_len;
887
64
            }
888
889
1.17k
            update->reason = ntohs(nfuf->reason);
890
1.17k
            update->idle_timeout = ntohs(nfuf->idle_timeout);
891
1.17k
            update->hard_timeout = ntohs(nfuf->hard_timeout);
892
1.17k
            update->table_id = nfuf->table_id;
893
1.17k
            update->cookie = nfuf->cookie;
894
1.17k
            update->priority = ntohs(nfuf->priority);
895
896
1.17k
            if (raw == OFPRAW_ONFST13_FLOW_MONITOR_REPLY) {
897
0
                uint16_t padded_match_len = 0;
898
0
                unsigned int instructions_len;
899
900
0
                error = ofputil_pull_ofp11_match(
901
0
                    msg, NULL, NULL, &update->match, &padded_match_len);
902
0
                if (error) {
903
0
                    return error;
904
0
                }
905
906
0
                instructions_len = length - sizeof *nfuf - padded_match_len;
907
0
                error = ofpacts_pull_openflow_instructions(
908
0
                    msg, instructions_len, oh->version, NULL, NULL, ofpacts);
909
0
                if (error) {
910
0
                    return error;
911
0
                }
912
1.17k
            } else {
913
1.17k
                error = nx_pull_match(msg, match_len, &update->match, NULL,
914
1.17k
                                      NULL, false, NULL, NULL);
915
1.17k
                if (error) {
916
107
                    return error;
917
107
                }
918
919
1.06k
                actions_len = length - sizeof *nfuf - ROUND_UP(match_len, 8);
920
1.06k
                error = ofpacts_pull_openflow_actions(
921
1.06k
                    msg, actions_len, oh->version, NULL, NULL, ofpacts);
922
1.06k
                if (error) {
923
34
                    return error;
924
34
                }
925
1.06k
            }
926
927
1.03k
            update->ofpacts = ofpacts->data;
928
1.03k
            update->ofpacts_len = ofpacts->size;
929
1.03k
        } else {
930
676
            VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has bad event %"PRIu16,
931
676
                         ntohs(nfuh->event));
932
676
            return OFPERR_NXBRC_FM_BAD_EVENT;
933
676
        }
934
935
1.82k
        update->event = nx_to_ofp_flow_update_event(nx_event);
936
1.82k
        return 0;
937
3.63k
    }
938
41.4k
    case OFPRAW_OFPST14_FLOW_MONITOR_REPLY: {
939
41.4k
        struct ofp_flow_update_header *ofuh;
940
41.4k
        uint16_t padded_match_len = 0;
941
942
41.4k
        if (msg->size < sizeof(struct ofp_flow_update_header)) {
943
0
            goto bad_len;
944
0
        }
945
946
41.4k
        ofuh = msg->data;
947
41.4k
        update->event = ntohs(ofuh->event);
948
41.4k
        length = ntohs(ofuh->length);
949
41.4k
        if (length > msg->size || length % 8) {
950
13.0k
            goto bad_len;
951
13.0k
        }
952
953
28.4k
        if (update->event == OFPFME_ABBREV) {
954
7.21k
            struct ofp_flow_update_abbrev *ofua;
955
956
7.21k
            if (length != sizeof *ofua) {
957
24
                goto bad_len;
958
24
            }
959
960
7.19k
            ofua = ofpbuf_pull(msg, sizeof *ofua);
961
7.19k
            update->xid = ofua->xid;
962
7.19k
            return 0;
963
21.2k
        } else if (update->event == OFPFME_PAUSED
964
21.2k
                   || update->event == OFPFME_RESUMED) {
965
12.1k
            struct ofp_flow_update_paused *ofup OVS_UNUSED;
966
967
12.1k
            if (length != sizeof *ofup) {
968
2.22k
                goto bad_len;
969
2.22k
            }
970
971
9.96k
            ofup = ofpbuf_pull(msg, sizeof *ofup);
972
9.96k
            return 0;
973
12.1k
        } else if (update->event == OFPFME_INITIAL
974
9.03k
                   || update->event == OFPFME_ADDED
975
9.03k
                   || update->event == OFPFME_REMOVED
976
9.03k
                   || update->event == OFPFME_MODIFIED) {
977
8.35k
            struct ofp_flow_update_full *ofuf;
978
8.35k
            unsigned int instructions_len;
979
980
8.35k
            if (length < sizeof *ofuf) {
981
1.27k
                goto bad_len;
982
1.27k
            }
983
984
7.08k
            ofuf = ofpbuf_pull(msg, sizeof *ofuf);
985
7.08k
            if (sizeof *ofuf > length) {
986
0
                goto bad_len;
987
0
            }
988
989
7.08k
            update->reason = ofuf->reason;
990
7.08k
            update->idle_timeout = ntohs(ofuf->idle_timeout);
991
7.08k
            update->hard_timeout = ntohs(ofuf->hard_timeout);
992
7.08k
            update->table_id = ofuf->table_id;
993
7.08k
            update->cookie = ofuf->cookie;
994
7.08k
            update->priority = ntohs(ofuf->priority);
995
996
7.08k
            error = ofputil_pull_ofp11_match(
997
7.08k
                msg, NULL, NULL, &update->match, &padded_match_len);
998
7.08k
            if (error) {
999
994
                return error;
1000
994
            }
1001
1002
6.08k
            instructions_len = length - sizeof *ofuf - padded_match_len;
1003
6.08k
            error = ofpacts_pull_openflow_instructions(
1004
6.08k
                msg, instructions_len, oh->version, NULL, NULL, ofpacts);
1005
6.08k
            if (error) {
1006
4.36k
                return error;
1007
4.36k
            }
1008
1009
1.72k
            update->ofpacts = ofpacts->data;
1010
1.72k
            update->ofpacts_len = ofpacts->size;
1011
1.72k
            return 0;
1012
6.08k
        } else {
1013
686
            VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has bad event %"PRIu16,
1014
686
                         ntohs(ofuh->event));
1015
686
            return OFPERR_NXBRC_FM_BAD_EVENT;
1016
686
        }
1017
28.4k
    }
1018
0
    default:
1019
0
        OVS_NOT_REACHED();
1020
45.4k
    }
1021
17.8k
bad_len:
1022
17.8k
    VLOG_WARN_RL(&rl, "%s has %"PRIu32" leftover bytes at end",
1023
17.8k
                 ofpraw_get_name(raw), msg->size);
1024
17.8k
    return OFPERR_OFPBRC_BAD_LEN;
1025
45.4k
}
1026
1027
uint32_t
1028
ofputil_decode_flow_monitor_cancel(const struct ofp_header *oh)
1029
44
{
1030
44
    enum ofperr error;
1031
44
    enum ofpraw raw;
1032
1033
44
    error = ofpraw_decode(&raw, oh);
1034
44
    if (error) {
1035
0
        return error;
1036
0
    }
1037
1038
44
    switch ((int) raw) {
1039
0
    case OFPRAW_ONFT13_FLOW_MONITOR_CANCEL:
1040
44
    case OFPRAW_NXT_FLOW_MONITOR_CANCEL: {
1041
44
        const struct nx_flow_monitor_cancel *cancel = ofpmsg_body(oh);
1042
44
        return ntohl(cancel->id);
1043
0
    }
1044
0
    default:
1045
0
        OVS_NOT_REACHED();
1046
44
    }
1047
44
}
1048
1049
struct ofpbuf *
1050
ofputil_encode_flow_monitor_cancel(uint32_t id, enum ofputil_protocol protocol)
1051
0
{
1052
0
    struct nx_flow_monitor_cancel *nfmc;
1053
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
1054
0
    struct ofpbuf *msg;
1055
1056
0
    switch (version) {
1057
0
    case OFP10_VERSION:
1058
0
    case OFP11_VERSION:
1059
0
    case OFP12_VERSION:
1060
0
    case OFP13_VERSION: {
1061
0
        if (version == OFP13_VERSION) {
1062
0
            msg = ofpraw_alloc(OFPRAW_ONFT13_FLOW_MONITOR_CANCEL, version, 0);
1063
0
        } else {
1064
0
            msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MONITOR_CANCEL, version, 0);
1065
0
        }
1066
0
        nfmc = ofpbuf_put_uninit(msg, sizeof *nfmc);
1067
0
        nfmc->id = htonl(id);
1068
0
        break;
1069
0
    }
1070
0
    case OFP14_VERSION:
1071
0
    case OFP15_VERSION: {
1072
0
        struct ofp14_flow_monitor_request *ofmr;
1073
1074
0
        msg = ofpbuf_new(0);
1075
1076
0
        ofpraw_put(OFPRAW_OFPST14_FLOW_MONITOR_REQUEST, version, msg);
1077
1078
0
        size_t start_ofs = msg->size;
1079
0
        ofpbuf_put_zeros(msg, sizeof *ofmr);
1080
1081
0
        ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
1082
0
        ofmr->monitor_id = htonl(id);
1083
0
        ofmr->command = OFPFMC_DELETE;
1084
0
        break;
1085
0
    }
1086
0
    default:
1087
0
        OVS_NOT_REACHED();
1088
0
    }
1089
0
    return msg;
1090
0
}
1091
1092
struct ofpbuf *
1093
ofputil_encode_flow_monitor_pause(enum ofp_flow_update_event command,
1094
                                  enum ofputil_protocol protocol)
1095
0
{
1096
0
    struct ofpbuf *msg;
1097
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
1098
1099
0
    if (!(command == OFPFME_PAUSED || command == OFPFME_RESUMED)) {
1100
0
        OVS_NOT_REACHED();
1101
0
    }
1102
1103
0
    switch (version) {
1104
0
    case OFP10_VERSION:
1105
0
    case OFP11_VERSION:
1106
0
    case OFP12_VERSION:
1107
0
        if (command == OFPFME_PAUSED) {
1108
0
            msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_MONITOR_PAUSED,
1109
0
                                   version, htonl(0), 0);
1110
0
        } else {
1111
0
            msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_MONITOR_RESUMED,
1112
0
                                   version, htonl(0), 0);
1113
0
        }
1114
0
        break;
1115
0
    case OFP13_VERSION:
1116
0
        if (command == OFPFME_PAUSED) {
1117
0
            msg = ofpraw_alloc_xid(OFPRAW_ONFT13_FLOW_MONITOR_PAUSED,
1118
0
                                   version, htonl(0), 0);
1119
0
        } else {
1120
0
            msg = ofpraw_alloc_xid(OFPRAW_ONFT13_FLOW_MONITOR_RESUMED,
1121
0
                                   version, htonl(0), 0);
1122
0
        }
1123
0
        break;
1124
0
    case OFP14_VERSION:
1125
0
    case OFP15_VERSION: {
1126
0
        msg = ofpraw_alloc_xid(OFPRAW_OFPST14_FLOW_MONITOR_REPLY, version,
1127
0
                                                   htonl(0), 1024);
1128
0
        struct ofp_flow_update_header *ofuh;
1129
0
        size_t start_ofs = msg->size;
1130
1131
0
        struct ofp_flow_update_paused *ofup;
1132
1133
0
        ofpbuf_put_zeros(msg, sizeof *ofup);
1134
0
        ofup = ofpbuf_at_assert(msg, start_ofs, sizeof *ofup);
1135
0
        ofup->event = htons(command);
1136
0
        ofup->length = htons(8);
1137
1138
0
        ofuh = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuh);
1139
0
        ofuh->length = htons(msg->size - start_ofs);
1140
0
        ofuh->event = htons(command);
1141
1142
0
        ofpmsg_update_length(msg);
1143
0
        break;
1144
0
    }
1145
0
    default:
1146
0
        OVS_NOT_REACHED();
1147
0
    }
1148
1149
0
    return msg;
1150
0
}
1151
1152
void
1153
ofputil_start_flow_update(struct ovs_list *replies,
1154
                          enum ofputil_protocol protocol)
1155
0
{
1156
0
    struct ofpbuf *msg;
1157
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
1158
1159
0
    switch (version) {
1160
0
    case OFP10_VERSION:
1161
0
    case OFP11_VERSION:
1162
0
    case OFP12_VERSION:
1163
0
        msg = ofpraw_alloc_xid(OFPRAW_NXST_FLOW_MONITOR_REPLY, version,
1164
0
                               htonl(0), 1024);
1165
0
        break;
1166
0
    case OFP13_VERSION:
1167
0
        msg = ofpraw_alloc_xid(OFPRAW_ONFST13_FLOW_MONITOR_REPLY, version,
1168
0
                               htonl(0), 1024);
1169
0
        break;
1170
0
    case OFP14_VERSION:
1171
0
    case OFP15_VERSION:
1172
0
        msg = ofpraw_alloc_xid(OFPRAW_OFPST14_FLOW_MONITOR_REPLY, version,
1173
0
                               htonl(0), 1024);
1174
0
        break;
1175
0
    default:
1176
0
        OVS_NOT_REACHED();
1177
0
    }
1178
1179
0
    ovs_list_init(replies);
1180
0
    ovs_list_push_back(replies, &msg->list_node);
1181
0
}
1182
1183
void
1184
ofputil_append_flow_update(const struct ofputil_flow_update *update,
1185
                           struct ovs_list *replies,
1186
                           const struct tun_table *tun_table)
1187
0
{
1188
0
    struct ofputil_flow_update *update_ =
1189
0
        CONST_CAST(struct ofputil_flow_update *, update);
1190
0
    const struct tun_table *orig_tun_table;
1191
0
    enum ofp_version version = ofpmp_version(replies);
1192
0
    struct ofpbuf *msg;
1193
0
    size_t start_ofs;
1194
1195
0
    orig_tun_table = update->match.flow.tunnel.metadata.tab;
1196
0
    update_->match.flow.tunnel.metadata.tab = tun_table;
1197
1198
0
    msg = ofpbuf_from_list(ovs_list_back(replies));
1199
0
    start_ofs = msg->size;
1200
1201
0
    switch (version) {
1202
0
        case OFP10_VERSION:
1203
0
        case OFP11_VERSION:
1204
0
        case OFP12_VERSION:
1205
0
        case OFP13_VERSION: {
1206
0
             struct nx_flow_update_header *nfuh;
1207
1208
0
            if (update->event == OFPFME_ABBREV) {
1209
0
                struct nx_flow_update_abbrev *nfua;
1210
1211
0
                nfua = ofpbuf_put_zeros(msg, sizeof *nfua);
1212
0
                nfua->xid = update->xid;
1213
0
            } else {
1214
0
                struct nx_flow_update_full *nfuf;
1215
0
                int match_len;
1216
1217
0
                ofpbuf_put_zeros(msg, sizeof *nfuf);
1218
0
                if (version == OFP13_VERSION) {
1219
0
                    match_len = oxm_put_match(msg, &update->match, version);
1220
0
                    ofpacts_put_openflow_instructions(
1221
0
                        update->ofpacts, update->ofpacts_len, msg, version);
1222
0
                } else {
1223
0
                    match_len = nx_put_match(msg, &update->match,
1224
0
                                             htonll(0), htonll(0));
1225
0
                    ofpacts_put_openflow_actions(
1226
0
                        update->ofpacts, update->ofpacts_len, msg, version);
1227
0
                }
1228
0
                nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
1229
0
                nfuf->reason = htons(update->reason);
1230
0
                nfuf->priority = htons(update->priority);
1231
0
                nfuf->idle_timeout = htons(update->idle_timeout);
1232
0
                nfuf->hard_timeout = htons(update->hard_timeout);
1233
0
                nfuf->match_len = htons(match_len);
1234
0
                nfuf->table_id = update->table_id;
1235
0
                nfuf->cookie = update->cookie;
1236
0
            }
1237
1238
0
            nfuh = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuh);
1239
0
            nfuh->length = htons(msg->size - start_ofs);
1240
0
            nfuh->event = htons(ofp_to_nx_flow_update_event(update->event));
1241
0
            break;
1242
0
        }
1243
0
        case OFP14_VERSION:
1244
0
        case OFP15_VERSION: {
1245
0
            struct ofp_flow_update_header *ofuh;
1246
1247
0
            if (update->event == OFPFME_ABBREV) {
1248
0
                struct ofp_flow_update_abbrev *ofua;
1249
1250
0
                ofua = ofpbuf_put_zeros(msg, sizeof *ofua);
1251
0
                ofua->xid = update->xid;
1252
0
            } else {
1253
0
                struct ofp_flow_update_full *ofuf;
1254
1255
0
                ofpbuf_put_zeros(msg, sizeof *ofuf);
1256
0
                oxm_put_match(msg, &update->match, version);
1257
0
                ofpacts_put_openflow_instructions(update->ofpacts,
1258
0
                                                  update->ofpacts_len,
1259
0
                                                  msg, version);
1260
0
                ofuf = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuf);
1261
0
                ofuf->reason = update->reason;
1262
0
                ofuf->priority = htons(update->priority);
1263
0
                ofuf->idle_timeout = htons(update->idle_timeout);
1264
0
                ofuf->hard_timeout = htons(update->hard_timeout);
1265
0
                ofuf->table_id = update->table_id;
1266
0
                ofuf->cookie = update->cookie;
1267
0
            }
1268
1269
0
            ofuh = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuh);
1270
0
            ofuh->length = htons(msg->size - start_ofs);
1271
0
            ofuh->event = htons(update->event);
1272
0
            break;
1273
0
        }
1274
0
    }
1275
1276
0
    ofpmp_postappend(replies, start_ofs);
1277
0
    update_->match.flow.tunnel.metadata.tab = orig_tun_table;
1278
0
}
1279
1280
void
1281
ofputil_flow_update_format(struct ds *s,
1282
                           const struct ofputil_flow_update *update,
1283
                           const struct ofputil_port_map *port_map,
1284
                           const struct ofputil_table_map *table_map)
1285
20.6k
{
1286
20.6k
    char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
1287
1288
20.6k
    ds_put_cstr(s, "\n event=");
1289
20.6k
    switch (update->event) {
1290
19
    case OFPFME_INITIAL:
1291
19
        ds_put_cstr(s, "INITIAL");
1292
19
        break;
1293
1294
1.76k
    case OFPFME_ADDED:
1295
1.76k
        ds_put_cstr(s, "ADDED");
1296
1.76k
        break;
1297
1298
557
    case OFPFME_REMOVED:
1299
557
        ds_put_format(s, "DELETED reason=%s",
1300
557
                      ofp_flow_removed_reason_to_string(update->reason,
1301
557
                                                        reasonbuf,
1302
557
                                                        sizeof reasonbuf));
1303
557
        break;
1304
1305
417
    case OFPFME_MODIFIED:
1306
417
        ds_put_cstr(s, "MODIFIED");
1307
417
        break;
1308
1309
7.97k
    case OFPFME_ABBREV:
1310
7.97k
        ds_put_format(s, "ABBREV xid=0x%"PRIx32, ntohl(update->xid));
1311
7.97k
        return;
1312
1313
4.54k
    case OFPFME_PAUSED:
1314
4.54k
        ds_put_cstr(s, "PAUSED");
1315
4.54k
        return;
1316
1317
5.41k
    case OFPFME_RESUMED:
1318
5.41k
        ds_put_cstr(s, "RESUMED");
1319
5.41k
        return;
1320
1321
20.6k
    }
1322
1323
2.75k
    ds_put_format(s, " table=");
1324
2.75k
    ofputil_format_table(update->table_id, table_map, s);
1325
2.75k
    if (update->idle_timeout != OFP_FLOW_PERMANENT) {
1326
781
        ds_put_format(s, " idle_timeout=%"PRIu16, update->idle_timeout);
1327
781
    }
1328
2.75k
    if (update->hard_timeout != OFP_FLOW_PERMANENT) {
1329
1.41k
        ds_put_format(s, " hard_timeout=%"PRIu16, update->hard_timeout);
1330
1.41k
    }
1331
2.75k
    ds_put_format(s, " cookie=%#"PRIx64, ntohll(update->cookie));
1332
1333
2.75k
    ds_put_char(s, ' ');
1334
2.75k
    match_format(&update->match, port_map, s, OFP_DEFAULT_PRIORITY);
1335
1336
2.75k
    if (update->ofpacts_len) {
1337
1.61k
        if (s->string[s->length - 1] != ' ') {
1338
1.59k
            ds_put_char(s, ' ');
1339
1.59k
        }
1340
1.61k
        ds_put_cstr(s, "actions=");
1341
1.61k
        struct ofpact_format_params fp = {
1342
1.61k
            .port_map = port_map,
1343
1.61k
            .table_map = table_map,
1344
1.61k
            .s = s,
1345
1.61k
        };
1346
1.61k
        ofpacts_format(update->ofpacts, update->ofpacts_len, &fp);
1347
1.61k
    }
1348
2.75k
}
1349

1350
/* Encodes 'rf' according to 'protocol', and returns the encoded message. */
1351
struct ofpbuf *
1352
ofputil_encode_requestforward(const struct ofputil_requestforward *rf,
1353
                              enum ofputil_protocol protocol)
1354
0
{
1355
0
    enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
1356
0
    enum ofpraw raw_msg_type;
1357
0
    struct ofpbuf *inner;
1358
1359
0
    switch (rf->reason) {
1360
0
    case OFPRFR_GROUP_MOD:
1361
0
        inner = ofputil_encode_group_mod(ofp_version, rf->group_mod,
1362
0
                                         rf->new_buckets, rf->group_existed);
1363
0
        break;
1364
1365
0
    case OFPRFR_METER_MOD:
1366
0
        inner = ofputil_encode_meter_mod(ofp_version, rf->meter_mod);
1367
0
        break;
1368
1369
0
    case OFPRFR_N_REASONS:
1370
0
    default:
1371
0
        OVS_NOT_REACHED();
1372
0
    }
1373
1374
0
    struct ofp_header *inner_oh = inner->data;
1375
0
    inner_oh->xid = rf->xid;
1376
0
    inner_oh->length = htons(inner->size);
1377
1378
0
    if (ofp_version < OFP13_VERSION) {
1379
0
        raw_msg_type = OFPRAW_NXT_REQUESTFORWARD;
1380
0
    } else if (ofp_version == OFP13_VERSION) {
1381
0
        raw_msg_type = OFPRAW_ONFT13_REQUESTFORWARD;
1382
0
    } else {
1383
0
        raw_msg_type = OFPRAW_OFPT14_REQUESTFORWARD;
1384
0
    }
1385
1386
0
    struct ofpbuf *outer = ofpraw_alloc_xid(raw_msg_type, ofp_version,
1387
0
                                            htonl(0), inner->size);
1388
0
    ofpbuf_put(outer, inner->data, inner->size);
1389
0
    ofpbuf_delete(inner);
1390
1391
0
    return outer;
1392
0
}
1393
1394
/* Decodes OFPT_REQUESTFORWARD message 'outer'.  On success, puts the decoded
1395
 * form into '*rf' and returns 0, and the caller is later responsible for
1396
 * freeing the content of 'rf', with ofputil_destroy_requestforward(rf).  On
1397
 * failure, returns an ofperr and '*rf' is indeterminate. */
1398
enum ofperr
1399
ofputil_decode_requestforward(const struct ofp_header *outer,
1400
                              struct ofputil_requestforward *rf)
1401
8.13k
{
1402
8.13k
    rf->new_buckets = NULL;
1403
8.13k
    rf->group_existed = -1;
1404
1405
8.13k
    struct ofpbuf b = ofpbuf_const_initializer(outer, ntohs(outer->length));
1406
1407
    /* Skip past outer message. */
1408
8.13k
    enum ofpraw raw_msg_type = ofpraw_pull_assert(&b);
1409
8.13k
    ovs_assert(raw_msg_type == OFPRAW_OFPT14_REQUESTFORWARD ||
1410
8.13k
               raw_msg_type == OFPRAW_ONFT13_REQUESTFORWARD ||
1411
8.13k
               raw_msg_type == OFPRAW_NXT_REQUESTFORWARD);
1412
1413
    /* Validate inner message. */
1414
8.13k
    if (b.size < sizeof(struct ofp_header)) {
1415
0
        return OFPERR_OFPBFC_MSG_BAD_LEN;
1416
0
    }
1417
8.13k
    const struct ofp_header *inner = b.data;
1418
8.13k
    unsigned int inner_len = ntohs(inner->length);
1419
8.13k
    if (inner_len < sizeof(struct ofp_header) || inner_len > b.size) {
1420
1.09k
        return OFPERR_OFPBFC_MSG_BAD_LEN;
1421
1.09k
    }
1422
7.04k
    if (inner->version != outer->version) {
1423
621
        return OFPERR_OFPBRC_BAD_VERSION;
1424
621
    }
1425
1426
    /* Parse inner message. */
1427
6.42k
    enum ofptype type;
1428
6.42k
    enum ofperr error = ofptype_decode(&type, inner);
1429
6.42k
    if (error) {
1430
80
        return error;
1431
80
    }
1432
1433
6.34k
    rf->xid = inner->xid;
1434
6.34k
    if (type == OFPTYPE_GROUP_MOD) {
1435
1.81k
        rf->reason = OFPRFR_GROUP_MOD;
1436
1.81k
        rf->group_mod = xmalloc(sizeof *rf->group_mod);
1437
1.81k
        error = ofputil_decode_group_mod(inner, rf->group_mod);
1438
1.81k
        if (error) {
1439
746
            free(rf->group_mod);
1440
746
            return error;
1441
746
        }
1442
4.52k
    } else if (type == OFPTYPE_METER_MOD) {
1443
4.10k
        rf->reason = OFPRFR_METER_MOD;
1444
4.10k
        rf->meter_mod = xmalloc(sizeof *rf->meter_mod);
1445
4.10k
        ofpbuf_init(&rf->bands, 64);
1446
4.10k
        error = ofputil_decode_meter_mod(inner, rf->meter_mod, &rf->bands);
1447
4.10k
        if (error) {
1448
866
            free(rf->meter_mod);
1449
866
            ofpbuf_uninit(&rf->bands);
1450
866
            return error;
1451
866
        }
1452
4.10k
    } else {
1453
417
        return OFPERR_OFPBFC_MSG_UNSUP;
1454
417
    }
1455
1456
4.31k
    return 0;
1457
6.34k
}
1458
1459
void
1460
ofputil_format_requestforward(struct ds *string,
1461
                              enum ofp_version ofp_version,
1462
                              const struct ofputil_requestforward *rf,
1463
                              const struct ofputil_port_map *port_map,
1464
                              const struct ofputil_table_map *table_map)
1465
4.31k
{
1466
4.31k
    ds_put_cstr(string, " reason=");
1467
1468
4.31k
    switch (rf->reason) {
1469
1.07k
    case OFPRFR_GROUP_MOD:
1470
1.07k
        ds_put_cstr(string, "group_mod");
1471
1.07k
        ofputil_group_mod_format__(string, ofp_version, rf->group_mod,
1472
1.07k
                                   port_map, table_map);
1473
1.07k
        break;
1474
1475
3.24k
    case OFPRFR_METER_MOD:
1476
3.24k
        ds_put_cstr(string, "meter_mod");
1477
3.24k
        ofputil_format_meter_mod(string, rf->meter_mod);
1478
3.24k
        break;
1479
1480
0
    case OFPRFR_N_REASONS:
1481
0
        OVS_NOT_REACHED();
1482
4.31k
    }
1483
4.31k
}
1484
1485
1486
/* Frees the content of 'rf', which should have been initialized through a
1487
 * successful call to ofputil_decode_requestforward(). */
1488
void
1489
ofputil_destroy_requestforward(struct ofputil_requestforward *rf)
1490
4.31k
{
1491
4.31k
    if (!rf) {
1492
0
        return;
1493
0
    }
1494
1495
4.31k
    switch (rf->reason) {
1496
1.07k
    case OFPRFR_GROUP_MOD:
1497
1.07k
        ofputil_uninit_group_mod(rf->group_mod);
1498
1.07k
        free(rf->group_mod);
1499
        /* 'rf' does not own rf->new_buckets. */
1500
1.07k
        break;
1501
1502
3.24k
    case OFPRFR_METER_MOD:
1503
3.24k
        ofpbuf_uninit(&rf->bands);
1504
3.24k
        free(rf->meter_mod);
1505
3.24k
        break;
1506
1507
0
    case OFPRFR_N_REASONS:
1508
0
        OVS_NOT_REACHED();
1509
4.31k
    }
1510
4.31k
}