Coverage Report

Created: 2025-07-18 06:07

/src/openvswitch/lib/ofp-packet.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-packet.h"
19
#include <string.h>
20
#include "dp-packet.h"
21
#include "nx-match.h"
22
#include "openvswitch/ofp-actions.h"
23
#include "openvswitch/ofp-errors.h"
24
#include "openvswitch/ofp-msgs.h"
25
#include "openvswitch/ofp-parse.h"
26
#include "openvswitch/ofp-print.h"
27
#include "openvswitch/ofp-port.h"
28
#include "openvswitch/ofp-prop.h"
29
#include "openvswitch/ofp-table.h"
30
#include "openvswitch/ofpbuf.h"
31
#include "openvswitch/vlog.h"
32
#include "util.h"
33
#include "uuid.h"
34
35
VLOG_DEFINE_THIS_MODULE(ofp_packet);
36
37
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
38
39
const char *
40
ofputil_packet_in_format_to_string(enum ofputil_packet_in_format format)
41
20
{
42
20
    switch (format) {
43
6
    case OFPUTIL_PACKET_IN_STD:
44
6
        return "standard";
45
11
    case OFPUTIL_PACKET_IN_NXT:
46
11
        return "nxt_packet_in";
47
3
    case OFPUTIL_PACKET_IN_NXT2:
48
3
        return "nxt_packet_in2";
49
0
    default:
50
0
        OVS_NOT_REACHED();
51
20
    }
52
20
}
53
54
int
55
ofputil_packet_in_format_from_string(const char *s)
56
0
{
57
0
    return (!strcmp(s, "standard") || !strcmp(s, "openflow10")
58
0
            ? OFPUTIL_PACKET_IN_STD
59
0
            : !strcmp(s, "nxt_packet_in") || !strcmp(s, "nxm")
60
0
            ? OFPUTIL_PACKET_IN_NXT
61
0
            : !strcmp(s, "nxt_packet_in2")
62
0
            ? OFPUTIL_PACKET_IN_NXT2
63
0
            : -1);
64
0
}
65
66
struct ofpbuf *
67
ofputil_encode_set_packet_in_format(enum ofp_version ofp_version,
68
                                    enum ofputil_packet_in_format format)
69
0
{
70
0
    struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_SET_PACKET_IN_FORMAT,
71
0
                                      ofp_version, 0);
72
0
    ovs_be32 *spif = ofpbuf_put_uninit(msg, sizeof *spif);
73
0
    *spif = htonl(format);
74
75
0
    return msg;
76
0
}
77
78
enum ofperr
79
ofputil_decode_set_packet_in_format(const struct ofp_header *oh,
80
                                    enum ofputil_packet_in_format *format)
81
64
{
82
64
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
83
64
    ovs_assert(ofpraw_pull_assert(&b) == OFPRAW_NXT_SET_PACKET_IN_FORMAT);
84
64
    ovs_be32 *spifp = ofpbuf_pull(&b, sizeof *spifp);
85
64
    uint32_t spif = ntohl(*spifp);
86
87
64
    switch (spif) {
88
6
    case OFPUTIL_PACKET_IN_STD:
89
17
    case OFPUTIL_PACKET_IN_NXT:
90
20
    case OFPUTIL_PACKET_IN_NXT2:
91
20
        *format = spif;
92
20
        return 0;
93
94
44
    default:
95
44
        VLOG_WARN_RL(&rl, "NXT_SET_PACKET_IN_FORMAT message specified invalid "
96
44
                     "packet-in format %"PRIu32, spif);
97
44
        return OFPERR_OFPBRC_EPERM;
98
64
    }
99
64
}
100

101
/* The caller has done basic initialization of '*pin'; the other output
102
 * arguments needs to be initialized. */
103
static enum ofperr
104
decode_nx_packet_in2(const struct ofp_header *oh, bool loose,
105
                     const struct tun_table *tun_table,
106
                     const struct vl_mff_map *vl_mff_map,
107
                     struct ofputil_packet_in *pin,
108
                     size_t *total_len, uint32_t *buffer_id,
109
                     struct ofpbuf *continuation)
110
14.3k
{
111
14.3k
    *total_len = 0;
112
14.3k
    *buffer_id = UINT32_MAX;
113
114
14.3k
    struct ofpbuf properties;
115
14.3k
    ofpbuf_use_const(&properties, oh, ntohs(oh->length));
116
14.3k
    ofpraw_pull_assert(&properties);
117
118
49.7k
    while (properties.size > 0) {
119
38.9k
        struct ofpbuf payload;
120
38.9k
        uint64_t type;
121
122
38.9k
        enum ofperr error = ofpprop_pull(&properties, &payload, &type);
123
38.9k
        if (error) {
124
2.51k
            return error;
125
2.51k
        }
126
127
36.4k
        switch (type) {
128
10.2k
        case NXPINT_PACKET:
129
10.2k
            pin->packet = payload.msg;
130
10.2k
            pin->packet_len = ofpbuf_msgsize(&payload);
131
10.2k
            break;
132
133
3.54k
        case NXPINT_FULL_LEN: {
134
3.54k
            uint32_t u32;
135
3.54k
            error = ofpprop_parse_u32(&payload, &u32);
136
3.54k
            if (!error) {
137
3.47k
                *total_len = u32;
138
3.47k
            }
139
3.54k
            break;
140
0
        }
141
142
2.42k
        case NXPINT_BUFFER_ID:
143
2.42k
            error = ofpprop_parse_u32(&payload, buffer_id);
144
2.42k
            break;
145
146
553
        case NXPINT_TABLE_ID:
147
553
            error = ofpprop_parse_u8(&payload, &pin->table_id);
148
553
            break;
149
150
97
        case NXPINT_COOKIE:
151
97
            error = ofpprop_parse_be64(&payload, &pin->cookie);
152
97
            break;
153
154
110
        case NXPINT_REASON: {
155
110
            uint8_t reason;
156
110
            error = ofpprop_parse_u8(&payload, &reason);
157
110
            if (!error) {
158
17
                pin->reason = reason;
159
17
            }
160
110
            break;
161
0
        }
162
163
5.54k
        case NXPINT_METADATA:
164
5.54k
            error = oxm_decode_match(payload.msg, ofpbuf_msgsize(&payload),
165
5.54k
                                     loose, tun_table, vl_mff_map,
166
5.54k
                                     &pin->flow_metadata);
167
5.54k
            pin->flow_metadata.flow.tunnel.metadata.tab = tun_table;
168
5.54k
            break;
169
170
469
        case NXPINT_USERDATA:
171
469
            pin->userdata = payload.msg;
172
469
            pin->userdata_len = ofpbuf_msgsize(&payload);
173
469
            break;
174
175
7.78k
        case NXPINT_CONTINUATION:
176
7.78k
            if (continuation) {
177
7.78k
                error = ofpprop_parse_nested(&payload, continuation);
178
7.78k
            }
179
7.78k
            break;
180
181
5.63k
        default:
182
5.63k
            error = OFPPROP_UNKNOWN(loose, "NX_PACKET_IN2", type);
183
5.63k
            break;
184
36.4k
        }
185
36.4k
        if (error) {
186
1.00k
            return error;
187
1.00k
        }
188
36.4k
    }
189
190
10.8k
    if (!pin->packet_len) {
191
2.60k
        VLOG_WARN_RL(&rl, "NXT_PACKET_IN2 lacks packet");
192
2.60k
        return OFPERR_OFPBRC_BAD_LEN;
193
8.20k
    } else if (!*total_len) {
194
5.64k
        *total_len = pin->packet_len;
195
5.64k
    } else if (*total_len < pin->packet_len) {
196
773
        VLOG_WARN_RL(&rl, "NXT_PACKET_IN2 claimed full_len < len");
197
773
        return OFPERR_OFPBRC_BAD_LEN;
198
773
    }
199
200
7.43k
    return 0;
201
10.8k
}
202
203
/* Decodes the packet-in message starting at 'oh' into '*pin'.  Populates
204
 * 'pin->packet' and 'pin->packet_len' with the part of the packet actually
205
 * included in the message.  If 'total_lenp' is nonnull, populates
206
 * '*total_lenp' with the original length of the packet (which is larger than
207
 * 'packet->len' if only part of the packet was included).  If 'buffer_idp' is
208
 * nonnull, stores the packet's buffer ID in '*buffer_idp' (UINT32_MAX if it
209
 * was not buffered).
210
 *
211
 * Populates 'continuation', if nonnull, with the continuation data from the
212
 * packet-in (an empty buffer, if 'oh' did not contain continuation data).  The
213
 * format of this data is supposed to be opaque to anything other than
214
 * ovs-vswitchd, so that in any other process the only reasonable use of this
215
 * data is to be copied into an NXT_RESUME message via ofputil_encode_resume().
216
 *
217
 * This function points 'pin->packet' into 'oh', so the caller should not free
218
 * it separately from the original OpenFlow message.  This is also true for
219
 * 'pin->userdata' (which could also end up NULL if there is no userdata).
220
 *
221
 * 'vl_mff_map' is an optional parameter that is used to validate the length
222
 * of variable length mf_fields in 'match'. If it is not provided, the
223
 * default mf_fields with maximum length will be used.
224
 *
225
 * Returns 0 if successful, otherwise an OpenFlow error code. */
