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

Reply via email to