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