226
enum ofperr
227
ofputil_decode_packet_in(const struct ofp_header *oh, bool loose,
228
                         const struct tun_table *tun_table,
229
                         const struct vl_mff_map *vl_mff_map,
230
                         struct ofputil_packet_in *pin,
231
                         size_t *total_lenp, uint32_t *buffer_idp,
232
                         struct ofpbuf *continuation)
233
126k
{
234
126k
    uint32_t buffer_id;
235
126k
    size_t total_len;
236
237
126k
    memset(pin, 0, sizeof *pin);
238
126k
    pin->cookie = OVS_BE64_MAX;
239
126k
    if (continuation) {
240
126k
        ofpbuf_use_const(continuation, NULL, 0);
241
126k
    }
242
243
126k
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
244
126k
    enum ofpraw raw = ofpraw_pull_assert(&b);
245
126k
    if (raw == OFPRAW_OFPT13_PACKET_IN || raw == OFPRAW_OFPT12_PACKET_IN) {
246
72.9k
        const struct ofp12_packet_in *opi = ofpbuf_pull(&b, sizeof *opi);
247
72.9k
        const ovs_be64 *cookie = (raw == OFPRAW_OFPT13_PACKET_IN
248
72.9k
                                  ? ofpbuf_pull(&b, sizeof *cookie)
249
72.9k
                                  : NULL);
250
72.9k
        enum ofperr error = oxm_pull_match_loose(&b, false, tun_table,
251
72.9k
                                                 &pin->flow_metadata);
252
72.9k
        pin->flow_metadata.flow.tunnel.metadata.tab = tun_table;
253
72.9k
        if (error) {
254
35.5k
            return error;
255
35.5k
        }
256
257
37.4k
        if (!ofpbuf_try_pull(&b, 2)) {
258
578
            return OFPERR_OFPBRC_BAD_LEN;
259
578
        }
260
261
36.8k
        pin->reason = opi->reason;
262
36.8k
        pin->table_id = opi->table_id;
263
36.8k
        buffer_id = ntohl(opi->buffer_id);
264
36.8k
        total_len = ntohs(opi->total_len);
265
36.8k
        if (cookie) {
266
1.41k
            pin->cookie = *cookie;
267
1.41k
        }
268
269
36.8k
        pin->packet = b.data;
270
36.8k
        pin->packet_len = b.size;
271
53.7k
    } else if (raw == OFPRAW_OFPT10_PACKET_IN) {
272
28.9k
        const struct ofp10_packet_in *opi;
273
274
28.9k
        opi = ofpbuf_pull(&b, offsetof(struct ofp10_packet_in, data));
275
276
28.9k
        pin->packet = CONST_CAST(uint8_t *, opi->data);
277
28.9k
        pin->packet_len = b.size;
278
279
28.9k
        match_init_catchall(&pin->flow_metadata);
280
28.9k
        match_set_in_port(&pin->flow_metadata,
281
28.9k
                          u16_to_ofp(ntohs(opi->in_port)));
282
28.9k
        pin->reason = opi->reason;
283
28.9k
        buffer_id = ntohl(opi->buffer_id);
284
28.9k
        total_len = ntohs(opi->total_len);
285
28.9k
    } else if (raw == OFPRAW_OFPT11_PACKET_IN) {
286
408
        const struct ofp11_packet_in *opi;
287
408
        ofp_port_t in_port;
288
408
        enum ofperr error;
289
290
408
        opi = ofpbuf_pull(&b, sizeof *opi);
291
292
408
        pin->packet = b.data;
293
408
        pin->packet_len = b.size;
294
295
408
        buffer_id = ntohl(opi->buffer_id);
296
408
        error = ofputil_port_from_ofp11(opi->in_port, &in_port);
297
408
        if (error) {
298
294
            return error;
299
294
        }
300
114
        match_init_catchall(&pin->flow_metadata);
301
114
        match_set_in_port(&pin->flow_metadata, in_port);
302
114
        total_len = ntohs(opi->total_len);
303
114
        pin->reason = opi->reason;
304
114
        pin->table_id = opi->table_id;
305
24.4k
    } else if (raw == OFPRAW_NXT_PACKET_IN) {
306
10.1k
        const struct nx_packet_in *npi;
307
10.1k
        int error;
308
309
10.1k
        npi = ofpbuf_pull(&b, sizeof *npi);
310
10.1k
        error = nx_pull_match_loose(&b, ntohs(npi->match_len),
311
10.1k
                                    &pin->flow_metadata, NULL, NULL, false,
312
10.1k
                                    NULL);
313
10.1k
        if (error) {
314
6.52k
            return error;
315
6.52k
        }
316
317
3.60k
        if (!ofpbuf_try_pull(&b, 2)) {
318
34
            return OFPERR_OFPBRC_BAD_LEN;
319
34
        }
320
321
3.57k
        pin->reason = npi->reason;
322
3.57k
        pin->table_id = npi->table_id;
323
3.57k
        pin->cookie = npi->cookie;
324
325
3.57k
        buffer_id = ntohl(npi->buffer_id);
326
3.57k
        total_len = ntohs(npi->total_len);
327
328
3.57k
        pin->packet = b.data;
329
3.57k
        pin->packet_len = b.size;
330
14.3k
    } else if (raw == OFPRAW_NXT_PACKET_IN2 || raw == OFPRAW_NXT_RESUME) {
331
14.3k
        enum ofperr error = decode_nx_packet_in2(oh, loose, tun_table,
332
14.3k
                                                 vl_mff_map, pin, &total_len,
333
14.3k
                                                 &buffer_id, continuation);
334
14.3k
        if (error) {
335
6.89k
            return error;
336
6.89k
        }
337
14.3k
    } else {
338
0
        OVS_NOT_REACHED();
339
0
    }
340
341
76.9k
    if (total_lenp) {
342
76.9k
        *total_lenp = total_len;
343
76.9k
    }
344
76.9k
    if (buffer_idp) {
345
76.9k
        *buffer_idp = buffer_id;
346
76.9k
    }
347
348
76.9k
    return 0;
349
126k
}
350
351
static int
352
encode_packet_in_reason(enum ofp_packet_in_reason reason,
353
                        enum ofp_version version)
