]> git.proxmox.com Git - mirror_ovs.git/blame - ofproto/ofproto-dpif-trace.c
ofproto-dpif: Fix for recirc issue with mpls traffic with dp_hash
[mirror_ovs.git] / ofproto / ofproto-dpif-trace.c
CommitLineData
d13ee228 1/*
d40533fc 2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019 Nicira, Inc.
d13ee228
BP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
18
19#include "ofproto-dpif-trace.h"
20
0f2f05bb 21#include "conntrack.h"
d13ee228
BP
22#include "dpif.h"
23#include "ofproto-dpif-xlate.h"
d13ee228
BP
24#include "unixctl.h"
25
2d9b49dd
BP
26static void oftrace_node_destroy(struct oftrace_node *);
27
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
30 * 'text'. */
31struct oftrace_node *
32oftrace_report(struct ovs_list *super, enum oftrace_node_type type,
33 const char *text)
d13ee228 34{
2d9b49dd
BP
35 struct oftrace_node *node = xmalloc(sizeof *node);
36 ovs_list_push_back(super, &node->node);
37 node->type = type;
38 node->text = xstrdup(text);
39 ovs_list_init(&node->subs);
d13ee228 40
2d9b49dd 41 return node;
d13ee228
BP
42}
43
2d9b49dd
BP
44static bool
45oftrace_node_type_is_terminal(enum oftrace_node_type type)
d13ee228 46{
2d9b49dd
BP
47 switch (type) {
48 case OFT_ACTION:
49 case OFT_DETAIL:
50 case OFT_WARN:
51 case OFT_ERROR:
fac4786a 52 case OFT_BUCKET:
2d9b49dd
BP
53 return true;
54
55 case OFT_BRIDGE:
56 case OFT_TABLE:
57 case OFT_THAW:
58 return false;
d13ee228 59 }
2d9b49dd
BP
60
61 OVS_NOT_REACHED();
d13ee228
BP
62}
63
64static void
2d9b49dd 65oftrace_node_list_destroy(struct ovs_list *nodes)
d13ee228 66{
2d9b49dd
BP
67 if (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);
72 }
d13ee228 73 }
d13ee228
BP
74}
75
76static void
2d9b49dd 77oftrace_node_destroy(struct oftrace_node *node)
d13ee228 78{
2d9b49dd
BP
79 if (node) {
80 oftrace_node_list_destroy(&node->subs);
81 free(node->text);
82 free(node);
83 }
d13ee228
BP
84}
85
e6bc8e74
YHW
86bool
87oftrace_add_recirc_node(struct ovs_list *recirc_queue,
88 enum oftrace_recirc_type type, const struct flow *flow,
5fdd80cc
YHW
89 const struct dp_packet *packet, uint32_t recirc_id,
90 const uint16_t zone)
e6bc8e74
YHW
91{
92 if (!recirc_id_node_find_and_ref(recirc_id)) {
93 return false;
94 }
95
96 struct oftrace_recirc_node *node = xmalloc(sizeof *node);
97 ovs_list_push_back(recirc_queue, &node->node);
98
99 node->type = type;
100 node->recirc_id = recirc_id;
101 node->flow = *flow;
102 node->flow.recirc_id = recirc_id;
5fdd80cc 103 node->flow.ct_zone = zone;
e6bc8e74
YHW
104 node->packet = packet ? dp_packet_clone(packet) : NULL;
105
106 return true;
107}
108
109static void
110oftrace_recirc_node_destroy(struct oftrace_recirc_node *node)
111{
112 if (node) {
113 recirc_free_id(node->recirc_id);
114 dp_packet_delete(node->packet);
115 free(node);
116 }
117}
118
0f2f05bb
YHW
119static void
120oftrace_push_ct_state(struct ovs_list *next_ct_states, uint32_t ct_state)
121{
122 struct oftrace_next_ct_state *next_ct_state =
123 xmalloc(sizeof *next_ct_state);
124 next_ct_state->state = ct_state;
125 ovs_list_push_back(next_ct_states, &next_ct_state->node);
126}
127
128static uint32_t
129oftrace_pop_ct_state(struct ovs_list *next_ct_states)
130{
131 struct oftrace_next_ct_state *s;
132 LIST_FOR_EACH_POP (s, node, next_ct_states) {
36e67140
YHW
133 uint32_t state = s->state;
134 free(s);
135 return state;
0f2f05bb
YHW
136 }
137 OVS_NOT_REACHED();
138}
139
d13ee228 140static void
2d9b49dd
BP
141oftrace_node_print_details(struct ds *output,
142 const struct ovs_list *nodes, int level)
d13ee228 143{
2d9b49dd
BP
144 const struct oftrace_node *sub;
145 LIST_FOR_EACH (sub, node, nodes) {
146 if (sub->type == OFT_BRIDGE) {
147 ds_put_char(output, '\n');
148 }
d13ee228 149
2d9b49dd
BP
150 bool more = (sub->node.next != nodes
151 || oftrace_node_type_is_terminal(sub->type));
152
153 ds_put_char_multiple(output, ' ', (level + more) * 4);
154 switch (sub->type) {
155 case OFT_DETAIL:
156 ds_put_format(output, " -> %s\n", sub->text);
157 break;
158 case OFT_WARN:
159 ds_put_format(output, " >> %s\n", sub->text);
160 break;
161 case OFT_ERROR:
162 ds_put_format(output, " >>>> %s <<<<\n", sub->text);
163 break;
164 case OFT_BRIDGE:
165 ds_put_format(output, "%s\n", sub->text);
166 ds_put_char_multiple(output, ' ', (level + more) * 4);
167 ds_put_char_multiple(output, '-', strlen(sub->text));
168 ds_put_char(output, '\n');
169 break;
170 case OFT_TABLE:
fac4786a 171 case OFT_BUCKET:
2d9b49dd
BP
172 case OFT_THAW:
173 case OFT_ACTION:
174 ds_put_format(output, "%s\n", sub->text);
175 break;
d13ee228 176 }
d13ee228 177
2d9b49dd 178 oftrace_node_print_details(output, &sub->subs, level + more + more);
d13ee228 179 }
d13ee228
BP
180}
181
182/* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
183 * forms are supported:
184 *
b490b189
BP
185 * - [options] [dpname] odp_flow [packet]
186 * - [options] bridge br_flow [packet]
d13ee228
BP
187 *
188 * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure
189 * returns a nonnull malloced error message. */
190static char * OVS_WARN_UNUSED_RESULT
191parse_flow_and_packet(int argc, const char *argv[],
192 struct ofproto_dpif **ofprotop, struct flow *flow,
0f2f05bb 193 struct dp_packet **packetp,
b490b189
BP
194 struct ovs_list *next_ct_states,
195 bool *consistent)
d13ee228
BP
196{
197 const struct dpif_backer *backer = NULL;
d40533fc 198 char *error = NULL;
d13ee228 199 struct simap port_names = SIMAP_INITIALIZER(&port_names);
b490b189 200 struct dp_packet *packet = NULL;
6f068379
BP
201 uint8_t *l7 = NULL;
202 size_t l7_len = 64;
d13ee228
BP
203 struct ofpbuf odp_key;
204 struct ofpbuf odp_mask;
205
206 ofpbuf_init(&odp_key, 0);
207 ofpbuf_init(&odp_mask, 0);
208
b490b189
BP
209 const char *args[3];
210 int n_args = 0;
211 bool generate_packet = false;
212 if (consistent) {
213 *consistent = false;
d13ee228 214 }
b490b189
BP
215 for (int i = 1; i < argc; i++) {
216 const char *arg = argv[i];
217 if (!strcmp(arg, "-generate") || !strcmp(arg, "--generate")) {
218 generate_packet = true;
6f068379
BP
219 } else if (!strcmp(arg, "--l7")) {
220 if (i + 1 >= argc) {
d40533fc 221 error = xasprintf("Missing argument for option %s", arg);
6f068379
BP
222 goto exit;
223 }
224
225 struct dp_packet payload;
226 memset(&payload, 0, sizeof payload);
227 dp_packet_init(&payload, 0);
228 if (dp_packet_put_hex(&payload, argv[++i], NULL)[0] != '\0') {
229 dp_packet_uninit(&payload);
d40533fc 230 error = xstrdup("Trailing garbage in packet data");
6f068379
BP
231 goto exit;
232 }
233 free(l7);
234 l7_len = dp_packet_size(&payload);
235 l7 = dp_packet_steal_data(&payload);
236 } else if (!strcmp(arg, "--l7-len")) {
237 if (i + 1 >= argc) {
d40533fc 238 error = xasprintf("Missing argument for option %s", arg);
6f068379
BP
239 goto exit;
240 }
241 free(l7);
242 l7 = NULL;
243 l7_len = atoi(argv[++i]);
244 if (l7_len > 64000) {
d40533fc 245 error = xasprintf("%s: too much L7 data", argv[i]);
6f068379
BP
246 goto exit;
247 }
b490b189
BP
248 } else if (consistent
249 && (!strcmp(arg, "-consistent") ||
250 !strcmp(arg, "--consistent"))) {
251 *consistent = true;
252 } else if (!strcmp(arg, "--ct-next")) {
253 if (i + 1 >= argc) {
d40533fc 254 error = xasprintf("Missing argument for option %s", arg);
b490b189
BP
255 goto exit;
256 }
d13ee228 257
b490b189
BP
258 uint32_t ct_state;
259 struct ds ds = DS_EMPTY_INITIALIZER;
260 if (!parse_ct_state(argv[++i], 0, &ct_state, &ds)
261 || !validate_ct_state(ct_state, &ds)) {
d40533fc 262 error = ds_steal_cstr(&ds);
b490b189
BP
263 goto exit;
264 }
265 oftrace_push_ct_state(next_ct_states, ct_state);
266 } else if (arg[0] == '-') {
d40533fc 267 error = xasprintf("%s: unknown option", arg);
b490b189
BP
268 goto exit;
269 } else if (n_args >= ARRAY_SIZE(args)) {
d40533fc 270 error = xstrdup("too many arguments");
0f2f05bb 271 goto exit;
b490b189
BP
272 } else {
273 args[n_args++] = arg;
0f2f05bb 274 }
b490b189 275 }
0f2f05bb 276
b490b189
BP
277 /* 'args' must now have one of the following forms:
278 *
279 * odp_flow
280 * dpname odp_flow
281 * bridge br_flow
282 * odp_flow packet
283 * dpname odp_flow packet
284 * bridge br_flow packet
285 *
286 * Parse the packet if it's there. Note that:
287 *
288 * - If there is one argument, there cannot be a packet.
289 *
290 * - If there are three arguments, there must be a packet.
291 *
292 * If there is a packet, we strip it off.
293 */
294 if (!generate_packet && n_args > 1) {
d40533fc
BP
295 const char *const_error = eth_from_hex(args[n_args - 1], &packet);
296 if (!const_error) {
b490b189
BP
297 n_args--;
298 } else if (n_args > 2) {
299 /* The 3-argument form must end in a hex string. */
d40533fc 300 error = xstrdup(const_error);
0f2f05bb
YHW
301 goto exit;
302 }
0f2f05bb
YHW
303 }
304
b490b189
BP
305 /* We stripped off the packet if there was one, so 'args' now has one of
306 * the following forms:
307 *
308 * odp_flow
309 * dpname odp_flow
310 * bridge br_flow
311 *
312 * Before we parse the flow, try to identify the backer, then use that
313 * backer to assemble a collection of port names. The port names are
314 * useful so that the user can specify ports by name instead of number in
315 * the flow. */
316 if (n_args == 2) {
317 /* args[0] might be dpname. */
d13ee228 318 const char *dp_type;
b490b189
BP
319 if (!strncmp(args[0], "ovs-", 4)) {
320 dp_type = args[0] + 4;
d13ee228 321 } else {
b490b189 322 dp_type = args[0];
d13ee228
BP
323 }
324 backer = shash_find_data(&all_dpif_backers, dp_type);
b490b189
BP
325 } else if (n_args == 1) {
326 /* Pick default backer. */
d13ee228
BP
327 struct shash_node *node;
328 if (shash_count(&all_dpif_backers) == 1) {
329 node = shash_first(&all_dpif_backers);
330 backer = node->data;
331 }
332 } else {
d40533fc 333 error = xstrdup("Syntax error");
d13ee228
BP
334 goto exit;
335 }
336 if (backer && backer->dpif) {
337 struct dpif_port dpif_port;
338 struct dpif_port_dump port_dump;
339 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, backer->dpif) {
340 simap_put(&port_names, dpif_port.name,
341 odp_to_u32(dpif_port.port_no));
342 }
343 }
344
345 /* Parse the flow and determine whether a datapath or
346 * bridge is specified. If function odp_flow_key_from_string()
347 * returns 0, the flow is a odp_flow. If function
348 * parse_ofp_exact_flow() returns NULL, the flow is a br_flow. */
b490b189 349 if (!odp_flow_from_string(args[n_args - 1], &port_names,
d40533fc 350 &odp_key, &odp_mask, &error)) {
d13ee228 351 if (!backer) {
d40533fc 352 error = xstrdup("Cannot find the datapath");
d13ee228
BP
353 goto exit;
354 }
355
d40533fc
BP
356 if (odp_flow_key_to_flow(odp_key.data, odp_key.size, flow, &error)
357 == ODP_FIT_ERROR) {
d13ee228
BP
358 goto exit;
359 }
360
361 *ofprotop = xlate_lookup_ofproto(backer, flow,
d40533fc 362 &flow->in_port.ofp_port, &error);
d13ee228 363 if (*ofprotop == NULL) {
d13ee228
BP
364 goto exit;
365 }
366
367 flow->tunnel.metadata.tab = ofproto_get_tun_tab(&(*ofprotop)->up);
368
369 /* Convert Geneve options to OpenFlow format now. This isn't actually
370 * required in order to get the right results since the ofproto xlate
371 * actions will handle this for us. However, converting now ensures
372 * that our formatting code will always be able to consistently print
373 * in OpenFlow format, which is what we use here. */
374 if (flow->tunnel.flags & FLOW_TNL_F_UDPIF) {
375 struct flow_tnl tnl;
d13ee228 376 memcpy(&tnl, &flow->tunnel, sizeof tnl);
d40533fc
BP
377 int err = tun_metadata_from_geneve_udpif(
378 flow->tunnel.metadata.tab, &tnl, &tnl, &flow->tunnel);
d13ee228 379 if (err) {
d40533fc 380 error = xstrdup("Failed to parse Geneve options");
d13ee228
BP
381 goto exit;
382 }
383 }
d40533fc
BP
384 } else if (n_args != 2) {
385 char *s = error;
386 error = xasprintf("%s (or the bridge name was omitted)", s);
387 free(s);
388 goto exit;
d13ee228 389 } else {
d40533fc
BP
390 free(error);
391 error = NULL;
d13ee228 392
b490b189 393 *ofprotop = ofproto_dpif_lookup_by_name(args[0]);
d13ee228 394 if (!*ofprotop) {
d40533fc 395 error = xasprintf("%s: unknown bridge", args[0]);
d13ee228
BP
396 goto exit;
397 }
398
50f96b10
BP
399 struct ofputil_port_map map = OFPUTIL_PORT_MAP_INITIALIZER(&map);
400 const struct ofport *ofport;
401 HMAP_FOR_EACH (ofport, hmap_node, &(*ofprotop)->up.ports) {
402 ofputil_port_map_put(&map, ofport->ofp_port,
403 netdev_get_name(ofport->netdev));
404 }
d40533fc
BP
405 char *err = parse_ofp_exact_flow(flow, NULL,
406 ofproto_get_tun_tab(&(*ofprotop)->up),
407 args[n_args - 1], &map);
50f96b10 408 ofputil_port_map_destroy(&map);
d13ee228 409 if (err) {
d40533fc 410 error = xasprintf("Bad openflow flow syntax: %s", err);
d13ee228
BP
411 free(err);
412 goto exit;
413 }
414 }
415
b490b189
BP
416 if (generate_packet) {
417 /* Generate a packet, as requested. */
418 packet = dp_packet_new(0);
6f068379 419 flow_compose(packet, flow, l7, l7_len);
b490b189
BP
420 } else if (packet) {
421 /* Use the metadata from the flow and the packet argument to
422 * reconstruct the flow. */
423 pkt_metadata_from_flow(&packet->md, flow);
424 flow_extract(packet, flow);
d13ee228
BP
425 }
426
427exit:
d40533fc 428 if (error) {
d13ee228
BP
429 dp_packet_delete(packet);
430 packet = NULL;
431 }
432 *packetp = packet;
433 ofpbuf_uninit(&odp_key);
434 ofpbuf_uninit(&odp_mask);
435 simap_destroy(&port_names);
6f068379 436 free(l7);
d40533fc 437 return error;
d13ee228
BP
438}
439
0f2f05bb
YHW
440static void
441free_ct_states(struct ovs_list *ct_states)
442{
443 while (!ovs_list_is_empty(ct_states)) {
444 oftrace_pop_ct_state(ct_states);
445 }
446}
447
d13ee228
BP
448static void
449ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
450 void *aux OVS_UNUSED)
451{
452 struct ofproto_dpif *ofproto;
453 struct dp_packet *packet;
454 char *error;
455 struct flow flow;
0f2f05bb 456 struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states);
d13ee228 457
0f2f05bb 458 error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet,
b490b189 459 &next_ct_states, NULL);
d13ee228
BP
460 if (!error) {
461 struct ds result;
462
463 ds_init(&result);
0f2f05bb
YHW
464 ofproto_trace(ofproto, &flow, packet, NULL, 0, &next_ct_states,
465 &result);
d13ee228
BP
466 unixctl_command_reply(conn, ds_cstr(&result));
467 ds_destroy(&result);
468 dp_packet_delete(packet);
469 } else {
470 unixctl_command_reply_error(conn, error);
471 free(error);
472 }
0f2f05bb 473 free_ct_states(&next_ct_states);
d13ee228
BP
474}
475
476static void
477ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc,
478 const char *argv[], void *aux OVS_UNUSED)
479{
480 enum ofputil_protocol usable_protocols;
481 struct ofproto_dpif *ofproto;
482 bool enforce_consistency;
483 struct ofpbuf ofpacts;
484 struct dp_packet *packet;
485 struct ds result;
67210a55 486 struct match match;
d13ee228 487 uint16_t in_port;
0f2f05bb 488 struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states);
d13ee228
BP
489
490 /* Three kinds of error return values! */
491 enum ofperr retval;
492 char *error;
493
494 packet = NULL;
495 ds_init(&result);
496 ofpbuf_init(&ofpacts, 0);
497
498 /* Parse actions. */
efefbcae
BP
499 struct ofpact_parse_params pp = {
500 .port_map = NULL,
501 .ofpacts = &ofpacts,
502 .usable_protocols = &usable_protocols,
503 };
504 error = ofpacts_parse_actions(argv[--argc], &pp);
d13ee228
BP
505 if (error) {
506 unixctl_command_reply_error(conn, error);
507 free(error);
508 goto exit;
509 }
510
0f2f05bb 511 error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, &packet,
b490b189 512 &next_ct_states, &enforce_consistency);
d13ee228
BP
513 if (error) {
514 unixctl_command_reply_error(conn, error);
515 free(error);
516 goto exit;
517 }
67210a55 518 match_wc_init(&match, &match.flow);
d13ee228
BP
519
520 /* Do the same checks as handle_packet_out() in ofproto.c.
521 *
522 * We pass a 'table_id' of 0 to ofpacts_check(), which isn't
523 * strictly correct because these actions aren't in any table, but it's OK
524 * because it 'table_id' is used only to check goto_table instructions, but
525 * packet-outs take a list of actions and therefore it can't include
526 * instructions.
527 *
528 * We skip the "meter" check here because meter is an instruction, not an
529 * action, and thus cannot appear in ofpacts. */
67210a55 530 in_port = ofp_to_u16(match.flow.in_port.ofp_port);
d13ee228
BP
531 if (in_port >= ofproto->up.max_ports && in_port < ofp_to_u16(OFPP_MAX)) {
532 unixctl_command_reply_error(conn, "invalid in_port");
533 goto exit;
534 }
ae6f7530
BP
535
536 struct ofpact_check_params cp = {
537 .match = &match,
538 .max_ports = u16_to_ofp(ofproto->up.max_ports),
539 .table_id = 0,
540 .n_tables = ofproto->up.n_tables,
541 };
542 retval = ofpacts_check_consistency(
543 ofpacts.data, ofpacts.size,
544 enforce_consistency ? usable_protocols : 0, &cp);
d13ee228 545 if (!retval) {
d61973d6 546 ovs_mutex_lock(&ofproto_mutex);
d13ee228
BP
547 retval = ofproto_check_ofpacts(&ofproto->up, ofpacts.data,
548 ofpacts.size);
d61973d6 549 ovs_mutex_unlock(&ofproto_mutex);
d13ee228
BP
550 }
551
552 if (retval) {
553 ds_clear(&result);
554 ds_put_format(&result, "Bad actions: %s", ofperr_to_string(retval));
555 unixctl_command_reply_error(conn, ds_cstr(&result));
556 goto exit;
557 }
558
67210a55 559 ofproto_trace(ofproto, &match.flow, packet,
0f2f05bb 560 ofpacts.data, ofpacts.size, &next_ct_states, &result);
d13ee228
BP
561 unixctl_command_reply(conn, ds_cstr(&result));
562
563exit:
564 ds_destroy(&result);
565 dp_packet_delete(packet);
566 ofpbuf_uninit(&ofpacts);
0f2f05bb 567 free_ct_states(&next_ct_states);
d13ee228
BP
568}
569
418a7a84
BP
570static void
571explain_slow_path(enum slow_path_reason slow, struct ds *output)
572{
573 ds_put_cstr(output, "\nThis flow is handled by the userspace "
574 "slow path because it:");
575 for (; slow; slow = zero_rightmost_1bit(slow)) {
576 enum slow_path_reason bit = rightmost_1bit(slow);
577 ds_put_format(output, "\n - %s.",
578 slow_path_reason_to_explanation(bit));
579 }
580}
581
582/* Copies ODP actions from 'in' to 'out', dropping OVS_ACTION_ATTR_OUTPUT and
583 * OVS_ACTION_ATTR_RECIRC along the way. */
584static void
585prune_output_actions(const struct ofpbuf *in, struct ofpbuf *out)
586{
587 const struct nlattr *a;
588 unsigned int left;
589 NL_ATTR_FOR_EACH (a, left, in->data, in->size) {
590 if (a->nla_type == OVS_ACTION_ATTR_CLONE) {
591 struct ofpbuf in_nested;
592 nl_attr_get_nested(a, &in_nested);
593
594 size_t ofs = nl_msg_start_nested(out, OVS_ACTION_ATTR_CLONE);
595 prune_output_actions(&in_nested, out);
596 nl_msg_end_nested(out, ofs);
597 } else if (a->nla_type != OVS_ACTION_ATTR_OUTPUT &&
598 a->nla_type != OVS_ACTION_ATTR_RECIRC) {
599 ofpbuf_put(out, a, NLA_ALIGN(a->nla_len));
600 }
601 }
602}
603
604/* Executes all of the datapath actions, except for any OVS_ACTION_ATTR_OUTPUT
605 * and OVS_ACTION_ATTR_RECIRC actions, in 'actions' on 'packet', which has the
606 * given 'flow', on 'dpif'. The actions have slow path reason 'slow' (if any).
607 * Appends any error message to 'output'.
608 *
609 * With output and recirculation actions dropped, the only remaining side
610 * effects are from OVS_ACTION_ATTR_USERSPACE actions for executing actions to
611 * send a packet to an OpenFlow controller, IPFIX, NetFlow, and sFlow, etc. */
612static void
613execute_actions_except_outputs(struct dpif *dpif,
614 const struct dp_packet *packet,
615 const struct flow *flow,
616 const struct ofpbuf *actions,
617 enum slow_path_reason slow,
618 struct ds *output)
619{
620 struct ofpbuf pruned_actions;
621 ofpbuf_init(&pruned_actions, 0);
622 prune_output_actions(actions, &pruned_actions);
623
624 struct dpif_execute execute = {
625 .actions = pruned_actions.data,
626 .actions_len = pruned_actions.size,
627 .needs_help = (slow & SLOW_ACTION) != 0,
628 .flow = flow,
629 .packet = dp_packet_clone_with_headroom(packet, 2),
630 };
631 int error = dpif_execute(dpif, &execute);
632 if (error) {
633 ds_put_format(output, "\nAction execution failed (%s)\n.",
634 ovs_strerror(error));
635 }
636 dp_packet_delete(execute.packet);
637 ofpbuf_uninit(&pruned_actions);
638}
639
d13ee228 640static void
e6bc8e74
YHW
641ofproto_trace__(struct ofproto_dpif *ofproto, const struct flow *flow,
642 const struct dp_packet *packet, struct ovs_list *recirc_queue,
643 const struct ofpact ofpacts[], size_t ofpacts_len,
644 struct ds *output)
d13ee228 645{
2d9b49dd
BP
646 struct ofpbuf odp_actions;
647 ofpbuf_init(&odp_actions, 0);
d13ee228 648
2d9b49dd
BP
649 struct xlate_in xin;
650 struct flow_wildcards wc;
651 struct ovs_list trace = OVS_LIST_INITIALIZER(&trace);
652 xlate_in_init(&xin, ofproto,
d13ee228
BP
653 ofproto_dpif_get_tables_version(ofproto), flow,
654 flow->in_port.ofp_port, NULL, ntohs(flow->tcp_flags),
2d9b49dd
BP
655 packet, &wc, &odp_actions);
656 xin.ofpacts = ofpacts;
657 xin.ofpacts_len = ofpacts_len;
658 xin.trace = &trace;
e6bc8e74 659 xin.recirc_queue = recirc_queue;
2d9b49dd
BP
660
661 /* Copy initial flow out of xin.flow. It differs from '*flow' because
662 * xlate_in_init() initializes actset_output to OFPP_UNSET. */
663 struct flow initial_flow = xin.flow;
664 ds_put_cstr(output, "Flow: ");
50f96b10 665 flow_format(output, &initial_flow, NULL);
2d9b49dd
BP
666 ds_put_char(output, '\n');
667
668 struct xlate_out xout;
669 enum xlate_error error = xlate_actions(&xin, &xout);
670
671 oftrace_node_print_details(output, &trace, 0);
672
673 ds_put_cstr(output, "\nFinal flow: ");
674 if (flow_equal(&initial_flow, &xin.flow)) {
675 ds_put_cstr(output, "unchanged");
676 } else {
50f96b10 677 flow_format(output, &xin.flow, NULL);
2d9b49dd
BP
678 }
679 ds_put_char(output, '\n');
d13ee228 680
2d9b49dd
BP
681 ds_put_cstr(output, "Megaflow: ");
682 struct match match;
683 match_init(&match, flow, &wc);
50f96b10 684 match_format(&match, NULL, output, OFP_DEFAULT_PRIORITY);
2d9b49dd 685 ds_put_char(output, '\n');
d13ee228 686
2d9b49dd 687 ds_put_cstr(output, "Datapath actions: ");
0722f341 688 format_odp_actions(output, odp_actions.data, odp_actions.size, NULL);
d13ee228
BP
689
690 if (error != XLATE_OK) {
2d9b49dd
BP
691 ds_put_format(output,
692 "\nTranslation failed (%s), packet is dropped.\n",
d13ee228 693 xlate_strerror(error));
418a7a84
BP
694 } else {
695 if (xout.slow) {
696 explain_slow_path(xout.slow, output);
697 }
698 if (packet) {
699 execute_actions_except_outputs(ofproto->backer->dpif, packet,
700 &initial_flow, &odp_actions,
701 xout.slow, output);
d13ee228
BP
702 }
703 }
704
418a7a84 705
2d9b49dd
BP
706 xlate_out_uninit(&xout);
707 ofpbuf_uninit(&odp_actions);
708 oftrace_node_list_destroy(&trace);
d13ee228
BP
709}
710
e6bc8e74
YHW
711/* Implements a "trace" through 'ofproto''s flow table, appending a textual
712 * description of the results to 'output'.
713 *
714 * The trace follows a packet with the specified 'flow' through the flow
715 * table. 'packet' may be nonnull to trace an actual packet, with consequent
716 * side effects (if it is nonnull then its flow must be 'flow').
717 *
718 * If 'ofpacts' is nonnull then its 'ofpacts_len' bytes specify the actions to
719 * trace, otherwise the actions are determined by a flow table lookup. */
d1ea2cc3 720void
e6bc8e74
YHW
721ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
722 const struct dp_packet *packet,
723 const struct ofpact ofpacts[], size_t ofpacts_len,
0f2f05bb 724 struct ovs_list *next_ct_states, struct ds *output)
e6bc8e74
YHW
725{
726 struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue);
727 ofproto_trace__(ofproto, flow, packet, &recirc_queue,
728 ofpacts, ofpacts_len, output);
729
730 struct oftrace_recirc_node *recirc_node;
731 LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) {
732 ds_put_cstr(output, "\n\n");
733 ds_put_char_multiple(output, '=', 79);
734 ds_put_format(output, "\nrecirc(%#"PRIx32")",
735 recirc_node->recirc_id);
0f2f05bb 736
3782d8ef 737 if (next_ct_states && recirc_node->type == OFT_RECIRC_CONNTRACK) {
0f2f05bb
YHW
738 uint32_t ct_state;
739 if (ovs_list_is_empty(next_ct_states)) {
740 ct_state = CS_TRACKED | CS_NEW;
741 ds_put_cstr(output, " - resume conntrack with default "
742 "ct_state=trk|new (use --ct-next to customize)");
743 } else {
744 ct_state = oftrace_pop_ct_state(next_ct_states);
745 struct ds s = DS_EMPTY_INITIALIZER;
746 format_flags(&s, ct_state_to_string, ct_state, '|');
747 ds_put_format(output, " - resume conntrack with ct_state=%s",
748 ds_cstr(&s));
749 ds_destroy(&s);
750 }
751 recirc_node->flow.ct_state = ct_state;
e6bc8e74
YHW
752 }
753 ds_put_char(output, '\n');
754 ds_put_char_multiple(output, '=', 79);
755 ds_put_cstr(output, "\n\n");
756
757 ofproto_trace__(ofproto, &recirc_node->flow, recirc_node->packet,
758 &recirc_queue, ofpacts, ofpacts_len, output);
759 oftrace_recirc_node_destroy(recirc_node);
760 }
761}
762
d13ee228
BP
763void
764ofproto_dpif_trace_init(void)
765{
766 static bool registered;
767 if (registered) {
768 return;
769 }
770 registered = true;
771
772 unixctl_command_register(
773 "ofproto/trace",
0f2f05bb
YHW
774 "{[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
775 "[-generate|packet]", 1, INT_MAX, ofproto_unixctl_trace, NULL);
d13ee228
BP
776 unixctl_command_register(
777 "ofproto/trace-packet-out",
0f2f05bb
YHW
778 "[-consistent] {[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
779 "[-generate|packet] actions",
780 2, INT_MAX, ofproto_unixctl_trace_actions, NULL);
d13ee228 781}