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