354
0
{
355
0
    switch (reason) {
356
0
    case OFPR_NO_MATCH:
357
0
    case OFPR_ACTION:
358
0
    case OFPR_INVALID_TTL:
359
0
        return reason;
360
361
0
    case OFPR_ACTION_SET:
362
0
    case OFPR_GROUP:
363
0
    case OFPR_PACKET_OUT:
364
0
        return version < OFP14_VERSION ? OFPR_ACTION : reason;
365
366
0
    case OFPR_EXPLICIT_MISS:
367
0
        return version < OFP13_VERSION ? OFPR_ACTION : OFPR_NO_MATCH;
368
369
0
    case OFPR_IMPLICIT_MISS:
370
0
        return OFPR_NO_MATCH;
371
372
0
    case OFPR_N_REASONS:
373
0
    default:
374
0
        OVS_NOT_REACHED();
375
0
    }
376
0
}
377
378
/* Only NXT_PACKET_IN2 (not NXT_RESUME) should include NXCPT_USERDATA, so this
379
 * function omits it.  The caller can add it itself if desired. */
380
static void
381
ofputil_put_packet_in(const struct ofputil_packet_in *pin,
382
                      enum ofp_version version, size_t include_bytes,
383
                      struct ofpbuf *msg)
384
0
{
385
    /* Add packet properties. */
386
0
    ofpprop_put(msg, NXPINT_PACKET, pin->packet, include_bytes);
387
0
    if (include_bytes != pin->packet_len) {
388
0
        ofpprop_put_u32(msg, NXPINT_FULL_LEN, pin->packet_len);
389
0
    }
390
391
    /* Add flow properties. */
392
0
    ofpprop_put_u8(msg, NXPINT_TABLE_ID, pin->table_id);
393
0
    if (pin->cookie != OVS_BE64_MAX) {
394
0
        ofpprop_put_be64(msg, NXPINT_COOKIE, pin->cookie);
395
0
    }
396
397
    /* Add other properties. */
398
0
    ofpprop_put_u8(msg, NXPINT_REASON,
399
0
                   encode_packet_in_reason(pin->reason, version));
400
401
0
    size_t start = ofpprop_start(msg, NXPINT_METADATA);
402
0
    oxm_put_raw(msg, &pin->flow_metadata, version);
403
0
    ofpprop_end(msg, start);
404
0
}
405
406
static void
407
put_actions_property(struct ofpbuf *msg, uint64_t prop_type,
408
                     enum ofp_version version,
409
                     const struct ofpact *actions, size_t actions_len)
410
0
{
411
0
    if (actions_len) {
412
0
        size_t start = ofpprop_start_nested(msg, prop_type);
413
0
        ofpacts_put_openflow_actions(actions, actions_len, msg, version);
414
0
        ofpprop_end(msg, start);
415
0
    }
416
0
}
417
418
enum nx_continuation_prop_type {
419
    NXCPT_BRIDGE = 0x8000,
420
    NXCPT_STACK,
421
    NXCPT_MIRRORS,
422
    NXCPT_CONNTRACKED,
423
    NXCPT_TABLE_ID,
424
    NXCPT_COOKIE,
425
    NXCPT_ACTIONS,
426
    NXCPT_ACTION_SET,
427
    NXCPT_ODP_PORT,
428
};
429
430
/* Only NXT_PACKET_IN2 (not NXT_RESUME) should include NXCPT_USERDATA, so this
431
 * function omits it.  The caller can add it itself if desired. */
432
static void
433
ofputil_put_packet_in_private(const struct ofputil_packet_in_private *pin,
434
                              enum ofp_version version, size_t include_bytes,
435
                              struct ofpbuf *msg)
436
0
{
437
0
    ofputil_put_packet_in(&pin->base, version, include_bytes, msg);
438
439
0
    size_t continuation_ofs = ofpprop_start_nested(msg, NXPINT_CONTINUATION);
440
0
    size_t inner_ofs = msg->size;
441
442
0
    if (!uuid_is_zero(&pin->bridge)) {
443
0
        ofpprop_put_uuid(msg, NXCPT_BRIDGE, &pin->bridge);
444
0
    }
445
446
0
    struct ofpbuf pin_stack;
447
0
    ofpbuf_use_const(&pin_stack, pin->stack, pin->stack_size);
448
449
0
    while (pin_stack.size) {
450
0
        uint8_t len;
451
0
        uint8_t *val = nx_stack_pop(&pin_stack, &len);
452
0
        ofpprop_put(msg, NXCPT_STACK, val, len);
453
0
    }
454
455
0
    if (pin->mirrors) {
456
0
        ofpprop_put_u32(msg, NXCPT_MIRRORS, pin->mirrors);
457
0
    }
458
459
0
    if (pin->conntracked) {
460
0
        ofpprop_put_flag(msg, NXCPT_CONNTRACKED);
461
0
    }
462
463
0
    if (pin->actions_len) {
464
        /* Divide 'pin->actions' into groups that begins with an
465
         * unroll_xlate action.  For each group, emit a NXCPT_TABLE_ID and
466
         * NXCPT_COOKIE property (if either has changed; each is initially
467
         * assumed 0), then a NXCPT_ACTIONS property with the grouped
468
         * actions.
469
         *
470
         * The alternative is to make OFPACT_UNROLL_XLATE public.  We can
471
         * always do that later, since this is a private property. */
472
0
        const struct ofpact *const end = ofpact_end(pin->actions,
473
0
                                                    pin->actions_len);
474
0
        const struct ofpact_unroll_xlate *unroll = NULL;
475
0
        uint8_t table_id = 0;
476
0
        ovs_be64 cookie = 0;
477
478
0
        const struct ofpact *a;
479
0
        for (a = pin->actions; ; a = ofpact_next(a)) {
480
0
            if (a == end || a->type == OFPACT_UNROLL_XLATE) {
481
0
                if (unroll) {
482
0
                    if (table_id != unroll->rule_table_id) {
483
0
                        ofpprop_put_u8(msg, NXCPT_TABLE_ID,
484
0
                                       unroll->rule_table_id);
485
0
                        table_id = unroll->rule_table_id;
486
0
                    }
487
0
                    if (cookie != unroll->rule_cookie) {
488
0
                        ofpprop_put_be64(msg, NXCPT_COOKIE,
489
0
                                         unroll->rule_cookie);
490
0
                        cookie = unroll->rule_cookie;
491
0
                    }
492
0
                }
493
494
0
                const struct ofpact *start
495
0
                    = unroll ? ofpact_next(&unroll->ofpact) : pin->actions;
496
0
                put_actions_property(msg, NXCPT_ACTIONS, version,
497
0
                                     start, (a - start) * sizeof *a);
498
499
0
                if (a == end) {
500
0
                    break;
501
0
                }
502
0
                unroll = ofpact_get_UNROLL_XLATE(a);
503
0
            }
504
0
        }
505
0
    }
506
507
0
    if (pin->action_set_len) {
508
0
        size_t start = ofpprop_start_nested(msg, NXCPT_ACTION_SET);
509
0
        ofpacts_put_openflow_actions(pin->action_set,
510
0
                                     pin->action_set_len, msg, version);
511
0
        ofpprop_end(msg, start);
512
0
    }
513
514
0
    if (pin->odp_port) {
515
0
        ofpprop_put_u32(msg, NXCPT_ODP_PORT, odp_to_u32(pin->odp_port));
516
0
    }
517
518
0
    if (msg->size > inner_ofs) {
519
0
        ofpprop_end(msg, continuation_ofs);
520
0
    } else {
521
0
        msg->size = continuation_ofs;
522
0
    }
523
0
}
524
525
static struct ofpbuf *
526
ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in *pin)
527
0
{
528
0
    struct ofp10_packet_in *opi;
529
0
    struct ofpbuf *msg;
530
531
0
    msg = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION,
532
0
                           htonl(0), pin->packet_len);
533
0
    opi = ofpbuf_put_zeros(msg, offsetof(struct ofp10_packet_in, data));
534
0
    opi->total_len = htons(pin->packet_len);
535
0
    opi->in_port = htons(ofp_to_u16(pin->flow_metadata.flow.in_port.ofp_port));
536
0
    opi->reason = encode_packet_in_reason(pin->reason, OFP10_VERSION);
537
0
    opi->buffer_id = htonl(UINT32_MAX);
538
539
0
    return msg;
