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
);
165 case NXPINT_USERDATA
:
166 pin
->userdata
= payload
.msg
;
167 pin
->userdata_len
= ofpbuf_msgsize(&payload
);
170 case NXPINT_CONTINUATION
:
172 error
= ofpprop_parse_nested(&payload
, continuation
);
177 error
= OFPPROP_UNKNOWN(loose
, "NX_PACKET_IN2", type
);
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
;
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
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().
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).
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.
220 * Returns 0 if successful, otherwise an OpenFlow error code. */
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
)
232 memset(pin
, 0, sizeof *pin
);
233 pin
->cookie
= OVS_BE64_MAX
;
235 ofpbuf_use_const(continuation
, NULL
, 0);
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
)
245 enum ofperr error
= oxm_pull_match_loose(&b
, false, tun_table
,
246 &pin
->flow_metadata
);
251 if (!ofpbuf_try_pull(&b
, 2)) {
252 return OFPERR_OFPBRC_BAD_LEN
;
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
);
260 pin
->cookie
= *cookie
;
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
;
268 opi
= ofpbuf_pull(&b
, offsetof(struct ofp10_packet_in
, data
));
270 pin
->packet
= CONST_CAST(uint8_t *, opi
->data
);
271 pin
->packet_len
= b
.size
;
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
;
284 opi
= ofpbuf_pull(&b
, sizeof *opi
);
286 pin
->packet
= b
.data
;
287 pin
->packet_len
= b
.size
;
289 buffer_id
= ntohl(opi
->buffer_id
);
290 error
= ofputil_port_from_ofp11(opi
->in_port
, &in_port
);
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
;
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,
311 if (!ofpbuf_try_pull(&b
, 2)) {
312 return OFPERR_OFPBRC_BAD_LEN
;
315 pin
->reason
= npi
->reason
;
316 pin
->table_id
= npi
->table_id
;
317 pin
->cookie
= npi
->cookie
;
319 buffer_id
= ntohl(npi
->buffer_id
);
320 total_len
= ntohs(npi
->total_len
);
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
);
336 *total_lenp
= total_len
;
339 *buffer_idp
= buffer_id
;
346 encode_packet_in_reason(enum ofp_packet_in_reason reason
,
347 enum ofp_version version
)
352 case OFPR_INVALID_TTL
:
355 case OFPR_ACTION_SET
:
357 case OFPR_PACKET_OUT
:
358 return version
< OFP14_VERSION
? OFPR_ACTION
: reason
;
360 case OFPR_EXPLICIT_MISS
:
361 return version
< OFP13_VERSION
? OFPR_ACTION
: OFPR_NO_MATCH
;
363 case OFPR_IMPLICIT_MISS
:
364 return OFPR_NO_MATCH
;
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. */
375 ofputil_put_packet_in(const struct ofputil_packet_in
*pin
,
376 enum ofp_version version
, size_t include_bytes
,
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
);
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
);
391 /* Add other properties. */
392 ofpprop_put_u8(msg
, NXPINT_REASON
,
393 encode_packet_in_reason(pin
->reason
, version
));
395 size_t start
= ofpprop_start(msg
, NXPINT_METADATA
);
396 oxm_put_raw(msg
, &pin
->flow_metadata
, version
);
397 ofpprop_end(msg
, start
);
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
)
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
);
412 enum nx_continuation_prop_type
{
413 NXCPT_BRIDGE
= 0x8000,
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. */
426 ofputil_put_packet_in_private(const struct ofputil_packet_in_private
*pin
,
427 enum ofp_version version
, size_t include_bytes
,
430 ofputil_put_packet_in(&pin
->base
, version
, include_bytes
, msg
);
432 size_t continuation_ofs
= ofpprop_start_nested(msg
, NXPINT_CONTINUATION
);
433 size_t inner_ofs
= msg
->size
;
435 if (!uuid_is_zero(&pin
->bridge
)) {
436 ofpprop_put_uuid(msg
, NXCPT_BRIDGE
, &pin
->bridge
);
439 struct ofpbuf pin_stack
;
440 ofpbuf_use_const(&pin_stack
, pin
->stack
, pin
->stack_size
);
442 while (pin_stack
.size
) {
444 uint8_t *val
= nx_stack_pop(&pin_stack
, &len
);
445 ofpprop_put(msg
, NXCPT_STACK
, val
, len
);
449 ofpprop_put_u32(msg
, NXCPT_MIRRORS
, pin
->mirrors
);
452 if (pin
->conntracked
) {
453 ofpprop_put_flag(msg
, NXCPT_CONNTRACKED
);
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
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
,
467 const struct ofpact_unroll_xlate
*unroll
= NULL
;
468 uint8_t table_id
= 0;
471 const struct ofpact
*a
;
472 for (a
= pin
->actions
; ; a
= ofpact_next(a
)) {
473 if (a
== end
|| a
->type
== OFPACT_UNROLL_XLATE
) {
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
;
480 if (cookie
!= unroll
->rule_cookie
) {
481 ofpprop_put_be64(msg
, NXCPT_COOKIE
,
482 unroll
->rule_cookie
);
483 cookie
= unroll
->rule_cookie
;
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
);
495 unroll
= ofpact_get_UNROLL_XLATE(a
);
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
);
507 if (msg
->size
> inner_ofs
) {
508 ofpprop_end(msg
, continuation_ofs
);
510 msg
->size
= continuation_ofs
;
514 static struct ofpbuf
*
515 ofputil_encode_ofp10_packet_in(const struct ofputil_packet_in
*pin
)
517 struct ofp10_packet_in
*opi
;
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
);
531 static struct ofpbuf
*
532 ofputil_encode_nx_packet_in(const struct ofputil_packet_in
*pin
,
533 enum ofp_version version
)
535 struct nx_packet_in
*npi
;
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);
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
);
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
)
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
566 + pin
->action_set_len
567 + 256); /* fudge factor */
568 struct ofpbuf
*msg
= ofpraw_alloc_xid(OFPRAW_NXT_PACKET_IN2
, version
,
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
);
577 ofpmsg_update_length(msg
);
581 static struct ofpbuf
*
582 ofputil_encode_ofp11_packet_in(const struct ofputil_packet_in
*pin
)
584 struct ofp11_packet_in
*opi
;
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
;
601 static struct ofpbuf
*
602 ofputil_encode_ofp12_packet_in(const struct ofputil_packet_in
*pin
,
603 enum ofp_version version
)
605 enum ofpraw raw
= (version
>= OFP13_VERSION
606 ? OFPRAW_OFPT13_PACKET_IN
607 : OFPRAW_OFPT12_PACKET_IN
);
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
);
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
;
620 if (version
>= OFP13_VERSION
) {
621 ovs_be64 cookie
= pin
->cookie
;
622 ofpbuf_put(msg
, &cookie
, sizeof cookie
);
625 oxm_put_match(msg
, &pin
->flow_metadata
, version
);
626 ofpbuf_put_zeros(msg
, 2);
631 /* Converts abstract ofputil_packet_in_private 'pin' into a PACKET_IN message
632 * for 'protocol', using the packet-in format specified by 'format'.
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,
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
)
647 enum ofp_version version
= ofputil_protocol_to_ofp_version(protocol
);
651 case OFPUTIL_PACKET_IN_STD
:
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
);
660 case OFPUTIL_P_OF11_STD
:
661 msg
= ofputil_encode_ofp11_packet_in(&pin
->base
);
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
);
677 case OFPUTIL_PACKET_IN_NXT
:
678 msg
= ofputil_encode_nx_packet_in(&pin
->base
, version
);
681 case OFPUTIL_PACKET_IN_NXT2
:
682 return ofputil_encode_nx_packet_in2(pin
, version
,
683 pin
->base
.packet_len
);
689 ofpbuf_put(msg
, pin
->base
.packet
, pin
->base
.packet_len
);
690 ofpmsg_update_length(msg
);
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. */
698 ofputil_packet_in_reason_to_string(enum ofp_packet_in_reason reason
,
699 char *reasonbuf
, size_t bufsize
)
706 case OFPR_INVALID_TTL
:
707 return "invalid_ttl";
708 case OFPR_ACTION_SET
:
712 case OFPR_PACKET_OUT
:
714 case OFPR_EXPLICIT_MISS
:
715 case OFPR_IMPLICIT_MISS
:
720 snprintf(reasonbuf
, bufsize
, "%d", (int) reason
);
726 ofputil_packet_in_reason_from_string(const char *s
,
727 enum ofp_packet_in_reason
*reason
)
731 for (i
= 0; i
< OFPR_N_REASONS
; i
++) {
732 char reasonbuf
[OFPUTIL_PACKET_IN_REASON_BUFSIZE
];
733 const char *reason_s
;
735 reason_s
= ofputil_packet_in_reason_to_string(i
, reasonbuf
,
737 if (!strcasecmp(s
, reason_s
)) {
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. */
750 ofputil_encode_resume(const struct ofputil_packet_in
*pin
,
751 const struct ofpbuf
*continuation
,
752 enum ofputil_protocol protocol
)
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
,
758 ofputil_put_packet_in(pin
, version
, pin
->packet_len
, msg
);
759 ofpprop_put_nested(msg
, NXPINT_CONTINUATION
, continuation
);
760 ofpmsg_update_length(msg
);
765 parse_stack_prop(const struct ofpbuf
*property
, struct ofpbuf
*stack
)
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",
771 return OFPERR_OFPBPC_BAD_LEN
;
773 nx_stack_push_bottom(stack
, property
->msg
, len
);
778 parse_actions_property(struct ofpbuf
*property
, enum ofp_version version
,
779 struct ofpbuf
*ofpacts
)
781 if (!ofpbuf_try_pull(property
, ROUND_UP(ofpbuf_headersize(property
), 8))) {
782 VLOG_WARN_RL(&rl
, "actions property has bad length %"PRIu32
,
784 return OFPERR_OFPBPC_BAD_LEN
;
787 return ofpacts_pull_openflow_actions(property
, property
->size
,
788 version
, NULL
, NULL
, ofpacts
);
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.
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.
800 * When successful, 'pin' contains some dynamically allocated data. Call
801 * ofputil_packet_in_private_destroy() to free this data. */
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
)
809 memset(pin
, 0, sizeof *pin
);
811 struct ofpbuf continuation
;
813 error
= ofputil_decode_packet_in(oh
, loose
, tun_table
, vl_mff_map
,
814 &pin
->base
, total_len
, buffer_id
,
820 struct ofpbuf actions
, action_set
;
821 ofpbuf_init(&actions
, 0);
822 ofpbuf_init(&action_set
, 0);
824 uint8_t table_id
= 0;
828 ofpbuf_init(&stack
, 0);
830 while (continuation
.size
> 0) {
831 struct ofpbuf payload
;
834 error
= ofpprop_pull(&continuation
, &payload
, &type
);
841 error
= ofpprop_parse_uuid(&payload
, &pin
->bridge
);
845 error
= parse_stack_prop(&payload
, &stack
);
849 error
= ofpprop_parse_u32(&payload
, &pin
->mirrors
);
852 case NXCPT_CONNTRACKED
:
853 pin
->conntracked
= true;
857 error
= ofpprop_parse_u8(&payload
, &table_id
);
861 error
= ofpprop_parse_be64(&payload
, &cookie
);
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
);
873 case NXCPT_ACTION_SET
:
874 error
= parse_actions_property(&payload
, oh
->version
, &action_set
);
878 error
= OFPPROP_UNKNOWN(loose
, "continuation", type
);
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
);
894 ofputil_packet_in_private_destroy(pin
);
901 format_hex_arg(struct ds
*s
, const uint8_t *data
, size_t len
)
903 for (size_t i
= 0; i
< len
; i
++) {
907 ds_put_format(s
, "%02"PRIx8
, data
[i
]);
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
,
919 char reasonbuf
[OFPUTIL_PACKET_IN_REASON_BUFSIZE
];
920 const struct ofputil_packet_in
*public = &pin
->base
;
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
);
928 if (public->cookie
!= OVS_BE64_MAX
) {
929 ds_put_format(s
, " cookie=0x%"PRIx64
, ntohll(public->cookie
));
932 ds_put_format(s
, " total_len=%"PRIuSIZE
" ", total_len
);
934 match_format(&public->flow_metadata
, port_map
, s
, OFP_DEFAULT_PRIORITY
);
936 ds_put_format(s
, " (via %s)",
937 ofputil_packet_in_reason_to_string(public->reason
,
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***)");
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***)");
953 ds_put_char(s
, '\n');
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');
961 if (!uuid_is_zero(&pin
->bridge
)) {
962 ds_put_format(s
, " continuation.bridge="UUID_FMT
"\n",
963 UUID_ARGS(&pin
->bridge
));
966 if (pin
->stack_size
) {
967 ds_put_cstr(s
, " continuation.stack=(top)");
969 struct ofpbuf pin_stack
;
970 ofpbuf_use_const(&pin_stack
, pin
->stack
, pin
->stack_size
);
972 while (pin_stack
.size
) {
974 uint8_t *val
= nx_stack_pop(&pin_stack
, &len
);
975 union mf_subvalue value
;
978 memset(&value
, 0, sizeof value
- len
);
979 memcpy(&value
.u8
[sizeof value
- len
], val
, len
);
980 mf_subvalue_format(&value
, s
);
982 ds_put_cstr(s
, " (bottom)\n");
986 ds_put_format(s
, " continuation.mirrors=0x%"PRIx32
"\n",
990 if (pin
->conntracked
) {
991 ds_put_cstr(s
, " continuation.conntracked=true\n");
994 struct ofpact_format_params fp
= {
995 .port_map
= port_map
,
996 .table_map
= table_map
,
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');
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');
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
);
1019 if (verbosity
> 2) {
1020 ds_put_hex_dump(s
, public->packet
, public->packet_len
, 0, false);
1024 /* Frees data in 'pin' that is dynamically allocated by
1025 * ofputil_decode_packet_in_private().
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. */
1031 ofputil_packet_in_private_destroy(struct ofputil_packet_in_private
*pin
)
1036 free(pin
->action_set
);
1040 /* Converts an OFPT_PACKET_OUT in 'opo' into an abstract ofputil_packet_out in
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.
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.
1050 * Returns 0 if successful, otherwise an OFPERR_* value. */
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
)
1057 struct ofpbuf b
= ofpbuf_const_initializer(oh
, ntohs(oh
->length
));
1058 enum ofpraw raw
= ofpraw_pull_assert(&b
);
1060 ofpbuf_clear(ofpacts
);
1061 match_init_catchall(&po
->flow_metadata
);
1062 if (raw
== OFPRAW_OFPT15_PACKET_OUT
) {
1064 const struct ofp15_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
1066 po
->buffer_id
= ntohl(opo
->buffer_id
);
1067 error
= oxm_pull_match_loose(&b
, true, tun_table
, &po
->flow_metadata
);
1072 if (!po
->flow_metadata
.wc
.masks
.in_port
.ofp_port
) {
1073 return OFPERR_OFPBRC_BAD_PORT
;
1076 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1077 oh
->version
, NULL
, NULL
,
1082 } else if (raw
== OFPRAW_OFPT11_PACKET_OUT
) {
1085 const struct ofp11_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
1087 po
->buffer_id
= ntohl(opo
->buffer_id
);
1088 error
= ofputil_port_from_ofp11(opo
->in_port
, &in_port
);
1092 match_set_packet_type(&po
->flow_metadata
, htonl(PT_ETH
));
1093 match_set_in_port(&po
->flow_metadata
, in_port
);
1095 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1096 oh
->version
, NULL
, NULL
,
1101 } else if (raw
== OFPRAW_OFPT10_PACKET_OUT
) {
1103 const struct ofp10_packet_out
*opo
= ofpbuf_pull(&b
, sizeof *opo
);
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
)));
1109 error
= ofpacts_pull_openflow_actions(&b
, ntohs(opo
->actions_len
),
1110 oh
->version
, NULL
, NULL
,
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
;
1129 po
->ofpacts
= ofpacts
->data
;
1130 po
->ofpacts_len
= ofpacts
->size
;
1132 if (po
->buffer_id
== UINT32_MAX
) {
1133 po
->packet
= b
.data
;
1134 po
->packet_len
= b
.size
;
1144 ofputil_encode_packet_out(const struct ofputil_packet_out
*po
,
1145 enum ofputil_protocol protocol
)
1147 enum ofp_version ofp_version
= ofputil_protocol_to_ofp_version(protocol
);
1151 size
= po
->ofpacts_len
;
1152 if (po
->buffer_id
== UINT32_MAX
) {
1153 size
+= po
->packet_len
;
1156 switch (ofp_version
) {
1157 case OFP10_VERSION
: {
1158 struct ofp10_packet_out
*opo
;
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
,
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
);
1178 case OFP14_VERSION
: {
1179 struct ofp11_packet_out
*opo
;
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
,
1187 opo
->buffer_id
= htonl(po
->buffer_id
);
1189 ofputil_port_to_ofp11(po
->flow_metadata
.flow
.in_port
.ofp_port
);
1190 opo
->actions_len
= htons(len
);
1195 case OFP16_VERSION
: {
1196 struct ofp15_packet_out
*opo
;
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
,
1207 opo
->buffer_id
= htonl(po
->buffer_id
);
1208 opo
->actions_len
= htons(len
);
1216 if (po
->buffer_id
== UINT32_MAX
) {
1217 ofpbuf_put(msg
, po
->packet
, po
->packet_len
);
1220 ofpmsg_update_length(msg
);
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
,
1231 ds_put_char(s
, ' ');
1232 match_format(&po
->flow_metadata
, port_map
, s
, OFP_DEFAULT_PRIORITY
);
1234 ds_put_cstr(s
, " actions=");
1235 struct ofpact_format_params fp
= {
1236 .port_map
= port_map
,
1237 .table_map
= table_map
,
1240 ofpacts_format(po
->ofpacts
, po
->ofpacts_len
, &fp
);
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
,
1248 ds_put_char(s
, '\n');
1249 ds_put_cstr(s
, packet
);
1252 if (verbosity
> 2) {
1253 ds_put_hex_dump(s
, po
->packet
, po
->packet_len
, 0, false);
1256 ds_put_format(s
, " buffer=0x%08"PRIx32
, po
->buffer_id
);
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
)
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
;
1276 *usable_protocols
= OFPUTIL_P_ANY
;
1278 *po
= (struct ofputil_packet_out
) {
1279 .buffer_id
= UINT32_MAX
,
1281 match_init_catchall(&po
->flow_metadata
);
1282 match_set_in_port(&po
->flow_metadata
, OFPP_CONTROLLER
);
1284 act_str
= ofp_extract_actions(string
);
1286 while (ofputil_parse_key_value(&string
, &name
, &value
)) {
1288 error
= xasprintf("field %s missing value", name
);
1292 if (!strcmp(name
, "in_port")) {
1294 if (!ofputil_port_from_string(value
, port_map
, &in_port
)) {
1295 error
= xasprintf("%s is not a valid OpenFlow port", value
);
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
) {
1303 "%s is not a valid OpenFlow port for PACKET_OUT",
1307 match_set_in_port(&po
->flow_metadata
, in_port
);
1308 } else if (!strcmp(name
, "packet_type")) {
1310 char *ns_type
= strstr(value
, ",");
1312 ovs_be32 packet_type
;
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
);
1318 error
= xasprintf("%s(%s) can't be interpreted", name
, value
);
1321 } else if (!strcmp(name
, "packet")) {
1322 const char *error_msg
= eth_from_hex(value
, &packet
);
1324 error
= xasprintf("%s: %s", name
, error_msg
);
1328 const struct mf_field
*mf
= mf_from_name(name
);
1330 error
= xasprintf("unknown keyword %s", name
);
1334 error
= ofp_parse_field(mf
, value
, port_map
, &po
->flow_metadata
,
1339 if (!mf_is_pipeline_field(mf
)) {
1340 error
= xasprintf("%s is not a valid pipeline field "
1341 "for PACKET_OUT", name
);
1347 if (!packet
|| !dp_packet_size(packet
)) {
1348 error
= xstrdup("must specify packet");
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
,
1359 error
= ofpacts_parse_actions(act_str
, &pp
);
1360 *usable_protocols
&= action_usable_protocols
;
1365 po
->ofpacts_len
= ofpacts
.size
;
1366 po
->ofpacts
= ofpbuf_steal_data(&ofpacts
);
1368 po
->packet_len
= dp_packet_size(packet
);
1369 po
->packet
= dp_packet_steal_data(packet
);
1371 ofpbuf_uninit(&ofpacts
);
1372 dp_packet_delete(packet
);
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'.
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
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
)
1390 char *string
= xstrdup(str_
);
1393 error
= parse_ofp_packet_out_str__(po
, string
, port_map
, table_map
,
1397 po
->ofpacts_len
= 0;