2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 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.
19 #include "ofproto-dpif-trace.h"
21 #include "conntrack.h"
23 #include "ofproto-dpif-xlate.h"
26 static void oftrace_node_destroy(struct oftrace_node
*);
28 /* Creates a new oftrace_node, populates it with the given 'type' and a copy of
29 * 'text', and appends it to list 'super'. The caller retains ownership of
32 oftrace_report(struct ovs_list
*super
, enum oftrace_node_type type
,
35 struct oftrace_node
*node
= xmalloc(sizeof *node
);
36 ovs_list_push_back(super
, &node
->node
);
38 node
->text
= xstrdup(text
);
39 ovs_list_init(&node
->subs
);
45 oftrace_node_type_is_terminal(enum oftrace_node_type type
)
65 oftrace_node_list_destroy(struct ovs_list
*nodes
)
68 struct oftrace_node
*node
, *next
;
69 LIST_FOR_EACH_SAFE (node
, next
, node
, nodes
) {
70 ovs_list_remove(&node
->node
);
71 oftrace_node_destroy(node
);
77 oftrace_node_destroy(struct oftrace_node
*node
)
80 oftrace_node_list_destroy(&node
->subs
);
87 oftrace_add_recirc_node(struct ovs_list
*recirc_queue
,
88 enum oftrace_recirc_type type
, const struct flow
*flow
,
89 const struct ofpact_nat
*ofn
,
90 const struct dp_packet
*packet
, uint32_t recirc_id
,
93 if (!recirc_id_node_find_and_ref(recirc_id
)) {
97 struct oftrace_recirc_node
*node
= xmalloc(sizeof *node
);
98 ovs_list_push_back(recirc_queue
, &node
->node
);
101 node
->recirc_id
= recirc_id
;
103 node
->flow
.recirc_id
= recirc_id
;
104 node
->flow
.ct_zone
= zone
;
106 node
->packet
= packet
? dp_packet_clone(packet
) : NULL
;
112 oftrace_recirc_node_destroy(struct oftrace_recirc_node
*node
)
115 recirc_free_id(node
->recirc_id
);
116 dp_packet_delete(node
->packet
);
122 oftrace_push_ct_state(struct ovs_list
*next_ct_states
, uint32_t ct_state
)
124 struct oftrace_next_ct_state
*next_ct_state
=
125 xmalloc(sizeof *next_ct_state
);
126 next_ct_state
->state
= ct_state
;
127 ovs_list_push_back(next_ct_states
, &next_ct_state
->node
);
131 oftrace_pop_ct_state(struct ovs_list
*next_ct_states
)
133 struct oftrace_next_ct_state
*s
;
134 LIST_FOR_EACH_POP (s
, node
, next_ct_states
) {
135 uint32_t state
= s
->state
;
143 oftrace_node_print_details(struct ds
*output
,
144 const struct ovs_list
*nodes
, int level
)
146 const struct oftrace_node
*sub
;
147 LIST_FOR_EACH (sub
, node
, nodes
) {
148 if (sub
->type
== OFT_BRIDGE
) {
149 ds_put_char(output
, '\n');
152 bool more
= (sub
->node
.next
!= nodes
153 || oftrace_node_type_is_terminal(sub
->type
));
155 ds_put_char_multiple(output
, ' ', (level
+ more
) * 4);
158 ds_put_format(output
, " -> %s\n", sub
->text
);
161 ds_put_format(output
, " >> %s\n", sub
->text
);
164 ds_put_format(output
, " >>>> %s <<<<\n", sub
->text
);
167 ds_put_format(output
, "%s\n", sub
->text
);
168 ds_put_char_multiple(output
, ' ', (level
+ more
) * 4);
169 ds_put_char_multiple(output
, '-', strlen(sub
->text
));
170 ds_put_char(output
, '\n');
176 ds_put_format(output
, "%s\n", sub
->text
);
180 oftrace_node_print_details(output
, &sub
->subs
, level
+ more
+ more
);
185 oftrace_print_ip_flow(const struct flow
*flow
, int af
, struct ds
*output
)
188 ds_put_format(output
, "nw_src="IP_FMT
",tp_src=%"PRIu16
","
189 "nw_dst="IP_FMT
",tp_dst=%"PRIu16
,
190 IP_ARGS(flow
->nw_src
), ntohs(flow
->tp_src
),
191 IP_ARGS(flow
->nw_dst
), ntohs(flow
->tp_dst
));
192 } else if (af
== AF_INET6
) {
193 ds_put_cstr(output
, "ipv6_src=");
194 ipv6_format_addr_bracket(&flow
->ipv6_src
, output
, true);
195 ds_put_format(output
, ",tp_src=%"PRIu16
, ntohs(flow
->tp_src
));
196 ds_put_cstr(output
, ",ipv6_dst=");
197 ipv6_format_addr_bracket(&flow
->ipv6_dst
, output
, true);
198 ds_put_format(output
, ",tp_dst=%"PRIu16
, ntohs(flow
->tp_dst
));
200 ds_put_char(output
, '\n');
203 /* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
204 * forms are supported:
206 * - [options] [dpname] odp_flow [packet]
207 * - [options] bridge br_flow [packet]
209 * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure
210 * returns a nonnull malloced error message. */
211 static char * OVS_WARN_UNUSED_RESULT
212 parse_flow_and_packet(int argc
, const char *argv
[],
213 struct ofproto_dpif
**ofprotop
, struct flow
*flow
,
214 struct dp_packet
**packetp
,
215 struct ovs_list
*next_ct_states
,
218 const struct dpif_backer
*backer
= NULL
;
220 struct simap port_names
= SIMAP_INITIALIZER(&port_names
);
221 struct dp_packet
*packet
= NULL
;
224 struct ofpbuf odp_key
;
225 struct ofpbuf odp_mask
;
227 ofpbuf_init(&odp_key
, 0);
228 ofpbuf_init(&odp_mask
, 0);
232 bool generate_packet
= false;
236 for (int i
= 1; i
< argc
; i
++) {
237 const char *arg
= argv
[i
];
238 if (!strcmp(arg
, "-generate") || !strcmp(arg
, "--generate")) {
239 generate_packet
= true;
240 } else if (!strcmp(arg
, "--l7")) {
242 error
= xasprintf("Missing argument for option %s", arg
);
246 struct dp_packet payload
;
247 memset(&payload
, 0, sizeof payload
);
248 dp_packet_init(&payload
, 0);
249 if (dp_packet_put_hex(&payload
, argv
[++i
], NULL
)[0] != '\0') {
250 dp_packet_uninit(&payload
);
251 error
= xstrdup("Trailing garbage in packet data");
255 l7_len
= dp_packet_size(&payload
);
256 l7
= dp_packet_steal_data(&payload
);
257 } else if (!strcmp(arg
, "--l7-len")) {
259 error
= xasprintf("Missing argument for option %s", arg
);
264 l7_len
= atoi(argv
[++i
]);
265 if (l7_len
> 64000) {
266 error
= xasprintf("%s: too much L7 data", argv
[i
]);
269 } else if (consistent
270 && (!strcmp(arg
, "-consistent") ||
271 !strcmp(arg
, "--consistent"))) {
273 } else if (!strcmp(arg
, "--ct-next")) {
275 error
= xasprintf("Missing argument for option %s", arg
);
280 struct ds ds
= DS_EMPTY_INITIALIZER
;
281 if (!parse_ct_state(argv
[++i
], 0, &ct_state
, &ds
)
282 || !validate_ct_state(ct_state
, &ds
)) {
283 error
= ds_steal_cstr(&ds
);
286 oftrace_push_ct_state(next_ct_states
, ct_state
);
287 } else if (arg
[0] == '-') {
288 error
= xasprintf("%s: unknown option", arg
);
290 } else if (n_args
>= ARRAY_SIZE(args
)) {
291 error
= xstrdup("too many arguments");
294 args
[n_args
++] = arg
;
298 /* 'args' must now have one of the following forms:
304 * dpname odp_flow packet
305 * bridge br_flow packet
307 * Parse the packet if it's there. Note that:
309 * - If there is one argument, there cannot be a packet.
311 * - If there are three arguments, there must be a packet.
313 * If there is a packet, we strip it off.
315 if (!generate_packet
&& n_args
> 1) {
316 const char *const_error
= eth_from_hex(args
[n_args
- 1], &packet
);
319 } else if (n_args
> 2) {
320 /* The 3-argument form must end in a hex string. */
321 error
= xstrdup(const_error
);
326 /* We stripped off the packet if there was one, so 'args' now has one of
327 * the following forms:
333 * Before we parse the flow, try to identify the backer, then use that
334 * backer to assemble a collection of port names. The port names are
335 * useful so that the user can specify ports by name instead of number in
338 /* args[0] might be dpname. */
340 if (!strncmp(args
[0], "ovs-", 4)) {
341 dp_type
= args
[0] + 4;
345 backer
= shash_find_data(&all_dpif_backers
, dp_type
);
346 } else if (n_args
== 1) {
347 /* Pick default backer. */
348 struct shash_node
*node
;
349 if (shash_count(&all_dpif_backers
) == 1) {
350 node
= shash_first(&all_dpif_backers
);
354 error
= xstrdup("Syntax error");
357 if (backer
&& backer
->dpif
) {
358 struct dpif_port dpif_port
;
359 struct dpif_port_dump port_dump
;
360 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, backer
->dpif
) {
361 simap_put(&port_names
, dpif_port
.name
,
362 odp_to_u32(dpif_port
.port_no
));
366 /* Parse the flow and determine whether a datapath or
367 * bridge is specified. If function odp_flow_key_from_string()
368 * returns 0, the flow is a odp_flow. If function
369 * parse_ofp_exact_flow() returns NULL, the flow is a br_flow. */
370 if (!odp_flow_from_string(args
[n_args
- 1], &port_names
,
371 &odp_key
, &odp_mask
, &error
)) {
373 error
= xstrdup("Cannot find the datapath");
377 if (odp_flow_key_to_flow(odp_key
.data
, odp_key
.size
, flow
, &error
)
382 *ofprotop
= xlate_lookup_ofproto(backer
, flow
,
383 &flow
->in_port
.ofp_port
, &error
);
384 if (*ofprotop
== NULL
) {
388 flow
->tunnel
.metadata
.tab
= ofproto_get_tun_tab(&(*ofprotop
)->up
);
390 /* Convert Geneve options to OpenFlow format now. This isn't actually
391 * required in order to get the right results since the ofproto xlate
392 * actions will handle this for us. However, converting now ensures
393 * that our formatting code will always be able to consistently print
394 * in OpenFlow format, which is what we use here. */
395 if (flow
->tunnel
.flags
& FLOW_TNL_F_UDPIF
) {
397 memcpy(&tnl
, &flow
->tunnel
, sizeof tnl
);
398 int err
= tun_metadata_from_geneve_udpif(
399 flow
->tunnel
.metadata
.tab
, &tnl
, &tnl
, &flow
->tunnel
);
401 error
= xstrdup("Failed to parse Geneve options");
405 } else if (n_args
!= 2) {
407 error
= xasprintf("%s (or the bridge name was omitted)", s
);
414 *ofprotop
= ofproto_dpif_lookup_by_name(args
[0]);
416 error
= xasprintf("%s: unknown bridge", args
[0]);
420 struct ofputil_port_map map
= OFPUTIL_PORT_MAP_INITIALIZER(&map
);
421 const struct ofport
*ofport
;
422 HMAP_FOR_EACH (ofport
, hmap_node
, &(*ofprotop
)->up
.ports
) {
423 ofputil_port_map_put(&map
, ofport
->ofp_port
,
424 netdev_get_name(ofport
->netdev
));
426 char *err
= parse_ofp_exact_flow(flow
, NULL
,
427 ofproto_get_tun_tab(&(*ofprotop
)->up
),
428 args
[n_args
- 1], &map
);
429 ofputil_port_map_destroy(&map
);
431 error
= xasprintf("Bad openflow flow syntax: %s", err
);
437 if (generate_packet
) {
438 /* Generate a packet, as requested. */
439 packet
= dp_packet_new(0);
440 flow_compose(packet
, flow
, l7
, l7_len
);
442 /* Use the metadata from the flow and the packet argument to
443 * reconstruct the flow. */
444 pkt_metadata_from_flow(&packet
->md
, flow
);
445 flow_extract(packet
, flow
);
450 dp_packet_delete(packet
);
454 ofpbuf_uninit(&odp_key
);
455 ofpbuf_uninit(&odp_mask
);
456 simap_destroy(&port_names
);
462 free_ct_states(struct ovs_list
*ct_states
)
464 while (!ovs_list_is_empty(ct_states
)) {
465 oftrace_pop_ct_state(ct_states
);
470 ofproto_unixctl_trace(struct unixctl_conn
*conn
, int argc
, const char *argv
[],
471 void *aux OVS_UNUSED
)
473 struct ofproto_dpif
*ofproto
;
474 struct dp_packet
*packet
;
477 struct ovs_list next_ct_states
= OVS_LIST_INITIALIZER(&next_ct_states
);
479 error
= parse_flow_and_packet(argc
, argv
, &ofproto
, &flow
, &packet
,
480 &next_ct_states
, NULL
);
485 ofproto_trace(ofproto
, &flow
, packet
, NULL
, 0, &next_ct_states
,
487 unixctl_command_reply(conn
, ds_cstr(&result
));
489 dp_packet_delete(packet
);
491 unixctl_command_reply_error(conn
, error
);
494 free_ct_states(&next_ct_states
);
498 ofproto_unixctl_trace_actions(struct unixctl_conn
*conn
, int argc
,
499 const char *argv
[], void *aux OVS_UNUSED
)
501 enum ofputil_protocol usable_protocols
;
502 struct ofproto_dpif
*ofproto
;
503 bool enforce_consistency
;
504 struct ofpbuf ofpacts
;
505 struct dp_packet
*packet
;
509 struct ovs_list next_ct_states
= OVS_LIST_INITIALIZER(&next_ct_states
);
511 /* Three kinds of error return values! */
517 ofpbuf_init(&ofpacts
, 0);
520 struct ofpact_parse_params pp
= {
523 .usable_protocols
= &usable_protocols
,
525 error
= ofpacts_parse_actions(argv
[--argc
], &pp
);
527 unixctl_command_reply_error(conn
, error
);
532 error
= parse_flow_and_packet(argc
, argv
, &ofproto
, &match
.flow
, &packet
,
533 &next_ct_states
, &enforce_consistency
);
535 unixctl_command_reply_error(conn
, error
);
539 match_wc_init(&match
, &match
.flow
);
541 /* Do the same checks as handle_packet_out() in ofproto.c.
543 * We pass a 'table_id' of 0 to ofpacts_check(), which isn't
544 * strictly correct because these actions aren't in any table, but it's OK
545 * because it 'table_id' is used only to check goto_table instructions, but
546 * packet-outs take a list of actions and therefore it can't include
549 * We skip the "meter" check here because meter is an instruction, not an
550 * action, and thus cannot appear in ofpacts. */
551 in_port
= ofp_to_u16(match
.flow
.in_port
.ofp_port
);
552 if (in_port
>= ofproto
->up
.max_ports
&& in_port
< ofp_to_u16(OFPP_MAX
)) {
553 unixctl_command_reply_error(conn
, "invalid in_port");
557 struct ofpact_check_params cp
= {
559 .max_ports
= u16_to_ofp(ofproto
->up
.max_ports
),
561 .n_tables
= ofproto
->up
.n_tables
,
563 retval
= ofpacts_check_consistency(
564 ofpacts
.data
, ofpacts
.size
,
565 enforce_consistency
? usable_protocols
: 0, &cp
);
567 ovs_mutex_lock(&ofproto_mutex
);
568 retval
= ofproto_check_ofpacts(&ofproto
->up
, ofpacts
.data
,
570 ovs_mutex_unlock(&ofproto_mutex
);
575 ds_put_format(&result
, "Bad actions: %s", ofperr_to_string(retval
));
576 unixctl_command_reply_error(conn
, ds_cstr(&result
));
580 ofproto_trace(ofproto
, &match
.flow
, packet
,
581 ofpacts
.data
, ofpacts
.size
, &next_ct_states
, &result
);
582 unixctl_command_reply(conn
, ds_cstr(&result
));
586 dp_packet_delete(packet
);
587 ofpbuf_uninit(&ofpacts
);
588 free_ct_states(&next_ct_states
);
592 explain_slow_path(enum slow_path_reason slow
, struct ds
*output
)
594 ds_put_cstr(output
, "\nThis flow is handled by the userspace "
595 "slow path because it:");
596 for (; slow
; slow
= zero_rightmost_1bit(slow
)) {
597 enum slow_path_reason bit
= rightmost_1bit(slow
);
598 ds_put_format(output
, "\n - %s.",
599 slow_path_reason_to_explanation(bit
));
603 /* Copies ODP actions from 'in' to 'out', dropping OVS_ACTION_ATTR_OUTPUT and
604 * OVS_ACTION_ATTR_RECIRC along the way. */
606 prune_output_actions(const struct ofpbuf
*in
, struct ofpbuf
*out
)
608 const struct nlattr
*a
;
610 NL_ATTR_FOR_EACH (a
, left
, in
->data
, in
->size
) {
611 if (a
->nla_type
== OVS_ACTION_ATTR_CLONE
) {
612 struct ofpbuf in_nested
;
613 nl_attr_get_nested(a
, &in_nested
);
615 size_t ofs
= nl_msg_start_nested(out
, OVS_ACTION_ATTR_CLONE
);
616 prune_output_actions(&in_nested
, out
);
617 nl_msg_end_nested(out
, ofs
);
618 } else if (a
->nla_type
!= OVS_ACTION_ATTR_OUTPUT
&&
619 a
->nla_type
!= OVS_ACTION_ATTR_RECIRC
) {
620 ofpbuf_put(out
, a
, NLA_ALIGN(a
->nla_len
));
625 /* Executes all of the datapath actions, except for any OVS_ACTION_ATTR_OUTPUT
626 * and OVS_ACTION_ATTR_RECIRC actions, in 'actions' on 'packet', which has the
627 * given 'flow', on 'dpif'. The actions have slow path reason 'slow' (if any).
628 * Appends any error message to 'output'.
630 * With output and recirculation actions dropped, the only remaining side
631 * effects are from OVS_ACTION_ATTR_USERSPACE actions for executing actions to
632 * send a packet to an OpenFlow controller, IPFIX, NetFlow, and sFlow, etc. */
634 execute_actions_except_outputs(struct dpif
*dpif
,
635 const struct dp_packet
*packet
,
636 const struct flow
*flow
,
637 const struct ofpbuf
*actions
,
638 enum slow_path_reason slow
,
641 struct ofpbuf pruned_actions
;
642 ofpbuf_init(&pruned_actions
, 0);
643 prune_output_actions(actions
, &pruned_actions
);
645 struct dpif_execute execute
= {
646 .actions
= pruned_actions
.data
,
647 .actions_len
= pruned_actions
.size
,
648 .needs_help
= (slow
& SLOW_ACTION
) != 0,
650 .packet
= dp_packet_clone_with_headroom(packet
, 2),
652 int error
= dpif_execute(dpif
, &execute
);
654 ds_put_format(output
, "\nAction execution failed (%s)\n.",
655 ovs_strerror(error
));
657 dp_packet_delete(execute
.packet
);
658 ofpbuf_uninit(&pruned_actions
);
662 ofproto_trace_recirc_node(struct oftrace_recirc_node
*node
,
663 struct ovs_list
*next_ct_states
,
666 ds_put_cstr(output
, "\n\n");
667 ds_put_char_multiple(output
, '=', 79);
668 ds_put_format(output
, "\nrecirc(%#"PRIx32
")", node
->recirc_id
);
670 if (next_ct_states
&& node
->type
== OFT_RECIRC_CONNTRACK
) {
672 if (ovs_list_is_empty(next_ct_states
)) {
673 ct_state
= CS_TRACKED
| CS_NEW
;
674 ds_put_cstr(output
, " - resume conntrack with default "
675 "ct_state=trk|new (use --ct-next to customize)");
677 ct_state
= oftrace_pop_ct_state(next_ct_states
);
678 struct ds s
= DS_EMPTY_INITIALIZER
;
679 format_flags(&s
, ct_state_to_string
, ct_state
, '|');
680 ds_put_format(output
, " - resume conntrack with ct_state=%s",
684 node
->flow
.ct_state
= ct_state
;
686 ds_put_char(output
, '\n');
688 /* If there's any snat/dnat information assume we always translate to
689 * the first IP/port to make sure we don't match on incorrect flows later
693 const struct ofpact_nat
*ofn
= node
->nat_act
;
695 ds_put_cstr(output
, "Replacing src/dst IP/ports to simulate NAT:\n");
696 ds_put_cstr(output
, " Initial flow: ");
697 oftrace_print_ip_flow(&node
->flow
, ofn
->range_af
, output
);
699 if (ofn
->flags
& NX_NAT_F_SRC
) {
700 if (ofn
->range_af
== AF_INET
) {
701 node
->flow
.nw_src
= ofn
->range
.addr
.ipv4
.min
;
702 } else if (ofn
->range_af
== AF_INET6
) {
703 node
->flow
.ipv6_src
= ofn
->range
.addr
.ipv6
.min
;
706 if (ofn
->range_af
!= AF_UNSPEC
&& ofn
->range
.proto
.min
) {
707 node
->flow
.tp_src
= htons(ofn
->range
.proto
.min
);
710 if (ofn
->flags
& NX_NAT_F_DST
) {
711 if (ofn
->range_af
== AF_INET
) {
712 node
->flow
.nw_dst
= ofn
->range
.addr
.ipv4
.min
;
713 } else if (ofn
->range_af
== AF_INET6
) {
714 node
->flow
.ipv6_dst
= ofn
->range
.addr
.ipv6
.min
;
717 if (ofn
->range_af
!= AF_UNSPEC
&& ofn
->range
.proto
.min
) {
718 node
->flow
.tp_dst
= htons(ofn
->range
.proto
.min
);
721 ds_put_cstr(output
, " Modified flow: ");
722 oftrace_print_ip_flow(&node
->flow
, ofn
->range_af
, output
);
724 ds_put_char_multiple(output
, '=', 79);
725 ds_put_cstr(output
, "\n\n");
729 ofproto_trace__(struct ofproto_dpif
*ofproto
, const struct flow
*flow
,
730 const struct dp_packet
*packet
, struct ovs_list
*recirc_queue
,
731 const struct ofpact ofpacts
[], size_t ofpacts_len
,
734 struct ofpbuf odp_actions
;
735 ofpbuf_init(&odp_actions
, 0);
738 struct flow_wildcards wc
;
739 struct ovs_list trace
= OVS_LIST_INITIALIZER(&trace
);
740 xlate_in_init(&xin
, ofproto
,
741 ofproto_dpif_get_tables_version(ofproto
), flow
,
742 flow
->in_port
.ofp_port
, NULL
, ntohs(flow
->tcp_flags
),
743 packet
, &wc
, &odp_actions
);
744 xin
.ofpacts
= ofpacts
;
745 xin
.ofpacts_len
= ofpacts_len
;
747 xin
.recirc_queue
= recirc_queue
;
749 /* Copy initial flow out of xin.flow. It differs from '*flow' because
750 * xlate_in_init() initializes actset_output to OFPP_UNSET. */
751 struct flow initial_flow
= xin
.flow
;
752 ds_put_cstr(output
, "Flow: ");
753 flow_format(output
, &initial_flow
, NULL
);
754 ds_put_char(output
, '\n');
756 struct xlate_out xout
;
757 enum xlate_error error
= xlate_actions(&xin
, &xout
);
759 oftrace_node_print_details(output
, &trace
, 0);
761 ds_put_cstr(output
, "\nFinal flow: ");
762 if (flow_equal(&initial_flow
, &xin
.flow
)) {
763 ds_put_cstr(output
, "unchanged");
765 flow_format(output
, &xin
.flow
, NULL
);
767 ds_put_char(output
, '\n');
769 ds_put_cstr(output
, "Megaflow: ");
771 match_init(&match
, flow
, &wc
);
772 match_format(&match
, NULL
, output
, OFP_DEFAULT_PRIORITY
);
773 ds_put_char(output
, '\n');
775 ds_put_cstr(output
, "Datapath actions: ");
776 format_odp_actions(output
, odp_actions
.data
, odp_actions
.size
, NULL
);
778 if (error
!= XLATE_OK
) {
779 ds_put_format(output
,
780 "\nTranslation failed (%s), packet is dropped.\n",
781 xlate_strerror(error
));
784 explain_slow_path(xout
.slow
, output
);
787 execute_actions_except_outputs(ofproto
->backer
->dpif
, packet
,
788 &initial_flow
, &odp_actions
,
794 xlate_out_uninit(&xout
);
795 ofpbuf_uninit(&odp_actions
);
796 oftrace_node_list_destroy(&trace
);
799 /* Implements a "trace" through 'ofproto''s flow table, appending a textual
800 * description of the results to 'output'.
802 * The trace follows a packet with the specified 'flow' through the flow
803 * table. 'packet' may be nonnull to trace an actual packet, with consequent
804 * side effects (if it is nonnull then its flow must be 'flow').
806 * If 'ofpacts' is nonnull then its 'ofpacts_len' bytes specify the actions to
807 * trace, otherwise the actions are determined by a flow table lookup. */
809 ofproto_trace(struct ofproto_dpif
*ofproto
, const struct flow
*flow
,
810 const struct dp_packet
*packet
,
811 const struct ofpact ofpacts
[], size_t ofpacts_len
,
812 struct ovs_list
*next_ct_states
, struct ds
*output
)
814 struct ovs_list recirc_queue
= OVS_LIST_INITIALIZER(&recirc_queue
);
815 ofproto_trace__(ofproto
, flow
, packet
, &recirc_queue
,
816 ofpacts
, ofpacts_len
, output
);
818 struct oftrace_recirc_node
*recirc_node
;
819 LIST_FOR_EACH_POP (recirc_node
, node
, &recirc_queue
) {
820 ofproto_trace_recirc_node(recirc_node
, next_ct_states
, output
);
821 ofproto_trace__(ofproto
, &recirc_node
->flow
, recirc_node
->packet
,
822 &recirc_queue
, ofpacts
, ofpacts_len
, output
);
823 oftrace_recirc_node_destroy(recirc_node
);
828 ofproto_dpif_trace_init(void)
830 static bool registered
;
836 unixctl_command_register(
838 "{[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
839 "[-generate|packet]", 1, INT_MAX
, ofproto_unixctl_trace
, NULL
);
840 unixctl_command_register(
841 "ofproto/trace-packet-out",
842 "[-consistent] {[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
843 "[-generate|packet] actions",
844 2, INT_MAX
, ofproto_unixctl_trace_actions
, NULL
);