540
0
}
541
542
static struct ofpbuf *
543
ofputil_encode_nx_packet_in(const struct ofputil_packet_in *pin,
544
                            enum ofp_version version)
545
0
{
546
0
    struct nx_packet_in *npi;
547
0
    struct ofpbuf *msg;
548
0
    size_t match_len;
549
550
    /* The final argument is just an estimate of the space required. */
551
0
    msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN, version,
552
0
                           htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
553
0
    ofpbuf_put_zeros(msg, sizeof *npi);
554
0
    match_len = nx_put_match(msg, &pin->flow_metadata, 0, 0);
555
0
    ofpbuf_put_zeros(msg, 2);
556
557
0
    npi = msg->msg;
558
0
    npi->buffer_id = htonl(UINT32_MAX);
559
0
    npi->total_len = htons(pin->packet_len);
560
0
    npi->reason = encode_packet_in_reason(pin->reason, version);
561
0
    npi->table_id = pin->table_id;
562
0
    npi->cookie = pin->cookie;
563
0
    npi->match_len = htons(match_len);
564
565
0
    return msg;
566
0
}
567
568
static struct ofpbuf *
569
ofputil_encode_nx_packet_in2(const struct ofputil_packet_in_private *pin,
570
                             enum ofp_version version, size_t include_bytes)
571
0
{
572
    /* 'extra' is just an estimate of the space required. */
573
0
    size_t extra = (pin->base.packet_len
574
0
                    + NXM_TYPICAL_LEN   /* flow_metadata */
575
0
                    + pin->stack_size * 4
576
0
                    + pin->actions_len
577
0
                    + pin->action_set_len
578
0
                    + 256);     /* fudge factor */
579
0
    struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2, version,
580
0
                                          htonl(0), extra);
581
582
0
    ofputil_put_packet_in_private(pin, version, include_bytes, msg);
583
0
    if (pin->base.userdata_len) {
584
0
        ofpprop_put(msg, NXPINT_USERDATA, pin->base.userdata,
585
0
                    pin->base.userdata_len);
586
0
    }
587
588
0
    ofpmsg_update_length(msg);
589
0
    return msg;
590
0
}
591
592
static struct ofpbuf *
593
ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in *pin)
594
0
{
595
0
    struct ofp11_packet_in *opi;
596
0
    struct ofpbuf *msg;
597
598
0
    msg = ofpraw_alloc_xid(OFPRAW_OFPT11_PACKET_IN, OFP11_VERSION,
599
0
                           htonl(0), pin->packet_len);
600
0
    opi = ofpbuf_put_zeros(msg, sizeof *opi);
601
0
    opi->buffer_id = htonl(UINT32_MAX);
602
0
    opi->in_port = ofputil_port_to_ofp11(
603
0
        pin->flow_metadata.flow.in_port.ofp_port);
604
0
    opi->in_phy_port = opi->in_port;
605
0
    opi->total_len = htons(pin->packet_len);
606
0
    opi->reason = encode_packet_in_reason(pin->reason, OFP11_VERSION);
607
0
    opi->table_id = pin->table_id;
608
609
0
    return msg;
610
0
}
611
612
static struct ofpbuf *
613
ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in *pin,
614
                               enum ofp_version version)
615
0
{
616
0
    enum ofpraw raw = (version >= OFP13_VERSION
617
0
                       ? OFPRAW_OFPT13_PACKET_IN
618
0
                       : OFPRAW_OFPT12_PACKET_IN);
619
0
    struct ofpbuf *msg;
620
621
    /* The final argument is just an estimate of the space required. */
622
0
    msg = ofpraw_alloc_xid(raw, version,
623
0
                           htonl(0), NXM_TYPICAL_LEN + 2 + pin->packet_len);
624
625
0
    struct ofp12_packet_in *opi = ofpbuf_put_zeros(msg, sizeof *opi);
626
0
    opi->buffer_id = htonl(UINT32_MAX);
627
0
    opi->total_len = htons(pin->packet_len);
628
0
    opi->reason = encode_packet_in_reason(pin->reason, version);
629
0
    opi->table_id = pin->table_id;
630
631
0
    if (version >= OFP13_VERSION) {
632
0
        ovs_be64 cookie = pin->cookie;
633
0
        ofpbuf_put(msg, &cookie, sizeof cookie);
634
0
    }
635
636
0
    oxm_put_match(msg, &pin->flow_metadata, version);
637
0
    ofpbuf_put_zeros(msg, 2);
638
639
0
    return msg;
640
0
}
641
642
/* Converts abstract ofputil_packet_in_private 'pin' into a PACKET_IN message
643
 * for 'protocol', using the packet-in format specified by 'format'.
644
 *
645
 * This function is really meant only for use by ovs-vswitchd.  To any other
646
 * code, the "continuation" data, i.e. the data that is in struct
647
 * ofputil_packet_in_private but not in struct ofputil_packet_in, is supposed
648
 * to be opaque (and it might change from one OVS version to another).  Thus,
649
 * if any other code wants to encode a packet-in, it should use a non-"private"
650
 * version of this function.  (Such a version doesn't currently exist because
651
 * only ovs-vswitchd currently wants to encode packet-ins.  If you need one,
652
 * write it...) */
653
struct ofpbuf *
654
ofputil_encode_packet_in_private(const struct ofputil_packet_in_private *pin,
655
                                 enum ofputil_protocol protocol,
656
                                 enum ofputil_packet_in_format format)
657
0
{
658
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
659
660
0
    struct ofpbuf *msg;
661
0
    switch (format) {
662
0
    case OFPUTIL_PACKET_IN_STD:
663
0
        switch (protocol) {
664
0
        case OFPUTIL_P_OF10_STD:
665
0
        case OFPUTIL_P_OF10_STD_TID:
666
0
        case OFPUTIL_P_OF10_NXM:
667
0
        case OFPUTIL_P_OF10_NXM_TID:
668
0
            msg = ofputil_encode_ofp10_packet_in(&pin->base);
669
0
            break;
670
671
0
        case OFPUTIL_P_OF11_STD:
672
0
            msg = ofputil_encode_ofp11_packet_in(&pin->base);
673
0
            break;
674
675
0
        case OFPUTIL_P_OF12_OXM:
676
0
        case OFPUTIL_P_OF13_OXM:
677
0
        case OFPUTIL_P_OF14_OXM:
678
0
        case OFPUTIL_P_OF15_OXM:
679
0
            msg = ofputil_encode_ofp12_packet_in(&pin->base, version);
680
0
            break;
681
682
0
        default:
683
0
            OVS_NOT_REACHED();
684
0
        }
685
0
        break;
686
687
0
    case OFPUTIL_PACKET_IN_NXT:
688
0
        msg = ofputil_encode_nx_packet_in(&pin->base, version);
689
0
        break;
690
691
0
    case OFPUTIL_PACKET_IN_NXT2:
692
0
        return ofputil_encode_nx_packet_in2(pin, version,
693
0
                                            pin->base.packet_len);
694
695
0
    default:
696
0
        OVS_NOT_REACHED();
697
0
    }
698
699
0
    ofpbuf_put(msg, pin->base.packet, pin->base.packet_len);
700
0
    ofpmsg_update_length(msg);
701
0
    return msg;
702
0
}
703
704
/* Returns a string form of 'reason'.  The return value is either a statically
705
 * allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
706
 * 'bufsize' should be at least OFPUTIL_PACKET_IN_REASON_BUFSIZE. */
707
const char *
708
ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason,
709
                                   char *reasonbuf, size_t bufsize)
