Introduce the scheleton of what will be the upcall tracing infrastructure. Two commands are created upcall/trace/create: creates a upcall_tracing instance attached to a udpif upcall/trace/show: displays all the upcall_tracing instances upcall/trace/delete: deletes all the upcall_tracing instances
Signed-off-by: Adrian Moreno <[email protected]> --- ofproto/automake.mk | 2 + ofproto/ofproto-dpif-upcall-trace.c | 90 +++++++++++++++++++++++++++++ ofproto/ofproto-dpif-upcall-trace.h | 33 +++++++++++ ofproto/ofproto-dpif-upcall.c | 89 ++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 ofproto/ofproto-dpif-upcall-trace.c create mode 100644 ofproto/ofproto-dpif-upcall-trace.h diff --git a/ofproto/automake.mk b/ofproto/automake.mk index cb1361b8a..c1062f5b3 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -44,6 +44,8 @@ ofproto_libofproto_la_SOURCES = \ ofproto/ofproto-dpif-trace.h \ ofproto/ofproto-dpif-upcall.c \ ofproto/ofproto-dpif-upcall.h \ + ofproto/ofproto-dpif-upcall-trace.c \ + ofproto/ofproto-dpif-upcall-trace.h \ ofproto/ofproto-dpif-xlate.c \ ofproto/ofproto-dpif-xlate.h \ ofproto/ofproto-provider.h \ diff --git a/ofproto/ofproto-dpif-upcall-trace.c b/ofproto/ofproto-dpif-upcall-trace.c new file mode 100644 index 000000000..94f158cf9 --- /dev/null +++ b/ofproto/ofproto-dpif-upcall-trace.c @@ -0,0 +1,90 @@ +#include <config.h> + +#include "ofproto-dpif-upcall-trace.h" + +#include <openvswitch/dynamic-string.h> +#include <openvswitch/ofp-flow.h> +#include <openvswitch/ofp-port.h> +#include <openvswitch/vlog.h> +#include "ofproto-dpif.h" + +VLOG_DEFINE_THIS_MODULE(upcall_trace); + +char * OVS_WARN_UNUSED_RESULT +upcall_tracing_create(int argc, const char *argv[], + struct ofproto_dpif **ofprotop, + struct upcall_tracing **tracingp) +{ + struct ofputil_port_map port_map = OFPUTIL_PORT_MAP_INITIALIZER(&port_map); + struct upcall_tracing *tracing = xzalloc(sizeof *tracing); + struct ofproto_dpif *ofproto = NULL; + struct flow_wildcards wc_filter; + const struct ofport *ofport; + struct flow flow_filter; + char *error = NULL; + + ovs_mutex_init(&tracing->mutex); + ovs_list_init(&tracing->blocks); + tracing->n_blocks = 0; + tracing->last_trace_id = 0; + tracing->max_blocks = UPCALL_TRACE_DEFAULT_MAX_SIZE; + + if (argc < 3) { + error = xasprintf("Missing arguments"); + goto exit; + } + + ofproto = ofproto_dpif_lookup_by_name(argv[1]); + if (!ofproto) { + error = xasprintf("%s: unknown bridge", argv[1]); + goto exit; + } + + HMAP_FOR_EACH (ofport, hmap_node, &(ofproto->up.ports)) { + ofputil_port_map_put(&port_map, ofport->ofp_port, + netdev_get_name(ofport->netdev)); + } + + error = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL, argv[2], + &port_map); + if (error) { + goto exit; + } + match_init(&tracing->filter, &flow_filter, &wc_filter); + + +exit: + if (error) { + upcall_tracing_destroy(tracing); + *tracingp = NULL; + } else { + *ofprotop = ofproto; + *tracingp = tracing; + } + ofputil_port_map_destroy(&port_map); + return error; +} + +void +upcall_tracing_destroy(struct upcall_tracing *tracing) +{ + if (tracing) { + ovs_mutex_destroy(&tracing->mutex); + free(tracing); + } +} + +void +upcall_tracing_format(const struct upcall_tracing *tracing, struct ds *output) +{ + if (tracing) { + ovs_mutex_lock(&tracing->mutex); + ds_put_format(output, "enabled, max_traces=%"PRIuSIZE", " + "current=%"PRIuSIZE", filter: ", + tracing->max_blocks, tracing->n_blocks); + match_format(&tracing->filter, NULL, output, 0); + ovs_mutex_unlock(&tracing->mutex); + } else { + ds_put_cstr(output, "disabled"); + } +} diff --git a/ofproto/ofproto-dpif-upcall-trace.h b/ofproto/ofproto-dpif-upcall-trace.h new file mode 100644 index 000000000..150d48d29 --- /dev/null +++ b/ofproto/ofproto-dpif-upcall-trace.h @@ -0,0 +1,33 @@ +#ifndef OFPROTO_DPIF_UPCALL_TRACE_H +#define OFPROTO_DPIF_UPCALL_TRACE_H 1 + +#include "openvswitch/list.h" +#include "openvswitch/match.h" +#include "openvswitch/ofp-port.h" +#include "ovs-thread.h" + +struct flow; +struct ofproto_dpif; +struct xlate_in; +struct xlate_out; + +#define UPCALL_TRACE_DEFAULT_MAX_SIZE 64 + +/* upcall_tracing - The main upcall_tracing object configured by the user + * and that stores all the generated traces. */ +struct upcall_tracing { + /* Match filter (optional). */ + struct match filter; + + struct ovs_mutex mutex; + struct ovs_list blocks; /* List of upcall_trace_block, oldest first. */ + size_t n_blocks; + size_t max_blocks; + uint64_t last_trace_id; +}; +char * upcall_tracing_create(int argc, const char *argv[], + struct ofproto_dpif **ofprotop, + struct upcall_tracing **tracingp); +void upcall_tracing_destroy(struct upcall_tracing *); +void upcall_tracing_format(const struct upcall_tracing *, struct ds *); +#endif /*OFPROTO_DPIF_UPCALL_TRACE_H */ diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 8e4897202..20fa302a5 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -34,6 +34,7 @@ #include "openvswitch/ofpbuf.h" #include "ofproto-dpif-ipfix.h" #include "ofproto-dpif-sflow.h" +#include "ofproto-dpif-upcall-trace.h" #include "ofproto-dpif-xlate.h" #include "ofproto-dpif-xlate-cache.h" #include "ofproto-dpif-trace.h" @@ -196,6 +197,8 @@ struct udpif { size_t n_conns; /* Number of connections waiting. */ long long int offload_rebalance_time; /* Time of last offload rebalance */ + + OVSRCU_TYPE(struct upcall_tracing *) tracing; /* Tracing configuration. */ }; enum upcall_type { @@ -404,6 +407,13 @@ static void upcall_unixctl_resume(struct unixctl_conn *conn, int argc, static void upcall_unixctl_ofproto_detrace(struct unixctl_conn *, int argc, const char *argv[], void *aux); +static void upcall_unixctl_trace_create(struct unixctl_conn *, int argc, + const char *argv[], void *aux); +static void upcall_unixctl_trace_show(struct unixctl_conn *, int argc, + const char *argv[], void *aux); +static void upcall_unixctl_trace_delete(struct unixctl_conn *, int argc, + const char *argv[], void *aux); + static struct udpif_key *ukey_create_from_upcall(struct upcall *, struct flow_wildcards *); static int ukey_create_from_dpif_flow(const struct udpif *, @@ -482,6 +492,12 @@ udpif_init(void) upcall_unixctl_resume, NULL); unixctl_command_register("ofproto/detrace", "UFID [pmd=PMD-ID]", 1, 2, upcall_unixctl_ofproto_detrace, NULL); + unixctl_command_register("upcall/trace/create", "bridge flow", 2, 2, + upcall_unixctl_trace_create, NULL); + unixctl_command_register("upcall/trace/show", "", 0, 0, + upcall_unixctl_trace_show, NULL); + unixctl_command_register("upcall/trace/delete", "", 0, 1, + upcall_unixctl_trace_delete, NULL); ovsthread_once_done(&once); } } @@ -3411,6 +3427,79 @@ upcall_unixctl_ofproto_detrace(struct unixctl_conn *conn, int argc, ds_destroy(&ds); } +static void upcall_unixctl_trace_create(struct unixctl_conn *conn, int argc, + const char *argv[], + void *aux OVS_UNUSED) +{ + struct upcall_tracing *tracing; + struct ofproto_dpif *ofproto; + struct udpif *udpif; + char *error; + + error = upcall_tracing_create(argc, argv, &ofproto, &tracing); + if (error) { + unixctl_command_reply_error(conn, error); + free(error); + return; + } + + udpif = ofproto->backer->udpif; + struct upcall_tracing *old_tracing = + ovsrcu_get_protected(struct upcall_tracing *, &udpif->tracing); + + if (old_tracing) { + ovsrcu_postpone(upcall_tracing_destroy, old_tracing); + } + + ovsrcu_set(&udpif->tracing, tracing); + unixctl_command_reply(conn, ""); +} + +static void upcall_unixctl_trace_show(struct unixctl_conn *conn, + int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, + void *aux OVS_UNUSED) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + const struct shash_node **backers; + int i; + + backers = shash_sort(&all_dpif_backers); + for (i = 0; i < shash_count(&all_dpif_backers); i++) { + struct dpif_backer *backer = (struct dpif_backer *)(backers[i]->data); + struct upcall_tracing *tracing = + ovsrcu_get(struct upcall_tracing *, &backer->udpif->tracing); + ds_put_format(&ds, "%s: ", dpif_name(backer->dpif)); + upcall_tracing_format(tracing, &ds); + ds_put_cstr(&ds, "\n"); + } + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); +} + +static void upcall_unixctl_trace_delete(struct unixctl_conn *conn, + int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, + void *aux OVS_UNUSED) +{ + const struct shash_node **backers; + int i; + + backers = shash_sort(&all_dpif_backers); + for (i = 0; i < shash_count(&all_dpif_backers); i++) { + struct dpif_backer *backer = (struct dpif_backer *)(backers[i]->data); + struct upcall_tracing *old_tracing = + ovsrcu_get_protected(struct upcall_tracing *, + &backer->udpif->tracing); + + if (old_tracing) { + ovsrcu_postpone(upcall_tracing_destroy, old_tracing); + } + + ovsrcu_set(&backer->udpif->tracing, NULL); + } + unixctl_command_reply(conn, ""); +} /* Flows are sorted in the following order: * netdev, flow state (offloaded/kernel path), flow_pps_rate. -- 2.53.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
