]> git.proxmox.com Git - mirror_ovs.git/blame - ofproto/ofproto-dpif-trace.c
ovsdb: Use column diffs for ovsdb and raft log entries.
[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,
d072d2de 89 const struct ofpact_nat *ofn,
5fdd80cc
YHW
90 const struct dp_packet *packet, uint32_t recirc_id,
91 const uint16_t zone)
e6bc8e74
YHW
92{
93 if (!recirc_id_node_find_and_ref(recirc_id)) {
94 return false;
95 }
96
97 struct oftrace_recirc_node *node = xmalloc(sizeof *node);
98 ovs_list_push_back(recirc_queue, &node->node);
99
100 node->type = type;
101 node->recirc_id = recirc_id;
102 node->flow = *flow;
103 node->flow.recirc_id = recirc_id;
5fdd80cc 104 node->flow.ct_zone = zone;
d072d2de 105 node->nat_act = ofn;
e6bc8e74
YHW
106 node->packet = packet ? dp_packet_clone(packet) : NULL;
107
108 return true;
109}
110
111static void
112oftrace_recirc_node_destroy(struct oftrace_recirc_node *node)
113{
114 if (node) {
115 recirc_free_id(node->recirc_id);
116 dp_packet_delete(node->packet);
117 free(node);
118 }
119}
120
0f2f05bb
YHW
121static void
122oftrace_push_ct_state(struct ovs_list *next_ct_states, uint32_t ct_state)
123{
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);
128}
129
130static uint32_t
131oftrace_pop_ct_state(struct ovs_list *next_ct_states)
132{
133 struct oftrace_next_ct_state *s;
134 LIST_FOR_EACH_POP (s, node, next_ct_states) {
36e67140
YHW
135 uint32_t state = s->state;
136 free(s);
137 return state;
0f2f05bb
YHW
138 }
139 OVS_NOT_REACHED();
140}
141
d13ee228 142static void
2d9b49dd
BP
143oftrace_node_print_details(struct ds *output,
144 const struct ovs_list *nodes, int level)
d13ee228 145{
2d9b49dd
BP
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');
150 }
d13ee228 151
2d9b49dd
BP
152 bool more = (sub->node.next != nodes
153 || oftrace_node_type_is_terminal(sub->type));
154
155 ds_put_char_multiple(output, ' ', (level + more) * 4);
156 switch (sub->type) {
157 case OFT_DETAIL:
158 ds_put_format(output, " -> %s\n", sub->text);
159 break;
160 case OFT_WARN:
161 ds_put_format(output, " >> %s\n", sub->text);
162 break;
163 case OFT_ERROR:
164 ds_put_format(output, " >>>> %s <<<<\n", sub->text);
165 break;
166 case OFT_BRIDGE:
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');
171 break;
172 case OFT_TABLE:
fac4786a 173 case OFT_BUCKET:
2d9b49dd
BP
174 case OFT_THAW:
175 case OFT_ACTION:
176 ds_put_format(output, "%s\n", sub->text);
177 break;
d13ee228 178 }
d13ee228 179
2d9b49dd 180 oftrace_node_print_details(output, &sub->subs, level + more + more);
d13ee228 181 }
d13ee228
BP
182}
183
d072d2de
DC
184static void
185oftrace_print_ip_flow(const struct flow *flow, int af, struct ds *output)
186{
187 if (af == AF_INET) {
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));
199 }
200 ds_put_char(output, '\n');
201}
202
d13ee228
BP
203/* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
204 * forms are supported:
205 *
b490b189
BP
206 * - [options] [dpname] odp_flow [packet]
207 * - [options] bridge br_flow [packet]
d13ee228
BP
208 *
209 * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure
210 * returns a nonnull malloced error message. */
211static char * OVS_WARN_UNUSED_RESULT
212parse_flow_and_packet(int argc, const char *argv[],
213 struct ofproto_dpif **ofprotop, struct flow *flow,
0f2f05bb 214 struct dp_packet **packetp,
b490b189
BP
215 struct ovs_list *next_ct_states,
216 bool *consistent)
d13ee228
BP
217{
218 const struct dpif_backer *backer = NULL;
d40533fc 219 char *error = NULL;
d13ee228 220 struct simap port_names = SIMAP_INITIALIZER(&port_names);
b490b189 221 struct dp_packet *packet = NULL;
6f068379
BP
222 uint8_t *l7 = NULL;
223 size_t l7_len = 64;
d13ee228
BP
224 struct ofpbuf odp_key;
225 struct ofpbuf odp_mask;
226
227 ofpbuf_init(&odp_key, 0);
228 ofpbuf_init(&odp_mask, 0);
229
b490b189
BP
230 const char *args[3];
231 int n_args = 0;
232 bool generate_packet = false;
233 if (consistent) {
234 *consistent = false;
d13ee228 235 }
b490b189
BP
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;
6f068379
BP
240 } else if (!strcmp(arg, "--l7")) {
241 if (i + 1 >= argc) {
d40533fc 242 error = xasprintf("Missing argument for option %s", arg);
6f068379
BP
243 goto exit;
244 }
245
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);
d40533fc 251 error = xstrdup("Trailing garbage in packet data");
6f068379
BP
252 goto exit;
253 }
254 free(l7);
255 l7_len = dp_packet_size(&payload);
256 l7 = dp_packet_steal_data(&payload);
257 } else if (!strcmp(arg, "--l7-len")) {
258 if (i + 1 >= argc) {
d40533fc 259 error = xasprintf("Missing argument for option %s", arg);
6f068379
BP
260 goto exit;
261 }
262 free(l7);
263 l7 = NULL;
264 l7_len = atoi(argv[++i]);
265 if (l7_len > 64000) {
d40533fc 266 error = xasprintf("%s: too much L7 data", argv[i]);
6f068379
BP
267 goto exit;
268 }
b490b189
BP
269 } else if (consistent
270 && (!strcmp(arg, "-consistent") ||
271 !strcmp(arg, "--consistent"))) {
272 *consistent = true;
273 } else if (!strcmp(arg, "--ct-next")) {
274 if (i + 1 >= argc) {
d40533fc 275 error = xasprintf("Missing argument for option %s", arg);
b490b189
BP
276 goto exit;
277 }
d13ee228 278
b490b189
BP
279 uint32_t ct_state;
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)) {
d40533fc 283 error = ds_steal_cstr(&ds);
b490b189
BP
284 goto exit;
285 }
286 oftrace_push_ct_state(next_ct_states, ct_state);
287 } else if (arg[0] == '-') {
d40533fc 288 error = xasprintf("%s: unknown option", arg);
b490b189
BP
289 goto exit;
290 } else if (n_args >= ARRAY_SIZE(args)) {
d40533fc 291 error = xstrdup("too many arguments");
0f2f05bb 292 goto exit;
b490b189
BP
293 } else {
294 args[n_args++] = arg;
0f2f05bb 295 }
b490b189 296 }
0f2f05bb 297
b490b189
BP
298 /* 'args' must now have one of the following forms:
299 *
300 * odp_flow
301 * dpname odp_flow
302 * bridge br_flow
303 * odp_flow packet
304 * dpname odp_flow packet
305 * bridge br_flow packet
306 *
307 * Parse the packet if it's there. Note that:
308 *
309 * - If there is one argument, there cannot be a packet.
310 *
311 * - If there are three arguments, there must be a packet.
312 *
313 * If there is a packet, we strip it off.
314 */
315 if (!generate_packet && n_args > 1) {
d40533fc
BP
316 const char *const_error = eth_from_hex(args[n_args - 1], &packet);
317 if (!const_error) {
b490b189
BP
318 n_args--;
319 } else if (n_args > 2) {
320 /* The 3-argument form must end in a hex string. */
d40533fc 321 error = xstrdup(const_error);
0f2f05bb
YHW
322 goto exit;
323 }
0f2f05bb
YHW
324 }
325
b490b189
BP
326 /* We stripped off the packet if there was one, so 'args' now has one of
327 * the following forms:
328 *
329 * odp_flow
330 * dpname odp_flow
331 * bridge br_flow
332 *
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
336 * the flow. */
337 if (n_args == 2) {
338 /* args[0] might be dpname. */
d13ee228 339 const char *dp_type;
b490b189
BP
340 if (!strncmp(args[0], "ovs-", 4)) {
341 dp_type = args[0] + 4;
d13ee228 342 } else {
b490b189 343 dp_type = args[0];
d13ee228
BP
344 }
345 backer = shash_find_data(&all_dpif_backers, dp_type);
b490b189
BP
346 } else if (n_args == 1) {
347 /* Pick default backer. */
d13ee228
BP
348 struct shash_node *node;
349 if (shash_count(&all_dpif_backers) == 1) {
350 node = shash_first(&all_dpif_backers);
351 backer = node->data;
352 }
353 } else {
d40533fc 354 error = xstrdup("Syntax error");
d13ee228
BP
355 goto exit;
356 }
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));
363 }
364 }
365
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. */
b490b189 370 if (!odp_flow_from_string(args[n_args - 1], &port_names,
d40533fc 371 &odp_key, &odp_mask, &error)) {
d13ee228 372 if (!backer) {
d40533fc 373 error = xstrdup("Cannot find the datapath");
d13ee228
BP
374 goto exit;
375 }
376
d40533fc
BP
377 if (odp_flow_key_to_flow(odp_key.data, odp_key.size, flow, &error)
378 == ODP_FIT_ERROR) {
d13ee228
BP
379 goto exit;
380 }
381
382 *ofprotop = xlate_lookup_ofproto(backer, flow,
d40533fc 383 &flow->in_port.ofp_port, &error);
d13ee228 384 if (*ofprotop == NULL) {
d13ee228
BP
385 goto exit;
386 }
387
388 flow->tunnel.metadata.tab = ofproto_get_tun_tab(&(*ofprotop)->up);
389
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) {
396 struct flow_tnl tnl;
d13ee228 397 memcpy(&tnl, &flow->tunnel, sizeof tnl);
d40533fc
BP
398 int err = tun_metadata_from_geneve_udpif(
399 flow->tunnel.metadata.tab, &tnl, &tnl, &flow->tunnel);
d13ee228 400 if (err) {
d40533fc 401 error = xstrdup("Failed to parse Geneve options");
d13ee228
BP
402 goto exit;
403 }
404 }
d40533fc
BP
405 } else if (n_args != 2) {
406 char *s = error;
407 error = xasprintf("%s (or the bridge name was omitted)", s);
408 free(s);
409 goto exit;
d13ee228 410 } else {
d40533fc
BP
411 free(error);
412 error = NULL;
d13ee228 413
b490b189 414 *ofprotop = ofproto_dpif_lookup_by_name(args[0]);
d13ee228 415 if (!*ofprotop) {
d40533fc 416 error = xasprintf("%s: unknown bridge", args[0]);
d13ee228
BP
417 goto exit;
418 }
419
50f96b10
BP
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));
425 }
d40533fc
BP
426 char *err = parse_ofp_exact_flow(flow, NULL,
427 ofproto_get_tun_tab(&(*ofprotop)->up),
428 args[n_args - 1], &map);
50f96b10 429 ofputil_port_map_destroy(&map);
d13ee228 430 if (err) {
d40533fc 431 error = xasprintf("Bad openflow flow syntax: %s", err);
d13ee228
BP
432 free(err);
433 goto exit;
434 }
435 }
436
b490b189
BP
437 if (generate_packet) {
438 /* Generate a packet, as requested. */
439 packet = dp_packet_new(0);
6f068379 440 flow_compose(packet, flow, l7, l7_len);
b490b189
BP
441 } else if (packet) {
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);
d13ee228
BP
446 }
447
448exit:
d40533fc 449 if (error) {
d13ee228
BP
450 dp_packet_delete(packet);
451 packet = NULL;
452 }
453 *packetp = packet;
454 ofpbuf_uninit(&odp_key);
455 ofpbuf_uninit(&odp_mask);
456 simap_destroy(&port_names);
6f068379 457 free(l7);
d40533fc 458 return error;
d13ee228
BP
459}
460
0f2f05bb
YHW
461static void
462free_ct_states(struct ovs_list *ct_states)
463{
464 while (!ovs_list_is_empty(ct_states)) {
465 oftrace_pop_ct_state(ct_states);
466 }
467}
468
d13ee228
BP
469static void
470ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
471 void *aux OVS_UNUSED)
472{
473 struct ofproto_dpif *ofproto;
474 struct dp_packet *packet;
475 char *error;
476 struct flow flow;
0f2f05bb 477 struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states);
d13ee228 478
0f2f05bb 479 error = parse_flow_and_packet(argc, argv, &ofproto, &flow, &packet,
b490b189 480 &next_ct_states, NULL);
d13ee228
BP
481 if (!error) {
482 struct ds result;
483
484 ds_init(&result);
0f2f05bb
YHW
485 ofproto_trace(ofproto, &flow, packet, NULL, 0, &next_ct_states,
486 &result);
d13ee228
BP
487 unixctl_command_reply(conn, ds_cstr(&result));
488 ds_destroy(&result);
489 dp_packet_delete(packet);
490 } else {
491 unixctl_command_reply_error(conn, error);
492 free(error);
493 }
0f2f05bb 494 free_ct_states(&next_ct_states);
d13ee228
BP
495}
496
497static void
498ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc,
499 const char *argv[], void *aux OVS_UNUSED)
500{
501 enum ofputil_protocol usable_protocols;
502 struct ofproto_dpif *ofproto;
503 bool enforce_consistency;
504 struct ofpbuf ofpacts;
505 struct dp_packet *packet;
506 struct ds result;
67210a55 507 struct match match;
d13ee228 508 uint16_t in_port;
0f2f05bb 509 struct ovs_list next_ct_states = OVS_LIST_INITIALIZER(&next_ct_states);
d13ee228
BP
510
511 /* Three kinds of error return values! */
512 enum ofperr retval;
513 char *error;
514
515 packet = NULL;
516 ds_init(&result);
517 ofpbuf_init(&ofpacts, 0);
518
519 /* Parse actions. */
efefbcae
BP
520 struct ofpact_parse_params pp = {
521 .port_map = NULL,
522 .ofpacts = &ofpacts,
523 .usable_protocols = &usable_protocols,
524 };
525 error = ofpacts_parse_actions(argv[--argc], &pp);
d13ee228
BP
526 if (error) {
527 unixctl_command_reply_error(conn, error);
528 free(error);
529 goto exit;
530 }
531
0f2f05bb 532 error = parse_flow_and_packet(argc, argv, &ofproto, &match.flow, &packet,
b490b189 533 &next_ct_states, &enforce_consistency);
d13ee228
BP
534 if (error) {
535 unixctl_command_reply_error(conn, error);
536 free(error);
537 goto exit;
538 }
67210a55 539 match_wc_init(&match, &match.flow);
d13ee228
BP
540
541 /* Do the same checks as handle_packet_out() in ofproto.c.
542 *
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
547 * instructions.
548 *
549 * We skip the "meter" check here because meter is an instruction, not an
550 * action, and thus cannot appear in ofpacts. */
67210a55 551 in_port = ofp_to_u16(match.flow.in_port.ofp_port);
d13ee228
BP
552 if (in_port >= ofproto->up.max_ports && in_port < ofp_to_u16(OFPP_MAX)) {
553 unixctl_command_reply_error(conn, "invalid in_port");
554 goto exit;
555 }
ae6f7530
BP
556
557 struct ofpact_check_params cp = {
558 .match = &match,
559 .max_ports = u16_to_ofp(ofproto->up.max_ports),
560 .table_id = 0,
561 .n_tables = ofproto->up.n_tables,
562 };
563 retval = ofpacts_check_consistency(
564 ofpacts.data, ofpacts.size,
565 enforce_consistency ? usable_protocols : 0, &cp);
d13ee228 566 if (!retval) {
d61973d6 567 ovs_mutex_lock(&ofproto_mutex);
d13ee228
BP
568 retval = ofproto_check_ofpacts(&ofproto->up, ofpacts.data,
569 ofpacts.size);
d61973d6 570 ovs_mutex_unlock(&ofproto_mutex);
d13ee228
BP
571 }
572
573 if (retval) {
574 ds_clear(&result);
575 ds_put_format(&result, "Bad actions: %s", ofperr_to_string(retval));
576 unixctl_command_reply_error(conn, ds_cstr(&result));
577 goto exit;
578 }
579
67210a55 580 ofproto_trace(ofproto, &match.flow, packet,
0f2f05bb 581 ofpacts.data, ofpacts.size, &next_ct_states, &result);
d13ee228
BP
582 unixctl_command_reply(conn, ds_cstr(&result));
583
584exit:
585 ds_destroy(&result);
586 dp_packet_delete(packet);
587 ofpbuf_uninit(&ofpacts);
0f2f05bb 588 free_ct_states(&next_ct_states);
d13ee228
BP
589}
590
418a7a84
BP
591static void
592explain_slow_path(enum slow_path_reason slow, struct ds *output)
593{
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));
600 }
601}
602
603/* Copies ODP actions from 'in' to 'out', dropping OVS_ACTION_ATTR_OUTPUT and
604 * OVS_ACTION_ATTR_RECIRC along the way. */
605static void
606prune_output_actions(const struct ofpbuf *in, struct ofpbuf *out)
607{
608 const struct nlattr *a;
609 unsigned int left;
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);
614
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));
621 }
622 }
623}
624
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'.
629 *
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. */
633static void
634execute_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,
639 struct ds *output)
640{
641 struct ofpbuf pruned_actions;
642 ofpbuf_init(&pruned_actions, 0);
643 prune_output_actions(actions, &pruned_actions);
644
645 struct dpif_execute execute = {
646 .actions = pruned_actions.data,
647 .actions_len = pruned_actions.size,
648 .needs_help = (slow & SLOW_ACTION) != 0,
649 .flow = flow,
650 .packet = dp_packet_clone_with_headroom(packet, 2),
651 };
652 int error = dpif_execute(dpif, &execute);
653 if (error) {
654 ds_put_format(output, "\nAction execution failed (%s)\n.",
655 ovs_strerror(error));
656 }
657 dp_packet_delete(execute.packet);
658 ofpbuf_uninit(&pruned_actions);
659}
660
d072d2de
DC
661static void
662ofproto_trace_recirc_node(struct oftrace_recirc_node *node,
663 struct ovs_list *next_ct_states,
664 struct ds *output)
665{
666 ds_put_cstr(output, "\n\n");
667 ds_put_char_multiple(output, '=', 79);
668 ds_put_format(output, "\nrecirc(%#"PRIx32")", node->recirc_id);
669
670 if (next_ct_states && node->type == OFT_RECIRC_CONNTRACK) {
671 uint32_t ct_state;
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)");
676 } else {
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",
681 ds_cstr(&s));
682 ds_destroy(&s);
683 }
684 node->flow.ct_state = ct_state;
685 }
686 ds_put_char(output, '\n');
687
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
690 * on.
691 */
692 if (node->nat_act) {
693 const struct ofpact_nat *ofn = node->nat_act;
694
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);
698
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;
704 }
705
706 if (ofn->range_af != AF_UNSPEC && ofn->range.proto.min) {
707 node->flow.tp_src = htons(ofn->range.proto.min);
708 }
709 }
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;
715 }
716
717 if (ofn->range_af != AF_UNSPEC && ofn->range.proto.min) {
718 node->flow.tp_dst = htons(ofn->range.proto.min);
719 }
720 }
721 ds_put_cstr(output, " Modified flow: ");
722 oftrace_print_ip_flow(&node->flow, ofn->range_af, output);
723 }
724 ds_put_char_multiple(output, '=', 79);
725 ds_put_cstr(output, "\n\n");
726}
727
d13ee228 728static void
e6bc8e74
YHW
729ofproto_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,
732 struct ds *output)
d13ee228 733{
2d9b49dd
BP
734 struct ofpbuf odp_actions;
735 ofpbuf_init(&odp_actions, 0);
d13ee228 736
2d9b49dd
BP
737 struct xlate_in xin;
738 struct flow_wildcards wc;
739 struct ovs_list trace = OVS_LIST_INITIALIZER(&trace);
740 xlate_in_init(&xin, ofproto,
d13ee228
BP
741 ofproto_dpif_get_tables_version(ofproto), flow,
742 flow->in_port.ofp_port, NULL, ntohs(flow->tcp_flags),
2d9b49dd
BP
743 packet, &wc, &odp_actions);
744 xin.ofpacts = ofpacts;
745 xin.ofpacts_len = ofpacts_len;
746 xin.trace = &trace;
e6bc8e74 747 xin.recirc_queue = recirc_queue;
2d9b49dd
BP
748
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: ");
50f96b10 753 flow_format(output, &initial_flow, NULL);
2d9b49dd
BP
754 ds_put_char(output, '\n');
755
756 struct xlate_out xout;
757 enum xlate_error error = xlate_actions(&xin, &xout);
758
759 oftrace_node_print_details(output, &trace, 0);
760
761 ds_put_cstr(output, "\nFinal flow: ");
762 if (flow_equal(&initial_flow, &xin.flow)) {
763 ds_put_cstr(output, "unchanged");
764 } else {
50f96b10 765 flow_format(output, &xin.flow, NULL);
2d9b49dd
BP
766 }
767 ds_put_char(output, '\n');
d13ee228 768
2d9b49dd
BP
769 ds_put_cstr(output, "Megaflow: ");
770 struct match match;
771 match_init(&match, flow, &wc);
50f96b10 772 match_format(&match, NULL, output, OFP_DEFAULT_PRIORITY);
2d9b49dd 773 ds_put_char(output, '\n');
d13ee228 774
2d9b49dd 775 ds_put_cstr(output, "Datapath actions: ");
0722f341 776 format_odp_actions(output, odp_actions.data, odp_actions.size, NULL);
d13ee228
BP
777
778 if (error != XLATE_OK) {
2d9b49dd
BP
779 ds_put_format(output,
780 "\nTranslation failed (%s), packet is dropped.\n",
d13ee228 781 xlate_strerror(error));
418a7a84
BP
782 } else {
783 if (xout.slow) {
784 explain_slow_path(xout.slow, output);
785 }
786 if (packet) {
787 execute_actions_except_outputs(ofproto->backer->dpif, packet,
788 &initial_flow, &odp_actions,
789 xout.slow, output);
d13ee228
BP
790 }
791 }
792
418a7a84 793
2d9b49dd
BP
794 xlate_out_uninit(&xout);
795 ofpbuf_uninit(&odp_actions);
796 oftrace_node_list_destroy(&trace);
d13ee228
BP
797}
798
e6bc8e74
YHW
799/* Implements a "trace" through 'ofproto''s flow table, appending a textual
800 * description of the results to 'output'.
801 *
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').
805 *
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. */
d1ea2cc3 808void
e6bc8e74
YHW
809ofproto_trace(struct ofproto_dpif *ofproto, const struct flow *flow,
810 const struct dp_packet *packet,
811 const struct ofpact ofpacts[], size_t ofpacts_len,
0f2f05bb 812 struct ovs_list *next_ct_states, struct ds *output)
e6bc8e74
YHW
813{
814 struct ovs_list recirc_queue = OVS_LIST_INITIALIZER(&recirc_queue);
815 ofproto_trace__(ofproto, flow, packet, &recirc_queue,
816 ofpacts, ofpacts_len, output);
817
818 struct oftrace_recirc_node *recirc_node;
819 LIST_FOR_EACH_POP (recirc_node, node, &recirc_queue) {
d072d2de 820 ofproto_trace_recirc_node(recirc_node, next_ct_states, output);
e6bc8e74
YHW
821 ofproto_trace__(ofproto, &recirc_node->flow, recirc_node->packet,
822 &recirc_queue, ofpacts, ofpacts_len, output);
823 oftrace_recirc_node_destroy(recirc_node);
824 }
825}
826
d13ee228
BP
827void
828ofproto_dpif_trace_init(void)
829{
830 static bool registered;
831 if (registered) {
832 return;
833 }
834 registered = true;
835
836 unixctl_command_register(
837 "ofproto/trace",
0f2f05bb
YHW
838 "{[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
839 "[-generate|packet]", 1, INT_MAX, ofproto_unixctl_trace, NULL);
d13ee228
BP
840 unixctl_command_register(
841 "ofproto/trace-packet-out",
0f2f05bb
YHW
842 "[-consistent] {[dp_name] odp_flow | bridge br_flow} [OPTIONS...] "
843 "[-generate|packet] actions",
844 2, INT_MAX, ofproto_unixctl_trace_actions, NULL);
d13ee228 845}