710
105k
{
711
105k
    switch (reason) {
712
21.3k
    case OFPR_NO_MATCH:
713
21.3k
        return "no_match";
714
5.05k
    case OFPR_ACTION:
715
5.05k
        return "action";
716
18.2k
    case OFPR_INVALID_TTL:
717
18.2k
        return "invalid_ttl";
718
5.26k
    case OFPR_ACTION_SET:
719
5.26k
        return "action_set";
720
6.71k
    case OFPR_GROUP:
721
6.71k
        return "group";
722
3.36k
    case OFPR_PACKET_OUT:
723
3.36k
        return "packet_out";
724
4.89k
    case OFPR_EXPLICIT_MISS:
725
6.85k
    case OFPR_IMPLICIT_MISS:
726
6.85k
        return "";
727
728
213
    case OFPR_N_REASONS:
729
38.5k
    default:
730
38.5k
        snprintf(reasonbuf, bufsize, "%d", (int) reason);
731
38.5k
        return reasonbuf;
732
105k
    }
733
105k
}
734
735
bool
736
ofputil_packet_in_reason_from_string(const char *s,
737
                                     enum ofp_packet_in_reason *reason)
738
205
{
739
205
    int i;
740
741
1.55k
    for (i = 0; i < OFPR_N_REASONS; i++) {
742
1.48k
        char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
743
1.48k
        const char *reason_s;
744
745
1.48k
        reason_s = ofputil_packet_in_reason_to_string(i, reasonbuf,
746
1.48k
                                                      sizeof reasonbuf);
747
1.48k
        if (!strcasecmp(s, reason_s)) {
748
134
            *reason = i;
749
134
            return true;
750
134
        }
751
1.48k
    }
752
71
    return false;
753
205
}
754
755
/* Returns a newly allocated NXT_RESUME message for 'pin', with the given
756
 * 'continuation', for 'protocol'.  This message is suitable for resuming the
757
 * pipeline traveral of the packet represented by 'pin', if sent to the switch
758
 * from which 'pin' was received. */
759
struct ofpbuf *
760
ofputil_encode_resume(const struct ofputil_packet_in *pin,
761
                      const struct ofpbuf *continuation,
762
                      enum ofputil_protocol protocol)
763
0
{
764
0
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);
765
0
    size_t extra = pin->packet_len + NXM_TYPICAL_LEN + continuation->size;
766
0
    struct ofpbuf *msg = ofpraw_alloc_xid(OFPRAW_NXT_RESUME, version,
767
0
                                          0, extra);
768
0
    ofputil_put_packet_in(pin, version, pin->packet_len, msg);
769
0
    ofpprop_put_nested(msg, NXPINT_CONTINUATION, continuation);
770
0
    ofpmsg_update_length(msg);
771
0
    return msg;
772
0
}
773
774
static enum ofperr
775
parse_stack_prop(const struct ofpbuf *property, struct ofpbuf *stack)
776
3.87k
{
777
3.87k
    unsigned int len = ofpbuf_msgsize(property);
778
3.87k
    if (len > sizeof(union mf_subvalue)) {
779
0
        VLOG_WARN_RL(&rl, "NXCPT_STACK property has bad length %u",
780
0
                     len);
781
0
        return OFPERR_OFPBPC_BAD_LEN;
782
0
    }
783
3.87k
    nx_stack_push_bottom(stack, property->msg, len);
784
3.87k
    return 0;
785
3.87k
}
786
787
static enum ofperr
788
parse_actions_property(struct ofpbuf *property, enum ofp_version version,
789
                       struct ofpbuf *ofpacts)
790
3.95k
{
791
3.95k
    if (!ofpbuf_try_pull(property, ROUND_UP(ofpbuf_headersize(property), 8))) {
792
297
        VLOG_WARN_RL(&rl, "actions property has bad length %"PRIu32,
793
297
                     property->size);
794
297
        return OFPERR_OFPBPC_BAD_LEN;
795
297
    }
796
797
3.65k
    return ofpacts_pull_openflow_actions(property, property->size,
798
3.65k
                                         version, NULL, NULL, ofpacts);
799
3.95k
}
800
801
/* This is like ofputil_decode_packet_in(), except that it decodes the
802
 * continuation data into 'pin'.  The format of this data is supposed to be
803
 * opaque to any process other than ovs-vswitchd, so this function should not
804
 * be used outside ovs-vswitchd.
805
 *
806
 * 'vl_mff_map' is an optional parameter that is used to validate the length
807
 * of variable length mf_fields in 'match'. If it is not provided, the
808
 * default mf_fields with maximum length will be used.
809
 *
810
 * When successful, 'pin' contains some dynamically allocated data.  Call
811
 * ofputil_packet_in_private_destroy() to free this data. */
812
enum ofperr
813
ofputil_decode_packet_in_private(const struct ofp_header *oh, bool loose,
814
                                 const struct tun_table *tun_table,
815
                                 const struct vl_mff_map *vl_mff_map,
816
                                 struct ofputil_packet_in_private *pin,
817
                                 size_t *total_len, uint32_t *buffer_id)
818
126k
{
819
126k
    memset(pin, 0, sizeof *pin);
820
821
126k
    struct ofpbuf continuation;
822
126k
    enum ofperr error;
823
126k
    error = ofputil_decode_packet_in(oh, loose, tun_table, vl_mff_map,
824
126k
                                     &pin->base, total_len, buffer_id,
825
126k
                                     &continuation);
826
126k
    if (error) {
827
49.8k
        return error;
828
49.8k
    }
829
830
76.9k
    struct ofpbuf actions, action_set;
831
76.9k
    ofpbuf_init(&actions, 0);
832
76.9k
    ofpbuf_init(&action_set, 0);
833
834
76.9k
    uint8_t table_id = 0;
835
76.9k
    ovs_be64 cookie = 0;
836
837
76.9k
    struct ofpbuf stack;
838
76.9k
    ofpbuf_init(&stack, 0);
839
840
90.4k
    while (continuation.size > 0) {
841
15.5k
        struct ofpbuf payload;
842
15.5k
        uint64_t type;
843
844
15.5k
        error = ofpprop_pull(&continuation, &payload, &type);
845
15.5k
        if (error) {
846
1.39k
            break;
847
1.39k
        }
848
849
14.1k
        switch (type) {
850
355
        case NXCPT_BRIDGE:
851
355
            error = ofpprop_parse_uuid(&payload, &pin->bridge);
852
355
            break;
853
854
3.87k
        case NXCPT_STACK:
855
3.87k
            error = parse_stack_prop(&payload, &stack);
856
3.87k
            break;
857
858
1.26k
        case NXCPT_MIRRORS:
859
1.26k
            error = ofpprop_parse_u32(&payload, &pin->mirrors);
860
1.26k
            break;
861
862
466
        case NXCPT_CONNTRACKED:
863
466
            pin->conntracked = true;
864
466
            break;
865
866
855
        case NXCPT_TABLE_ID:
867
855
            error = ofpprop_parse_u8(&payload, &table_id);
868
855
            break;
869
870
301
        case NXCPT_COOKIE:
871
301
            error = ofpprop_parse_be64(&payload, &cookie);
872
301
            break;
873
874
2.80k
        case NXCPT_ACTIONS: {
875
2.80k
            struct ofpact_unroll_xlate *unroll
876
2.80k
                = ofpact_put_UNROLL_XLATE(&actions);
877
2.80k
            unroll->rule_table_id = table_id;
878
2.80k
            unroll->rule_cookie = cookie;
879
2.80k
            error = parse_actions_property(&payload, oh->version, &actions);
880
2.80k
            break;
881
0
        }
882
883
1.14k
        case NXCPT_ACTION_SET:
884
1.14k
            error = parse_actions_property(&payload, oh->version, &action_set);
885
1.14k
            break;
886
887
212
        case NXCPT_ODP_PORT: {
888
212
            uint32_t value;
889
212
            error = ofpprop_parse_u32(&payload, &value);
890
212
            if (!error) {
891
129
                pin->odp_port = u32_to_odp(value);
892
129
            }
893
212
            break;
894
0
         }
895
896
2.83k
        default:
897
2.83k
            error = OFPPROP_UNKNOWN(loose, "continuation", type);
898
2.83k
            break;
899
14.1k
        }
900
14.1k
        if (error) {
901
590
            break;
902
590
        }
903
14.1k
    }
904
905
76.9k
    pin->actions_len = actions.size;
906
76.9k
    pin->actions = ofpbuf_steal_data(&actions);
907
76.9k
    pin->action_set_len = action_set.size;
908
76.9k
    pin->action_set = ofpbuf_steal_data(&action_set);
909
76.9k
    pin->stack_size = stack.size;
910
76.9k
    pin->stack = ofpbuf_steal_data(&stack);
911
912
76.9k
    if (error) {
913
1.98k
        ofputil_packet_in_private_destroy(pin);
914
1.98k
    }
915
916
76.9k
    return error;
917
76.9k
}
918
919
void
920
ofputil_packet_in_private_format(struct ds *s,
921
                                 const struct ofputil_packet_in_private *pin,
922
                                 size_t total_len, uint32_t buffer_id,
923
                                 const struct ofputil_port_map *port_map,
924
                                 const struct ofputil_table_map *table_map,
925
                                 int verbosity)
