2 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 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.
19 #include "ofproto-dpif-trace.h"
22 #include "ofproto-dpif-xlate.h"
23 #include "openvswitch/ofp-parse.h"
26 static void ofproto_trace(struct ofproto_dpif
*, struct flow
*,
27 const struct dp_packet
*packet
,
28 const struct ofpact
[], size_t ofpacts_len
,
30 static void oftrace_node_destroy(struct oftrace_node
*);
32 /* Creates a new oftrace_node, populates it with the given 'type' and a copy of
33 * 'text', and appends it to list 'super'. The caller retains ownership of
36 oftrace_report(struct ovs_list
*super
, enum oftrace_node_type type
,
39 struct oftrace_node
*node
= xmalloc(sizeof *node
);
40 ovs_list_push_back(super
, &node
->node
);
42 node
->text
= xstrdup(text
);
43 ovs_list_init(&node
->subs
);
49 oftrace_node_type_is_terminal(enum oftrace_node_type type
)
68 oftrace_node_list_destroy(struct ovs_list
*nodes
)
71 struct oftrace_node
*node
, *next
;
72 LIST_FOR_EACH_SAFE (node
, next
, node
, nodes
) {
73 ovs_list_remove(&node
->node
);
74 oftrace_node_destroy(node
);
80 oftrace_node_destroy(struct oftrace_node
*node
)
83 oftrace_node_list_destroy(&node
->subs
);
90 oftrace_node_print_details(struct ds
*output
,
91 const struct ovs_list
*nodes
, int level
)
93 const struct oftrace_node
*sub
;
94 LIST_FOR_EACH (sub
, node
, nodes
) {
95 if (sub
->type
== OFT_BRIDGE
) {
96 ds_put_char(output
, '\n');
99 bool more
= (sub
->node
.next
!= nodes
100 || oftrace_node_type_is_terminal(sub
->type
));
102 ds_put_char_multiple(output
, ' ', (level
+ more
) * 4);
105 ds_put_format(output
, " -> %s\n", sub
->text
);
108 ds_put_format(output
, " >> %s\n", sub
->text
);
111 ds_put_format(output
, " >>>> %s <<<<\n", sub
->text
);
114 ds_put_format(output
, "%s\n", sub
->text
);
115 ds_put_char_multiple(output
, ' ', (level
+ more
) * 4);
116 ds_put_char_multiple(output
, '-', strlen(sub
->text
));
117 ds_put_char(output
, '\n');
122 ds_put_format(output
, "%s\n", sub
->text
);
126 oftrace_node_print_details(output
, &sub
->subs
, level
+ more
+ more
);
130 /* Parses the 'argc' elements of 'argv', ignoring argv[0]. The following
131 * forms are supported:
133 * - [dpname] odp_flow [-generate | packet]
134 * - bridge br_flow [-generate | packet]
136 * On success, initializes '*ofprotop' and 'flow' and returns NULL. On failure
137 * returns a nonnull malloced error message. */
138 static char * OVS_WARN_UNUSED_RESULT
139 parse_flow_and_packet(int argc
, const char *argv
[],
140 struct ofproto_dpif
**ofprotop
, struct flow
*flow
,
141 struct dp_packet
**packetp
)
143 const struct dpif_backer
*backer
= NULL
;
144 const char *error
= NULL
;
146 struct simap port_names
= SIMAP_INITIALIZER(&port_names
);
147 struct dp_packet
*packet
;
148 struct ofpbuf odp_key
;
149 struct ofpbuf odp_mask
;
151 ofpbuf_init(&odp_key
, 0);
152 ofpbuf_init(&odp_mask
, 0);
154 /* Handle "-generate" or a hex string as the last argument. */
155 if (!strcmp(argv
[argc
- 1], "-generate")) {
156 packet
= dp_packet_new(0);
159 error
= eth_from_hex(argv
[argc
- 1], &packet
);
162 } else if (argc
== 4) {
163 /* The 3-argument form must end in "-generate' or a hex string. */
169 /* odp_flow can have its in_port specified as a name instead of port no.
170 * We do not yet know whether a given flow is a odp_flow or a br_flow.
171 * But, to know whether a flow is odp_flow through odp_flow_from_string(),
172 * we need to create a simap of name to port no. */
175 if (!strncmp(argv
[1], "ovs-", 4)) {
176 dp_type
= argv
[1] + 4;
180 backer
= shash_find_data(&all_dpif_backers
, dp_type
);
181 } else if (argc
== 2) {
182 struct shash_node
*node
;
183 if (shash_count(&all_dpif_backers
) == 1) {
184 node
= shash_first(&all_dpif_backers
);
188 error
= "Syntax error";
191 if (backer
&& backer
->dpif
) {
192 struct dpif_port dpif_port
;
193 struct dpif_port_dump port_dump
;
194 DPIF_PORT_FOR_EACH (&dpif_port
, &port_dump
, backer
->dpif
) {
195 simap_put(&port_names
, dpif_port
.name
,
196 odp_to_u32(dpif_port
.port_no
));
200 /* Parse the flow and determine whether a datapath or
201 * bridge is specified. If function odp_flow_key_from_string()
202 * returns 0, the flow is a odp_flow. If function
203 * parse_ofp_exact_flow() returns NULL, the flow is a br_flow. */
204 if (!odp_flow_from_string(argv
[argc
- 1], &port_names
,
205 &odp_key
, &odp_mask
)) {
207 error
= "Cannot find the datapath";
211 if (odp_flow_key_to_flow(odp_key
.data
, odp_key
.size
, flow
) == ODP_FIT_ERROR
) {
212 error
= "Failed to parse datapath flow key";
216 *ofprotop
= xlate_lookup_ofproto(backer
, flow
,
217 &flow
->in_port
.ofp_port
);
218 if (*ofprotop
== NULL
) {
219 error
= "Invalid datapath flow";
223 flow
->tunnel
.metadata
.tab
= ofproto_get_tun_tab(&(*ofprotop
)->up
);
225 /* Convert Geneve options to OpenFlow format now. This isn't actually
226 * required in order to get the right results since the ofproto xlate
227 * actions will handle this for us. However, converting now ensures
228 * that our formatting code will always be able to consistently print
229 * in OpenFlow format, which is what we use here. */
230 if (flow
->tunnel
.flags
& FLOW_TNL_F_UDPIF
) {
234 memcpy(&tnl
, &flow
->tunnel
, sizeof tnl
);
235 err
= tun_metadata_from_geneve_udpif(flow
->tunnel
.metadata
.tab
,
236 &tnl
, &tnl
, &flow
->tunnel
);
238 error
= "Failed to parse Geneve options";
246 error
= "Must specify bridge name";
250 *ofprotop
= ofproto_dpif_lookup(argv
[1]);
252 error
= "Unknown bridge name";
256 struct ofputil_port_map map
= OFPUTIL_PORT_MAP_INITIALIZER(&map
);
257 const struct ofport
*ofport
;
258 HMAP_FOR_EACH (ofport
, hmap_node
, &(*ofprotop
)->up
.ports
) {
259 ofputil_port_map_put(&map
, ofport
->ofp_port
,
260 netdev_get_name(ofport
->netdev
));
262 err
= parse_ofp_exact_flow(flow
, NULL
,
263 ofproto_get_tun_tab(&(*ofprotop
)->up
),
264 argv
[argc
- 1], &map
);
265 ofputil_port_map_destroy(&map
);
267 m_err
= xasprintf("Bad openflow flow syntax: %s", err
);
273 /* Generate a packet, if requested. */
275 if (!dp_packet_size(packet
)) {
276 flow_compose(packet
, flow
);
278 /* Use the metadata from the flow and the packet argument
279 * to reconstruct the flow. */
280 pkt_metadata_from_flow(&packet
->md
, flow
);
281 flow_extract(packet
, flow
);
286 if (error
&& !m_err
) {
287 m_err
= xstrdup(error
);
290 dp_packet_delete(packet
);
294 ofpbuf_uninit(&odp_key
);
295 ofpbuf_uninit(&odp_mask
);
296 simap_destroy(&port_names
);
301 ofproto_unixctl_trace(struct unixctl_conn
*conn
, int argc
, const char *argv
[],
302 void *aux OVS_UNUSED
)
304 struct ofproto_dpif
*ofproto
;
305 struct dp_packet
*packet
;
309 error
= parse_flow_and_packet(argc
, argv
, &ofproto
, &flow
, &packet
);
314 ofproto_trace(ofproto
, &flow
, packet
, NULL
, 0, &result
);
315 unixctl_command_reply(conn
, ds_cstr(&result
));
317 dp_packet_delete(packet
);
319 unixctl_command_reply_error(conn
, error
);
325 ofproto_unixctl_trace_actions(struct unixctl_conn
*conn
, int argc
,
326 const char *argv
[], void *aux OVS_UNUSED
)
328 enum ofputil_protocol usable_protocols
;
329 struct ofproto_dpif
*ofproto
;
330 bool enforce_consistency
;
331 struct ofpbuf ofpacts
;
332 struct dp_packet
*packet
;
337 /* Three kinds of error return values! */
343 ofpbuf_init(&ofpacts
, 0);
346 error
= ofpacts_parse_actions(argv
[--argc
], NULL
,
347 &ofpacts
, &usable_protocols
);
349 unixctl_command_reply_error(conn
, error
);
354 /* OpenFlow 1.1 and later suggest that the switch enforces certain forms of
355 * consistency between the flow and the actions. With -consistent, we
356 * enforce consistency even for a flow supported in OpenFlow 1.0. */
357 if (!strcmp(argv
[1], "-consistent")) {
358 enforce_consistency
= true;
362 enforce_consistency
= false;
365 error
= parse_flow_and_packet(argc
, argv
, &ofproto
, &match
.flow
, &packet
);
367 unixctl_command_reply_error(conn
, error
);
371 match_wc_init(&match
, &match
.flow
);
373 /* Do the same checks as handle_packet_out() in ofproto.c.
375 * We pass a 'table_id' of 0 to ofpacts_check(), which isn't
376 * strictly correct because these actions aren't in any table, but it's OK
377 * because it 'table_id' is used only to check goto_table instructions, but
378 * packet-outs take a list of actions and therefore it can't include
381 * We skip the "meter" check here because meter is an instruction, not an
382 * action, and thus cannot appear in ofpacts. */
383 in_port
= ofp_to_u16(match
.flow
.in_port
.ofp_port
);
384 if (in_port
>= ofproto
->up
.max_ports
&& in_port
< ofp_to_u16(OFPP_MAX
)) {
385 unixctl_command_reply_error(conn
, "invalid in_port");
388 if (enforce_consistency
) {
389 retval
= ofpacts_check_consistency(ofpacts
.data
, ofpacts
.size
, &match
,
390 u16_to_ofp(ofproto
->up
.max_ports
),
391 0, ofproto
->up
.n_tables
,
394 retval
= ofpacts_check(ofpacts
.data
, ofpacts
.size
, &match
,
395 u16_to_ofp(ofproto
->up
.max_ports
), 0,
396 ofproto
->up
.n_tables
, &usable_protocols
);
399 ovs_mutex_lock(&ofproto_mutex
);
400 retval
= ofproto_check_ofpacts(&ofproto
->up
, ofpacts
.data
,
402 ovs_mutex_unlock(&ofproto_mutex
);
407 ds_put_format(&result
, "Bad actions: %s", ofperr_to_string(retval
));
408 unixctl_command_reply_error(conn
, ds_cstr(&result
));
412 ofproto_trace(ofproto
, &match
.flow
, packet
,
413 ofpacts
.data
, ofpacts
.size
, &result
);
414 unixctl_command_reply(conn
, ds_cstr(&result
));
418 dp_packet_delete(packet
);
419 ofpbuf_uninit(&ofpacts
);
422 /* Implements a "trace" through 'ofproto''s flow table, appending a textual
423 * description of the results to 'output'.
425 * The trace follows a packet with the specified 'flow' through the flow
426 * table. 'packet' may be nonnull to trace an actual packet, with consequent
427 * side effects (if it is nonnull then its flow must be 'flow').
429 * If 'ofpacts' is nonnull then its 'ofpacts_len' bytes specify the actions to
430 * trace, otherwise the actions are determined by a flow table lookup. */
432 ofproto_trace(struct ofproto_dpif
*ofproto
, struct flow
*flow
,
433 const struct dp_packet
*packet
,
434 const struct ofpact ofpacts
[], size_t ofpacts_len
,
437 struct ofpbuf odp_actions
;
438 ofpbuf_init(&odp_actions
, 0);
441 struct flow_wildcards wc
;
442 struct ovs_list trace
= OVS_LIST_INITIALIZER(&trace
);
443 xlate_in_init(&xin
, ofproto
,
444 ofproto_dpif_get_tables_version(ofproto
), flow
,
445 flow
->in_port
.ofp_port
, NULL
, ntohs(flow
->tcp_flags
),
446 packet
, &wc
, &odp_actions
);
447 xin
.ofpacts
= ofpacts
;
448 xin
.ofpacts_len
= ofpacts_len
;
451 /* Copy initial flow out of xin.flow. It differs from '*flow' because
452 * xlate_in_init() initializes actset_output to OFPP_UNSET. */
453 struct flow initial_flow
= xin
.flow
;
454 ds_put_cstr(output
, "Flow: ");
455 flow_format(output
, &initial_flow
, NULL
);
456 ds_put_char(output
, '\n');
458 struct xlate_out xout
;
459 enum xlate_error error
= xlate_actions(&xin
, &xout
);
461 oftrace_node_print_details(output
, &trace
, 0);
463 ds_put_cstr(output
, "\nFinal flow: ");
464 if (flow_equal(&initial_flow
, &xin
.flow
)) {
465 ds_put_cstr(output
, "unchanged");
467 flow_format(output
, &xin
.flow
, NULL
);
469 ds_put_char(output
, '\n');
471 ds_put_cstr(output
, "Megaflow: ");
473 match_init(&match
, flow
, &wc
);
474 match_format(&match
, NULL
, output
, OFP_DEFAULT_PRIORITY
);
475 ds_put_char(output
, '\n');
477 ds_put_cstr(output
, "Datapath actions: ");
478 format_odp_actions(output
, odp_actions
.data
, odp_actions
.size
);
480 if (error
!= XLATE_OK
) {
481 ds_put_format(output
,
482 "\nTranslation failed (%s), packet is dropped.\n",
483 xlate_strerror(error
));
484 } else if (xout
.slow
) {
485 enum slow_path_reason slow
;
487 ds_put_cstr(output
, "\nThis flow is handled by the userspace "
488 "slow path because it:");
492 enum slow_path_reason bit
= rightmost_1bit(slow
);
494 ds_put_format(output
, "\n\t- %s.",
495 slow_path_reason_to_explanation(bit
));
501 xlate_out_uninit(&xout
);
502 ofpbuf_uninit(&odp_actions
);
503 oftrace_node_list_destroy(&trace
);
507 ofproto_dpif_trace_init(void)
509 static bool registered
;
515 unixctl_command_register(
517 "{[dp_name] odp_flow | bridge br_flow} [-generate|packet]",
518 1, 3, ofproto_unixctl_trace
, NULL
);
519 unixctl_command_register(
520 "ofproto/trace-packet-out",
521 "[-consistent] {[dp_name] odp_flow | bridge br_flow} [-generate|packet] actions",
522 2, 6, ofproto_unixctl_trace_actions
, NULL
);