2 * Copyright (c) 2008-2017 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "openvswitch/ofp-packet.h"
20 #include "dp-packet.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"
35 VLOG_DEFINE_THIS_MODULE(ofp_packet
);
37 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
40 ofputil_packet_in_format_to_string(enum ofputil_packet_in_format format
)
43 case OFPUTIL_PACKET_IN_STD
:
45 case OFPUTIL_PACKET_IN_NXT
:
46 return "nxt_packet_in";
47 case OFPUTIL_PACKET_IN_NXT2
:
48 return "nxt_packet_in2";
55 ofputil_packet_in_format_from_string(const char *s
)
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
67 ofputil_encode_set_packet_in_format(enum ofp_version ofp_version
,
68 enum ofputil_packet_in_format format
)
70 struct ofpbuf
*msg
= ofpraw_alloc(OFPRAW_NXT_SET_PACKET_IN_FORMAT
,
72 ovs_be32
*spif
= ofpbuf_put_uninit(msg
, sizeof *spif
);
73 *spif
= htonl(format
);
79 ofputil_decode_set_packet_in_format(const struct ofp_header
*oh
,
80 enum ofputil_packet_in_format
*format
)
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
);
88 case OFPUTIL_PACKET_IN_STD
:
89 case OFPUTIL_PACKET_IN_NXT
:
90 case OFPUTIL_PACKET_IN_NXT2
:
95 VLOG_WARN_RL(&rl
, "NXT_SET_PACKET_IN_FORMAT message specified invalid "
96 "packet-in format %"PRIu32
, spif
);
97 return OFPERR_OFPBRC_EPERM
;
101 /* The caller has done basic initialization of '*pin'; the other output
102 * arguments needs to be initialized. */
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
)
112 *buffer_id
= UINT32_MAX
;
114 struct ofpbuf properties
;
115 ofpbuf_use_const(&properties
, oh
, ntohs(oh
->length
));
116 ofpraw_pull_assert(&properties
);
118 while (properties
.size
> 0) {
119 struct ofpbuf payload
;
122 enum ofperr error
= ofpprop_pull(&properties
, &payload
, &type
);
129 pin
->packet
= payload
.msg
;
130 pin
->packet_len
= ofpbuf_msgsize(&payload
);
133 case NXPINT_FULL_LEN
: {
135 error
= ofpprop_parse_u32(&payload
, &u32
);
140 case NXPINT_BUFFER_ID
:
141 error
= ofpprop_parse_u32(&payload
, buffer_id
);
144 case NXPINT_TABLE_ID
:
145 error
= ofpprop_parse_u8(&payload
, &pin
->table_id
);
149 error
= ofpprop_parse_be64(&payload
, &pin
->cookie
);
152 case NXPINT_REASON
: {
154 error
= ofpprop_parse_u8(&payload
, &reason
);
155 pin
->reason
= reason
;
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
;
166 case NXPINT_USERDATA
:
167 pin
->userdata
= payload
.msg
;
168 pin
->userdata_len
= ofpbuf_msgsize(&payload
);
171 case NXPINT_CONTINUATION
:
173 error
= ofpprop_parse_nested(&payload
, continuation
);
178 error
= OFPPROP_UNKNOWN(loose
, "NX_PACKET_IN2", type
);
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
;
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
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().
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).
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.
221 * Returns 0 if successful, otherwise an OpenFlow error code. */
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
)
233 memset(pin
, 0, sizeof *pin
);
234 pin
->cookie
= OVS_BE64_MAX
;
236 ofpbuf_use_const(continuation
, NULL
, 0);
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
)
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
;
253 if (!ofpbuf_try_pull(&b
, 2)) {
254 return OFPERR_OFPBRC_BAD_LEN
;
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
);
262 pin
->cookie
= *cookie
;
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
;
270 opi
= ofpbuf_pull(&b
, offsetof(struct ofp10_packet_in
, data
));
272 pin
->packet
= CONST_CAST(uint8_t *, opi
->data
);
273 pin
->packet_len
= b
.size
;
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
;
286 opi
= ofpbuf_pull(&b
, sizeof *opi
);
288 pin
->packet
= b
.data
;
289 pin
->packet_len
= b
.size
;
291 buffer_id
= ntohl(opi
->buffer_id
);
292 error
= ofputil_port_from_ofp11(opi
->in_port
, &in_port
);
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
;
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,
313 if (!ofpbuf_try_pull(&b
, 2)) {
314 return OFPERR_OFPBRC_BAD_LEN
;
317 pin
->reason
= npi
->reason
;
318 pin
->table_id
= npi
->table_id
;
319 pin
->cookie
= npi
->cookie
;
321 buffer_id
= ntohl(npi
->buffer_id
);
322 total_len
= ntohs(npi
->total_len
);
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
);
338 *total_lenp
= total_len
;
341 *buffer_idp
= buffer_id
;
348 encode_packet_in_reason(enum ofp_packet_in_reason reason
,
349 enum ofp_version version
)
354 case OFPR_INVALID_TTL
:
357 case OFPR_ACTION_SET
:
359 case OFPR_PACKET_OUT
:
360 return version
< OFP14_VERSION
? OFPR_ACTION
: reason
;
362 case OFPR_EXPLICIT_MISS
:
363 return version
< OFP13_VERSION
? OFPR_ACTION
: OFPR_NO_MATCH
;
365 case OFPR_IMPLICIT_MISS
:
366 return OFPR_NO_MATCH
;
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. */
377 ofputil_put_packet_in(const struct ofputil_packet_in
*pin
,
378 enum ofp_version version
, size_t include_bytes
,
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
);
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
);
393 /* Add other properties. */
394 ofpprop_put_u8(msg
, NXPINT_REASON
,
395 encode_packet_in_reason(pin
->reason
, version
));
397 size_t start
= ofpprop_start(msg
, NXPINT_METADATA
);
398 oxm_put_raw(msg
, &pin
->flow_metadata
, version
);
399 ofpprop_end(msg
, start
);
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
)
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
);
414 enum nx_continuation_prop_type
{
415 NXCPT_BRIDGE
= 0x8000,
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. */
429 ofputil_put_packet_in_private(const struct ofputil_packet_in_private
*pin
,
430 enum ofp_version version
, size_t include_bytes
,
433 ofputil_put_packet_in(&pin
->base
, version
, include_bytes
, msg
);
435 size_t continuation_ofs
= ofpprop_start_nested(msg
, NXPINT_CONTINUATION
);
436 size_t inner_ofs
= msg
->size
;
438 if (!uuid_is_zero(&pin
->bridge
)) {
439 ofpprop_put_uuid(msg
, NXCPT_BRIDGE
, &pin
->bridge
);
442 struct ofpbuf pin_stack
;
443 ofpbuf_use_const(&pin_stack
, pin
->stack
, pin
->stack_size
);
445 while (pin_stack
.size
) {
447 uint8_t *val
= nx_stack_pop(&pin_stack
, &len
);
448 ofpprop_put(msg
, NXCPT_STACK
, val
, len
);
452 ofpprop_put_u32(msg
, NXCPT_MIRRORS
, pin
->mirrors
);
455 if (pin
->conntracked
) {
456 ofpprop_put_flag(msg
, NXCPT_CONNTRACKED
);
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
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
,
470 const struct ofpact_unroll_xlate
*unroll
= NULL
;
471 uint8_t table_id
= 0;
474 const struct ofpact
*a
;
475 for (a
= pin
->actions
; ; a
= ofpact_next(a
)) {
476 if (a
== end
|| a
->type
== OFPACT_UNROLL_XLATE
) {
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
;
483 if (cookie
!= unroll
->rule_cookie
) {
484 ofpprop_put_be64(msg
, NXCPT_COOKIE
,
485 unroll
->rule_cookie
);
486 cookie
= unroll
->rule_cookie
;
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
);
498 unroll
= ofpact_get_UNROLL_XLATE(a
);
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
);
511 ofpprop_put_u32(msg
, NXCPT_ODP_PORT
, odp_to_u32(pin
->odp_port
));
514 if (msg
->size
> inner_ofs
) {
515 ofpprop_end(msg
, continuation_ofs
);
517 msg
->size
= continuation_ofs
;
521 static struct ofpbuf
*
522 ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in
*pin
)
524 struct ofp10_packet_in
*opi
;
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
);
538 static struct ofpbuf
*
539 ofputil_encode_nx_packet_in(const struct ofputil_packet_in
*pin
,
540 enum ofp_version version
)
542 struct nx_packet_in
*npi
;
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);
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
);
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
)
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
573 + pin
->action_set_len
574 + 256); /* fudge factor */
575 struct ofpbuf
*msg
= ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2
, version
,
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
);
584 ofpmsg_update_length(msg
);
588 static struct ofpbuf
*
589 ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in
*pin
)
591 struct ofp11_packet_in
*opi
;
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
;
608 static struct ofpbuf
*
609 ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in
*pin
,
610 enum ofp_version version
)
612 enum ofpraw raw
= (version
>= OFP13_VERSION
613 ? OFPRAW_OFPT13_PACKET_IN
614 : OFPRAW_OFPT12_PACKET_IN
);
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
);
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
;
627 if (version
>= OFP13_VERSION
) {
628 ovs_be64 cookie
= pin
->cookie
;
629 ofpbuf_put(msg
, &cookie
, sizeof cookie
);
632 oxm_put_match(msg
, &pin
->flow_metadata
, version
);
633 ofpbuf_put_zeros(msg
, 2);
638 /* Converts abstract ofputil_packet_in_private 'pin' into a PACKET_IN message
639 * for 'protocol', using the packet-in format specified by 'format'.
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,
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
)
654 enum ofp_version version
= ofputil_protocol_to_ofp_version(protocol
);
658 case OFPUTIL_PACKET_IN_STD
:
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
);
667 case OFPUTIL_P_OF11_STD
:
668 msg
= ofputil_encode_ofp11_packet_in(&pin
->base
);
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
);
683 case OFPUTIL_PACKET_IN_NXT
:
684 msg
= ofputil_encode_nx_packet_in(&pin
->base
, version
);
687 case OFPUTIL_PACKET_IN_NXT2
:
688 return ofputil_encode_nx_packet_in2(pin
, version
,
689 pin
->base
.packet_len
);
695 ofpbuf_put(msg
, pin
->base
.packet
, pin
->base
.packet_len
);
696 ofpmsg_update_length(msg
);
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. */
704 ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason
,
705 char *reasonbuf
, size_t bufsize
)
712 case OFPR_INVALID_TTL
:
713 return "invalid_ttl";
714 case OFPR_ACTION_SET
:
718 case OFPR_PACKET_OUT
:
720 case OFPR_EXPLICIT_MISS
:
721 case OFPR_IMPLICIT_MISS
:
726 snprintf(reasonbuf
, bufsize
, "%d", (int) reason
);
732 ofputil_packet_in_reason_from_string(const char *s
,
733 enum ofp_packet_in_reason
*reason
)
737 for (i
= 0; i
< OFPR_N_REASONS
; i
++) {
738 char reasonbuf
[OFPUTIL_PACKET_IN_REASON_BUFSIZE
];
739 const char *reason_s
;
741 reason_s
= ofputil_packet_in_reason_to_string(i
, reasonbuf
,
743 if (!strcasecmp(s
, reason_s
)) {
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. */
756 ofputil_encode_resume(const struct ofputil_packet_in
*pin
,
757 const struct ofpbuf
*continuation
,
758 enum ofputil_protocol protocol
)
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
,
764 ofputil_put_packet_in(pin
, version
, pin
->packet_len
, msg
);
765 ofpprop_put_nested(msg
, NXPINT_CONTINUATION
, continuation
);
766 ofpmsg_update_length(msg
);
771 parse_stack_prop(const struct ofpbuf
*property
, struct ofpbuf
*stack
)
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",
777 return OFPERR_OFPBPC_BAD_LEN
;
779 nx_stack_push_bottom(stack
, property
->msg
, len
);
784 parse_actions_property(struct ofpbuf
*property
, enum ofp_version version
,
785 struct ofpbuf
*ofpacts
)
787 if (!ofpbuf_try_pull(property
, ROUND_UP(ofpbuf_headersize(property
), 8))) {
788 VLOG_WARN_RL(&rl
, "actions property has bad length %"PRIu32
,
790 return OFPERR_OFPBPC_BAD_LEN
;
793 return ofpacts_pull_openflow_actions(property
, property
->size
,
794 version
, NULL
, NULL
, ofpacts
);
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.
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.
806 * When successful, 'pin' contains some dynamically allocated data. Call
807 * ofputil_packet_in_private_destroy() to free this data. */
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
)
815 memset(pin
, 0, sizeof *pin
);
817 struct ofpbuf continuation
;
819 error
= ofputil_decode_packet_in(oh
, loose
, tun_table
, vl_mff_map
,
820 &pin
->base
, total_len
, buffer_id
,
826 struct ofpbuf actions
, action_set
;
827 ofpbuf_init(&actions
, 0);
828 ofpbuf_init(&action_set
, 0);
830 uint8_t table_id
= 0;
834 ofpbuf_init(&stack
, 0);
836 while (continuation
.size
> 0) {
837 struct ofpbuf payload
;
840 error
= ofpprop_pull(&continuation
, &payload
, &type
);
847 error
= ofpprop_parse_uuid(&payload
, &pin
->bridge
);
851 error
= parse_stack_prop(&payload
, &stack
);
855 error
= ofpprop_parse_u32(&payload
, &pin
->mirrors
);
858 case NXCPT_CONNTRACKED
:
859 pin
->conntracked
= true;
863 error
= ofpprop_parse_u8(&payload
, &table_id
);
867 error
= ofpprop_parse_be64(&payload
, &cookie
);
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
);
879 case NXCPT_ACTION_SET
:
880 error
= parse_actions_property(&payload
, oh
->version
, &action_set
);
883 case NXCPT_ODP_PORT
: {
885 error
= ofpprop_parse_u32(&payload
, &value
);
886 pin
->odp_port
= u32_to_odp(value
);
891 error
= OFPPROP_UNKNOWN(loose
, "continuation", type
);
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
);
907 ofputil_packet_in_private_destroy(pin
);
914 format_hex_arg(struct ds
*s
, const uint8_t *data
, size_t len
)
916 for (size_t i
= 0; i
< len
; i
++) {
920 ds_put_format(s
, "%02"PRIx8
, data
[i
]);
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
,
932 char reasonbuf
[OFPUTIL_PACKET_IN_REASON_BUFSIZE
];
933 const struct ofputil_packet_in
*public = &pin
->base
;
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
);
941 if (public->cookie
!= OVS_BE64_MAX
) {
942 ds_put_format(s
, " cookie=0x%"PRIx64
, ntohll(public->cookie
));
945 ds_put_format(s
, " total_len=%"PRIuSIZE
" ", total_len
);
947 match_format(&public->flow_metadata
, port_map
, s
, OFP_DEFAULT_PRIORITY
);
949 ds_put_format(s
, " (via %s)",
950 ofputil_packet_in_reason_to_string(public->reason
,
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***)");
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***)");
966 ds_put_char(s
, '\n');
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');
974 if (!uuid_is_zero(&pin
->bridge
)) {
975 ds_put_format(s
, " continuation.bridge="UUID_FMT
"\n",
976 UUID_ARGS(&pin
->bridge
));
979 if (pin
->stack_size
) {
980 ds_put_cstr(s
, " continuation.stack=(top)");
982 struct ofpbuf pin_stack
;
983 ofpbuf_use_const(&pin_stack
, pin
->stack
, pin
->stack_size
);
985 while (pin_stack
.size
) {
987 uint8_t *val
= nx_stack_pop(&pin_stack
, &len
);
988 union mf_subvalue value
;
991 memset(&value
, 0, sizeof value
- len
);
992 memcpy(&value
.u8
[sizeof value
- len
], val
, len
);
993 mf_subvalue_format(&value
, s
);
995 ds_put_cstr(s
, " (bottom)\n");
999 ds_put_format(s
, " continuation.mirrors=0x%"PRIx32
"\n",
1003 if (pin
->conntracked
) {
1004 ds_put_cstr(s
, " continuation.conntracked=true\n");
1007 struct ofpact_format_params fp
= {
1008 .port_map
= port_map
,
1009 .table_map
= table_map
,
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');
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');
1025 if (pin
->odp_port
) {
1026 ds_put_format(s
, " continuation.odp_port=%"PRIu32
, pin
->odp_port
);
1027 ds_put_char(s
, '\n');
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
);
1037 if (verbosity
> 2) {
1038 ds_put_hex_dump(s
, public->packet
, public->packet_len
, 0, false);
1042 /* Frees data in 'pin' that is dynamically allocated by
1043 * ofputil_decode_packet_in_private().
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. */
1049 ofputil_packet_in_private_destroy(struct ofputil_packet_in_private
*pin
)
1054 free(pin
->action_set
);
1058 /* Converts an OFPT_PACKET_OUT in 'opo' into an abstract ofputil_packet_out in
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.
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.
1068 * Returns 0 if successful, otherwise an OFPERR_* value. */
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
)
1075 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
1076 enum ofpraw raw
= ofpraw_pull_assert(&b
);
1078 ofpbuf_clear(ofpacts
);
1079 match_init_catchall(&po
->flow_metadata
);
1080 if (raw
== OFPRAW_OFPT15_PACKET_OUT
) {
1082 const struct ofp15_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
1084 po
->buffer_id
= ntohl(opo
->buffer_id
);
1085 error
= oxm_pull_match_loose(&b
, true, tun_table
, &po
->flow_metadata
);
1090 if (!po
->flow_metadata
.wc
.masks
.in_port
.ofp_port
) {
1091 return OFPERR_OFPBRC_BAD_PORT
;
1094 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1095 oh
->version
, NULL
, NULL
,
1100 } else if (raw
== OFPRAW_OFPT11_PACKET_OUT
) {
1103 const struct ofp11_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
1105 po
->buffer_id
= ntohl(opo
->buffer_id
);
1106 error
= ofputil_port_from_ofp11(opo
->in_port
, &in_port
);
1110 match_set_packet_type(&po
->flow_metadata
, htonl(PT_ETH
));
1111 match_set_in_port(&po
->flow_metadata
, in_port
);
1113 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1114 oh
->version
, NULL
, NULL
,
1119 } else if (raw
== OFPRAW_OFPT10_PACKET_OUT
) {
1121 const struct ofp10_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
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
)));
1127 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1128 oh
->version
, NULL
, NULL
,
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
;
1147 po
->ofpacts
= ofpacts
->data
;
1148 po
->ofpacts_len
= ofpacts
->size
;
1150 if (po
->buffer_id
== UINT32_MAX
) {
1151 po
->packet
= b
.data
;
1152 po
->packet_len
= b
.size
;
1162 ofputil_encode_packet_out(const struct ofputil_packet_out
*po
,
1163 enum ofputil_protocol protocol
)
1165 enum ofp_version ofp_version
= ofputil_protocol_to_ofp_version(protocol
);
1169 size
= po
->ofpacts_len
;
1170 if (po
->buffer_id
== UINT32_MAX
) {
1171 size
+= po
->packet_len
;
1174 switch (ofp_version
) {
1175 case OFP10_VERSION
: {
1176 struct ofp10_packet_out
*opo
;
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
,
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
);
1196 case OFP14_VERSION
: {
1197 struct ofp11_packet_out
*opo
;
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
,
1205 opo
->buffer_id
= htonl(po
->buffer_id
);
1207 ofputil_port_to_ofp11(po
->flow_metadata
.flow
.in_port
.ofp_port
);
1208 opo
->actions_len
= htons(len
);
1212 case OFP15_VERSION
: {
1213 struct ofp15_packet_out
*opo
;
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
,
1224 opo
->buffer_id
= htonl(po
->buffer_id
);
1225 opo
->actions_len
= htons(len
);
1233 if (po
->buffer_id
== UINT32_MAX
) {
1234 ofpbuf_put(msg
, po
->packet
, po
->packet_len
);
1237 ofpmsg_update_length(msg
);
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
,
1248 ds_put_char(s
, ' ');
1249 match_format(&po
->flow_metadata
, port_map
, s
, OFP_DEFAULT_PRIORITY
);
1251 ds_put_cstr(s
, " actions=");
1252 struct ofpact_format_params fp
= {
1253 .port_map
= port_map
,
1254 .table_map
= table_map
,
1257 ofpacts_format(po
->ofpacts
, po
->ofpacts_len
, &fp
);
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
,
1265 ds_put_char(s
, '\n');
1266 ds_put_cstr(s
, packet
);
1269 if (verbosity
> 2) {
1270 ds_put_hex_dump(s
, po
->packet
, po
->packet_len
, 0, false);
1273 ds_put_format(s
, " buffer=0x%08"PRIx32
, po
->buffer_id
);
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
)
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
;
1293 *usable_protocols
= OFPUTIL_P_ANY
;
1295 *po
= (struct ofputil_packet_out
) {
1296 .buffer_id
= UINT32_MAX
,
1298 match_init_catchall(&po
->flow_metadata
);
1299 match_set_in_port(&po
->flow_metadata
, OFPP_CONTROLLER
);
1301 act_str
= ofp_extract_actions(string
);
1303 while (ofputil_parse_key_value(&string
, &name
, &value
)) {
1305 error
= xasprintf("field %s missing value", name
);
1309 if (!strcmp(name
, "in_port")) {
1311 if (!ofputil_port_from_string(value
, port_map
, &in_port
)) {
1312 error
= xasprintf("%s is not a valid OpenFlow port", value
);
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
) {
1320 "%s is not a valid OpenFlow port for PACKET_OUT",
1324 match_set_in_port(&po
->flow_metadata
, in_port
);
1325 } else if (!strcmp(name
, "packet_type")) {
1327 char *ns_type
= strstr(value
, ",");
1329 ovs_be32 packet_type
;
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
);
1335 error
= xasprintf("%s(%s) can't be interpreted", name
, value
);
1338 } else if (!strcmp(name
, "packet")) {
1339 const char *error_msg
= eth_from_hex(value
, &packet
);
1341 error
= xasprintf("%s: %s", name
, error_msg
);
1345 const struct mf_field
*mf
= mf_from_name(name
);
1347 error
= xasprintf("unknown keyword %s", name
);
1351 error
= ofp_parse_field(mf
, value
, port_map
, &po
->flow_metadata
,
1356 if (!mf_is_pipeline_field(mf
)) {
1357 error
= xasprintf("%s is not a valid pipeline field "
1358 "for PACKET_OUT", name
);
1364 if (!packet
|| !dp_packet_size(packet
)) {
1365 error
= xstrdup("must specify packet");
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
,
1376 error
= ofpacts_parse_actions(act_str
, &pp
);
1377 *usable_protocols
&= action_usable_protocols
;
1382 po
->ofpacts_len
= ofpacts
.size
;
1383 po
->ofpacts
= ofpbuf_steal_data(&ofpacts
);
1385 po
->packet_len
= dp_packet_size(packet
);
1386 po
->packet
= dp_packet_steal_data(packet
);
1388 ofpbuf_uninit(&ofpacts
);
1389 dp_packet_delete(packet
);
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'.
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
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
)
1407 char *string
= xstrdup(str_
);
1410 error
= parse_ofp_packet_out_str__(po
, string
, port_map
, table_map
,
1414 po
->ofpacts_len
= 0;