926
74.9k
{
927
74.9k
    char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
928
74.9k
    const struct ofputil_packet_in *public = &pin->base;
929
930
74.9k
    if (public->table_id
931
74.9k
        || ofputil_table_map_get_name(table_map, public->table_id)) {
932
19.5k
        ds_put_format(s, " table_id=");
933
19.5k
        ofputil_format_table(public->table_id, table_map, s);
934
19.5k
    }
935
936
74.9k
    if (public->cookie != OVS_BE64_MAX) {
937
4.98k
        ds_put_format(s, " cookie=0x%"PRIx64, ntohll(public->cookie));
938
4.98k
    }
939
940
74.9k
    ds_put_format(s, " total_len=%"PRIuSIZE" ", total_len);
941
942
74.9k
    match_format(&public->flow_metadata, port_map, s, OFP_DEFAULT_PRIORITY);
943
944
74.9k
    ds_put_format(s, " (via %s)",
945
74.9k
                  ofputil_packet_in_reason_to_string(public->reason,
946
74.9k
                                                     reasonbuf,
947
74.9k
                                                     sizeof reasonbuf));
948
949
74.9k
    ds_put_format(s, " data_len=%"PRIuSIZE, public->packet_len);
950
74.9k
    if (buffer_id == UINT32_MAX) {
951
6.82k
        ds_put_format(s, " (unbuffered)");
952
6.82k
        if (total_len != public->packet_len) {
953
2.16k
            ds_put_format(s, " (***total_len != data_len***)");
954
2.16k
        }
955
68.1k
    } else {
956
68.1k
        ds_put_format(s, " buffer=0x%08"PRIx32, buffer_id);
957
68.1k
        if (total_len < public->packet_len) {
958
7.98k
            ds_put_format(s, " (***total_len < data_len***)");
959
7.98k
        }
960
68.1k
    }
961
74.9k
    ds_put_char(s, '\n');
962
963
74.9k
    if (public->userdata_len) {
964
288
        ds_put_cstr(s, " userdata=");
965
288
        ds_put_hex_with_delimiter(s, pin->base.userdata,
966
288
                                  pin->base.userdata_len, ".");
967
288
        ds_put_char(s, '\n');
968
288
    }
969
970
74.9k
    if (!uuid_is_zero(&pin->bridge)) {
971
240
        ds_put_format(s, " continuation.bridge="UUID_FMT"\n",
972
240
                      UUID_ARGS(&pin->bridge));
973
240
    }
974
975
74.9k
    if (pin->stack_size) {
976
2.11k
        ds_put_cstr(s, " continuation.stack=(top)");
977
978
2.11k
        struct ofpbuf pin_stack;
979
2.11k
        ofpbuf_use_const(&pin_stack, pin->stack, pin->stack_size);
980
981
5.51k
        while (pin_stack.size) {
982
3.40k
            uint8_t len;
983
3.40k
            uint8_t *val = nx_stack_pop(&pin_stack, &len);
984
3.40k
            union mf_subvalue value;
985
986
3.40k
            ds_put_char(s, ' ');
987
3.40k
            memset(&value, 0, sizeof value - len);
988
3.40k
            memcpy(&value.u8[sizeof value - len], val, len);
989
3.40k
            mf_subvalue_format(&value, s);
990
3.40k
        }
991
2.11k
        ds_put_cstr(s, " (bottom)\n");
992
2.11k
    }
993
994
74.9k
    if (pin->mirrors) {
995
864
        ds_put_format(s, " continuation.mirrors=0x%"PRIx32"\n",
996
864
                      pin->mirrors);
997
864
    }
998
999
74.9k
    if (pin->conntracked) {
1000
382
        ds_put_cstr(s, " continuation.conntracked=true\n");
1001
382
    }
1002
1003
74.9k
    struct ofpact_format_params fp = {
1004
74.9k
        .port_map = port_map,
1005
74.9k
        .table_map = table_map,
1006
74.9k
        .s = s,
1007
74.9k
    };
1008
1009
74.9k
    if (pin->actions_len) {
1010
1.72k
        ds_put_cstr(s, " continuation.actions=");
1011
1.72k
        ofpacts_format(pin->actions, pin->actions_len, &fp);
1012
1.72k
        ds_put_char(s, '\n');
1013
1.72k
    }
1014
1015
74.9k
    if (pin->action_set_len) {
1016
798
        ds_put_cstr(s, " continuation.action_set=");
1017
798
        ofpacts_format(pin->action_set, pin->action_set_len, &fp);
1018
798
        ds_put_char(s, '\n');
1019
798
    }
1020
1021
74.9k
    if (pin->odp_port) {
1022
89
        ds_put_format(s, " continuation.odp_port=%"PRIu32, pin->odp_port);
1023
89
        ds_put_char(s, '\n');
1024
89
    }
1025
1026
74.9k
    if (verbosity > 0) {
1027
74.9k
        char *packet = ofp_packet_to_string(
1028
74.9k
            public->packet, public->packet_len,
1029
74.9k
            public->flow_metadata.flow.packet_type);
1030
74.9k
        ds_put_cstr(s, packet);
1031
74.9k
        free(packet);
1032
74.9k
    }
1033
74.9k
    if (verbosity > 2) {
1034
0
        ds_put_hex_dump(s, public->packet, public->packet_len, 0, false);
1035
0
    }
1036
74.9k
}
1037
1038
/* Frees data in 'pin' that is dynamically allocated by
1039
 * ofputil_decode_packet_in_private().
1040
 *
1041
 * 'pin->base' contains some pointer members that
1042
 * ofputil_decode_packet_in_private() doesn't initialize to newly allocated
1043
 * data, so this function doesn't free those. */
1044
void
1045
ofputil_packet_in_private_destroy(struct ofputil_packet_in_private *pin)
1046
76.9k
{
1047
76.9k
    if (pin) {
1048
76.9k
        free(pin->stack);
1049
76.9k
        free(pin->actions);
1050
76.9k
        free(pin->action_set);
1051
76.9k
    }
1052
76.9k
}
1053
1054
/* Converts an OFPT_PACKET_OUT in 'opo' into an abstract ofputil_packet_out in
1055
 * 'po'.
1056
 *
1057
 * Uses 'ofpacts' to store the abstract OFPACT_* version of the packet out
1058
 * message's actions.  The caller must initialize 'ofpacts' and retains
1059
 * ownership of it.  'po->ofpacts' will point into the 'ofpacts' buffer.
1060
 *
1061
 * 'po->packet' refers to the packet data in 'oh', so the buffer containing
1062
 * 'oh' must not be destroyed while 'po' is being used.
1063
 *
1064
 * Returns 0 if successful, otherwise an OFPERR_* value. */
1065
enum ofperr
1066
ofputil_decode_packet_out(struct ofputil_packet_out *po,
1067
                          const struct ofp_header *oh,
1068
                          const struct tun_table *tun_table,
1069
                          struct ofpbuf *ofpacts)
