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