1070
169k
{
1071
169k
    struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
1072
169k
    enum ofpraw raw = ofpraw_pull_assert(&b);
1073
1074
169k
    ofpbuf_clear(ofpacts);
1075
169k
    match_init_catchall(&po->flow_metadata);
1076
169k
    if (raw == OFPRAW_OFPT15_PACKET_OUT) {
1077
74.3k
        enum ofperr error;
1078
74.3k
        const struct ofp15_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
1079
1080
74.3k
        po->buffer_id = ntohl(opo->buffer_id);
1081
74.3k
        error = oxm_pull_match_loose(&b, true, tun_table, &po->flow_metadata);
1082
74.3k
        if (error) {
1083
47.4k
            return error;
1084
47.4k
        }
1085
1086
26.8k
        if (!po->flow_metadata.wc.masks.in_port.ofp_port) {
1087
19.2k
            return OFPERR_OFPBRC_BAD_PORT;
1088
19.2k
        }
1089
1090
7.67k
        error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
1091
7.67k
                                              oh->version, NULL, NULL,
1092
7.67k
                                              ofpacts);
1093
7.67k
        if (error) {
1094
7.20k
            return error;
1095
7.20k
        }
1096
94.7k
    } else if (raw == OFPRAW_OFPT11_PACKET_OUT) {
1097
58.2k
        enum ofperr error;
1098
58.2k
        ofp_port_t in_port;
1099
58.2k
        const struct ofp11_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
1100
1101
58.2k
        po->buffer_id = ntohl(opo->buffer_id);
1102
58.2k
        error = ofputil_port_from_ofp11(opo->in_port, &in_port);
1103
58.2k
        if (error) {
1104
5.21k
            return error;
1105
5.21k
        }
1106
52.9k
        match_set_packet_type(&po->flow_metadata, htonl(PT_ETH));
1107
52.9k
        match_set_in_port(&po->flow_metadata, in_port);
1108
1109
52.9k
        error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
1110
52.9k
                                              oh->version, NULL, NULL,
1111
52.9k
                                              ofpacts);
1112
52.9k
        if (error) {
1113
40.8k
            return error;
1114
40.8k
        }
1115
52.9k
    } else if (raw == OFPRAW_OFPT10_PACKET_OUT) {
1116
36.5k
        enum ofperr error;
1117
36.5k
        const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
1118
1119
36.5k
        po->buffer_id = ntohl(opo->buffer_id);
1120
36.5k
        match_set_packet_type(&po->flow_metadata, htonl(PT_ETH));
1121
36.5k
        match_set_in_port(&po->flow_metadata, u16_to_ofp(ntohs(opo->in_port)));
1122
1123
36.5k
        error = ofpacts_pull_openflow_actions(&b, ntohs(opo->actions_len),
1124
36.5k
                                              oh->version, NULL, NULL,
1125
36.5k
                                              ofpacts);
1126
36.5k
        if (error) {
1127
25.7k
            return error;
1128
25.7k
        }
1129
36.5k
    } else {
1130
0
        OVS_NOT_REACHED();
1131
0
    }
1132
1133
23.3k
    ofp_port_t in_port = po->flow_metadata.flow.in_port.ofp_port;
1134
23.3k
    if (ofp_to_u16(in_port) >= ofp_to_u16(OFPP_MAX)
1135
23.3k
        && in_port != OFPP_LOCAL
1136
23.3k
        && in_port != OFPP_NONE
1137
23.3k
        && in_port != OFPP_CONTROLLER) {
1138
236
        VLOG_WARN_RL(&rl, "packet-out has bad input port %#"PRIx32,
1139
236
                     po->flow_metadata.flow.in_port.ofp_port);
1140
236
        return OFPERR_OFPBRC_BAD_PORT;
1141
236
    }
1142
1143
23.1k
    po->ofpacts = ofpacts->data;
1144
23.1k
    po->ofpacts_len = ofpacts->size;
1145
1146
23.1k
    if (po->buffer_id == UINT32_MAX) {
1147
1.24k
        po->packet = b.data;
1148
1.24k
        po->packet_len = b.size;
1149
21.9k
    } else {
1150
21.9k
        po->packet = NULL;
1151
21.9k
        po->packet_len = 0;
1152
21.9k
    }
1153
1154
23.1k
    return 0;
1155
23.3k
}
1156
1157
struct ofpbuf *
1158
ofputil_encode_packet_out(const struct ofputil_packet_out *po,
1159
                          enum ofputil_protocol protocol)
1160
0
{
1161
0
    enum ofp_version ofp_version = ofputil_protocol_to_ofp_version(protocol);
1162
0
    struct ofpbuf *msg;
1163
0
    size_t size;
1164
1165
0
    size = po->ofpacts_len;
1166
0
    if (po->buffer_id == UINT32_MAX) {
1167
0
        size += po->packet_len;
1168
0
    }
1169
1170
0
    switch (ofp_version) {
1171
0
    case OFP10_VERSION: {
1172
0
        struct ofp10_packet_out *opo;
1173
0
        size_t actions_ofs;
1174
1175
0
        msg = ofpraw_alloc(OFPRAW_OFPT10_PACKET_OUT, OFP10_VERSION, size);
1176
0
        ofpbuf_put_zeros(msg, sizeof *opo);
1177
0
        actions_ofs = msg->size;
1178
0
        ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
1179
0
                                     ofp_version);
1180
1181
0
        opo = msg->msg;
1182
0
        opo->buffer_id = htonl(po->buffer_id);
1183
0
        opo->in_port =htons(ofp_to_u16(
1184
0
                                po->flow_metadata.flow.in_port.ofp_port));
1185
0
        opo->actions_len = htons(msg->size - actions_ofs);
1186
0
        break;
1187
0
    }
1188
1189
0
    case OFP11_VERSION:
1190
0
    case OFP12_VERSION:
1191
0
    case OFP13_VERSION:
1192
0
    case OFP14_VERSION: {
1193
0
        struct ofp11_packet_out *opo;
1194
0
        size_t len;
1195
1196
0
        msg = ofpraw_alloc(OFPRAW_OFPT11_PACKET_OUT, ofp_version, size);
1197
0
        ofpbuf_put_zeros(msg, sizeof *opo);
1198
0
        len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
1199
0
                                           ofp_version);
1200
0
        opo = msg->msg;
1201
0
        opo->buffer_id = htonl(po->buffer_id);
1202
0
        opo->in_port =
1203
0
            ofputil_port_to_ofp11(po->flow_metadata.flow.in_port.ofp_port);
1204
0
        opo->actions_len = htons(len);
1205
0
        break;
1206
0
    }
1207
1208
0
    case OFP15_VERSION: {
1209
0
        struct ofp15_packet_out *opo;
1210
0
        size_t len;
1211
1212
        /* The final argument is just an estimate of the space required. */
1213
0
        msg = ofpraw_alloc(OFPRAW_OFPT15_PACKET_OUT, ofp_version,
1214
0
                           size + NXM_TYPICAL_LEN);
1215
0
        ofpbuf_put_zeros(msg, sizeof *opo);
1216
0
        oxm_put_match(msg, &po->flow_metadata, ofp_version);
1217
0
        len = ofpacts_put_openflow_actions(po->ofpacts, po->ofpacts_len, msg,
1218
0
                                           ofp_version);
1219
0
        opo = msg->msg;
1220
0
        opo->buffer_id = htonl(po->buffer_id);
1221
0
        opo->actions_len = htons(len);
1222
0
        break;
1223
0
    }
1224
1225
0
    default:
1226
0
        OVS_NOT_REACHED();
1227
0
    }
1228
1229
0
    if (po->buffer_id == UINT32_MAX) {
1230
0
        ofpbuf_put(msg, po->packet, po->packet_len);
1231
0
    }
1232
1233
0
    ofpmsg_update_length(msg);
1234
1235
0
    return msg;
1236
0
}
1237
1238
void
1239
ofputil_packet_out_format(struct ds *s, const struct ofputil_packet_out *po,
1240
                          const struct ofputil_port_map *port_map,
1241
                          const struct ofputil_table_map *table_map,
1242
                          int verbosity)
1243
23.1k
{
1244
23.1k
    ds_put_char(s, ' ');
1245
23.1k
    match_format(&po->flow_metadata, port_map, s, OFP_DEFAULT_PRIORITY);
1246
1247
23.1k
    ds_put_cstr(s, " actions=");
1248
23.1k
    struct ofpact_format_params fp = {
1249
23.1k
        .port_map = port_map,
1250
23.1k
        .table_map = table_map,
1251
23.1k
        .s = s,
1252
23.1k
    };
1253
23.1k
    ofpacts_format(po->ofpacts, po->ofpacts_len, &fp);
1254
1255
23.1k
    if (po->buffer_id == UINT32_MAX) {
1256
1.24k
        ds_put_format(s, " data_len=%"PRIuSIZE, po->packet_len);
1257
1.24k
        if (verbosity > 0 && po->packet_len > 0) {
1258
1.06k
            ovs_be32 po_packet_type = po->flow_metadata.flow.packet_type;
1259
1.06k
            char *packet = ofp_packet_to_string(po->packet, po->packet_len,
1260
1.06k
                                                po_packet_type);
1261
1.06k
            ds_put_char(s, '\n');
1262
1.06k
            ds_put_cstr(s, packet);
1263
1.06k
            free(packet);
1264
1.06k
        }
1265
1.24k
        if (verbosity > 2) {
1266
0
            ds_put_hex_dump(s, po->packet, po->packet_len, 0, false);
1267
0
        }
1268
21.9k
    } else {
1269
21.9k
        ds_put_format(s, " buffer=0x%08"PRIx32, po->buffer_id);
1270
21.9k
    }
1271
23.1k
}
1272

1273
/* Parse a string representation of a OFPT_PACKET_OUT to '*po'.  If successful,
1274
 * both 'po->ofpacts' and 'po->packet' must be free()d by the caller. */
1275
static char * OVS_WARN_UNUSED_RESULT
1276
parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string,
1277
                           const struct ofputil_port_map *port_map,
1278
                           const struct ofputil_table_map *table_map,
1279
                           enum ofputil_protocol *usable_protocols)
1280
0
{
1281
0
    enum ofputil_protocol action_usable_protocols;
1282
0
    uint64_t stub[256 / 8];
1283
0
    struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
1284
0
    struct dp_packet *packet = NULL;
1285
0
    char *act_str = NULL;
1286
0
    char *name, *value;
1287
0
    char *error = NULL;
1288
1289
0
    *usable_protocols = OFPUTIL_P_ANY;
1290
1291
0
    *po = (struct ofputil_packet_out) {
1292
0
        .buffer_id = UINT32_MAX,
1293
0
    };
1294
0
    match_init_catchall(&po->flow_metadata);
1295
0
    match_set_in_port(&po->flow_metadata, OFPP_CONTROLLER);
1296
1297
0
    act_str = ofp_extract_actions(string);
1298
1299
0
    while (ofputil_parse_key_value(&string, &name, &value)) {
1300
0
        if (!*value) {
1301
0
            error = xasprintf("field %s missing value", name);
1302
0
            goto out;
1303
0
        }
1304
1305
0
        if (!strcmp(name, "in_port")) {
1306
0
            ofp_port_t in_port;
1307
0
            if (!ofputil_port_from_string(value, port_map, &in_port)) {
1308
0
                error = xasprintf("%s is not a valid OpenFlow port", value);
1309
0
                goto out;
1310
0
            }
1311
0
            if (ofp_to_u16(in_port) > ofp_to_u16(OFPP_MAX)
1312
0
                && in_port != OFPP_LOCAL
1313
0
                && in_port != OFPP_NONE
1314
0
                && in_port != OFPP_CONTROLLER) {
1315
0
                error = xasprintf(
1316
0
                              "%s is not a valid OpenFlow port for PACKET_OUT",
1317
0
                              value);
1318
0
                goto out;
1319
0
            }
1320
0
            match_set_in_port(&po->flow_metadata, in_port);
1321
0
        } else if (!strcmp(name, "packet_type")) {
1322
0
            char *ns = value;
1323
0
            char *ns_type = strstr(value, ",");
1324
0
            if (ns_type) {
1325
0
                ovs_be32 packet_type;
1326
0
                *ns_type = '\0';
1327
0
                packet_type = PACKET_TYPE_BE(strtoul(ns, NULL, 0),
1328
0
                                             strtoul(++ns_type, NULL, 0));
1329
0
                match_set_packet_type(&po->flow_metadata, packet_type);
1330
0
            } else {
1331
0
                error = xasprintf("%s(%s) can't be interpreted", name, value);
1332
0
                goto out;
1333
0
            }
1334
0
        } else if (!strcmp(name, "packet")) {
1335
0
            const char *error_msg = eth_from_hex(value, &packet);
1336
0
            if (error_msg) {
1337
0
                error = xasprintf("%s: %s", name, error_msg);
1338
0
                goto out;
1339
0
            }
1340
0
        } else {
1341
0
            const struct mf_field *mf = mf_from_name(name);
1342
0
            if (!mf) {
1343
0
                error = xasprintf("unknown keyword %s", name);
1344
0
                goto out;
1345
0
            }
1346
1347
0
            error = ofp_parse_field(mf, value, port_map, &po->flow_metadata,
1348
0
                                    usable_protocols);
1349
0
            if (error) {
1350
0
                goto out;
1351
0
            }
1352
0
            if (!mf_is_pipeline_field(mf)) {
1353
0
                error = xasprintf("%s is not a valid pipeline field "
1354
0
                                  "for PACKET_OUT", name);
1355
0
                goto out;
1356
0
            }
1357
0
        }
1358
0
    }
1359
1360
0
    if (!packet || !dp_packet_size(packet)) {
1361
0
        error = xstrdup("must specify packet");
1362
0
        goto out;
1363
0
    }
1364
1365
0
    if (act_str) {
1366
0
        struct ofpact_parse_params pp = {
1367
0
            .port_map = port_map,
1368
0
            .table_map = table_map,
1369
0
            .ofpacts = &ofpacts,
1370
0
            .usable_protocols = &action_usable_protocols,
1371
0
        };
1372
0
        error = ofpacts_parse_actions(act_str, &pp);
1373
0
        *usable_protocols &= action_usable_protocols;
1374
0
        if (error) {
1375
0
            goto out;
1376
0
        }
1377
0
    }
1378
0
    po->ofpacts_len = ofpacts.size;
1379
0
    po->ofpacts = ofpbuf_steal_data(&ofpacts);
1380
1381
0
    po->packet_len = dp_packet_size(packet);
1382
0
    po->packet = dp_packet_steal_data(packet);
1383
0
out:
1384
0
    ofpbuf_uninit(&ofpacts);
1385
0
    dp_packet_delete(packet);
1386
0
    return error;
1387
0
}
1388
1389
/* Convert 'str_' (as described in the Packet-Out Syntax section of the
1390
 * ovs-ofctl man page) into 'po' for sending a OFPT_PACKET_OUT message to a
1391
 * switch.  Returns the set of usable protocols in '*usable_protocols'.
1392
 *
1393
 * Returns NULL if successful, otherwise a malloc()'d string describing the
1394
 * error.  The caller is responsible for freeing the returned string.
1395
 * If successful, both 'po->ofpacts' and 'po->packet' must be free()d by
1396
 * the caller. */
1397
char * OVS_WARN_UNUSED_RESULT
1398
parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_,
1399
                         const struct ofputil_port_map *port_map,
1400
                         const struct ofputil_table_map *table_map,
1401
                         enum ofputil_protocol *usable_protocols)
1402
0
{
1403
0
    char *string = xstrdup(str_);
1404
0
    char *error;
1405
1406
0
    error = parse_ofp_packet_out_str__(po, string, port_map, table_map,
1407
0
                                       usable_protocols);
1408
0
    if (error) {
1409
0
        po->ofpacts = NULL;
1410
0
        po->ofpacts_len = 0;
1411
0
    }
1412
1413
0
    free(string);
1414
0
    return error;
1415
0
}