vici: Add 'get|reset-counters' commands
authorTobias Brunner <tobias@strongswan.org>
Thu, 24 Aug 2017 15:41:37 +0000 (17:41 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Nov 2017 15:28:28 +0000 (16:28 +0100)
src/libcharon/plugins/vici/Makefile.am
src/libcharon/plugins/vici/README.md
src/libcharon/plugins/vici/vici_plugin.c
src/libcharon/plugins/vici/vici_query.c

index af0b65c..e8bcdba 100644 (file)
@@ -2,6 +2,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/libstrongswan \
        -I$(top_srcdir)/src/libstrongswan/plugins/pubkey \
        -I$(top_srcdir)/src/libcharon \
+       -I$(top_srcdir)/src/libcharon/plugins/counters \
        -DSWANCTLDIR=\""${swanctldir}\"" \
        -DIPSEC_PIDDIR=\"${piddir}\"
 
index f47f80c..8352125 100644 (file)
@@ -682,6 +682,35 @@ List currently loaded algorithms and their implementation.
                }
        }
 
+### get-counters() ###
+
+List global or connection-specific counters for several IKE events.
+
+       {
+               name = <optional connection name, omit for global counters>
+               all = <yes to get counters for all connections, name is ignored>
+       } => {
+               counters = {
+                       <name|empty for global counters> = {
+                               <pairs of counter name and 64-bit counter value>
+                       }
+               }
+               success = <yes or no>
+               errmsg = <error string on failure>
+       }
+
+### reset-counters() ###
+
+Reset global or connection-specific IKE event counters.
+
+       {
+               name = <optional connection name, omit for global counters>
+               all = <yes to reset counters for all connections, name is ignored>
+       } => {
+               success = <yes or no>
+               errmsg = <error string on failure>
+       }
+
 ## Server-issued events ##
 
 Based on the packet layer, the vici plugin raises event messages using named
index 1366512..53da75e 100644 (file)
@@ -176,6 +176,7 @@ METHOD(plugin_t, get_features, int,
        static plugin_feature_t f[] = {
                PLUGIN_CALLBACK((plugin_feature_callback_t)register_vici, NULL),
                        PLUGIN_PROVIDE(CUSTOM, "vici"),
+                               PLUGIN_SDEPEND(CUSTOM, "counters"),
        };
        *features = f;
        return countof(f);
index 2cc5959..134ea37 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2015 Tobias Brunner, Andreas Steffen
+ * Copyright (C) 2015-2017 Tobias Brunner
+ * Copyright (C) 2015 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * Copyright (C) 2014 Martin Willi
 #include <asn1/asn1.h>
 #include <credentials/certificates/certificate.h>
 #include <credentials/certificates/x509.h>
+#include <counters_query.h>
+
+ENUM(vici_counter_type_names,
+       COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
+       "ike-rekey-init",
+       "ike-rekey-resp",
+       "child-rekey",
+       "invalid",
+       "invalid-spi",
+       "ike-init-in-req",
+       "ike-init-in-resp",
+       "ike-init-out-req",
+       "ike-init-out-resp",
+       "ike-auth-in-req",
+       "ike-auth-in-resp",
+       "ike-auth-out-req",
+       "ike-auth-out-resp",
+       "create-child-in-req",
+       "create-child-in-resp",
+       "create-child-out-req",
+       "create-child-out-resp",
+       "info-in-req",
+       "info-in-resp",
+       "info-out-req",
+       "info-out-resp",
+);
 
 typedef struct private_vici_query_t private_vici_query_t;
 
@@ -74,6 +101,11 @@ struct private_vici_query_t {
        vici_dispatcher_t *dispatcher;
 
        /**
+        * Query interface for counters
+        */
+       counters_query_t *counters;
+
+       /**
         * Daemon startup timestamp
         */
        time_t uptime;
@@ -1223,6 +1255,131 @@ CALLBACK(get_algorithms, vici_message_t*,
        return b->finalize(b);
 }
 
+/**
+ * Make sure we have the counters query interface
+ */
+static inline bool ensure_counters(private_vici_query_t *this)
+{
+       if (this->counters)
+       {
+               return TRUE;
+       }
+       return (this->counters = lib->get(lib, "counters")) != NULL;
+}
+
+/**
+ * Add a single set of counters to the message
+ *
+ * Frees the array of counter values
+ */
+static void add_counters(vici_builder_t *b, char *name, uint64_t *counters)
+{
+       char buf[BUF_LEN];
+       counter_type_t i;
+
+       b->begin_section(b, name ?: "");
+       for (i = 0; i < COUNTER_MAX; i++)
+       {
+               snprintf(buf, sizeof(buf), "%N", vici_counter_type_names, i);
+               b->add_kv(b, buf, "%"PRIu64, counters[i]);
+       }
+       b->end_section(b);
+       free(counters);
+}
+
+CALLBACK(get_counters, vici_message_t*,
+       private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+       vici_builder_t *b;
+       enumerator_t *enumerator;
+       uint64_t *counters;
+       char *conn, *errmsg = NULL;
+       bool all;
+
+       b = vici_builder_create();
+
+       if (ensure_counters(this))
+       {
+               conn = request->get_str(request, NULL, "name");
+               all = request->get_bool(request, FALSE, "all");
+
+               b->begin_section(b, "counters");
+               if (all)
+               {
+                       enumerator = this->counters->get_names(this->counters);
+                       while (enumerator->enumerate(enumerator, &conn))
+                       {
+                               counters = this->counters->get_all(this->counters, conn);
+                               if (counters)
+                               {
+                                       add_counters(b, conn, counters);
+                               }
+                       }
+                       enumerator->destroy(enumerator);
+               }
+               else
+               {
+                       counters = this->counters->get_all(this->counters, conn);
+                       if (counters)
+                       {
+                               add_counters(b, conn, counters);
+                       }
+                       else
+                       {
+                               errmsg = "no counters found for this connection";
+                       }
+               }
+               b->end_section(b);
+       }
+       else
+       {
+               errmsg = "no counters available (plugin missing?)";
+       }
+
+       b->add_kv(b, "success", errmsg ? "no" : "yes");
+       if (errmsg)
+       {
+               b->add_kv(b, "errmsg", "%s", errmsg);
+       }
+       return b->finalize(b);
+}
+
+CALLBACK(reset_counters, vici_message_t*,
+       private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+       vici_builder_t *b;
+       char *conn, *errmsg = NULL;
+       bool all;
+
+       b = vici_builder_create();
+
+       if (ensure_counters(this))
+       {
+               conn = request->get_str(request, NULL, "name");
+               all = request->get_bool(request, FALSE, "all");
+
+               if (all)
+               {
+                       this->counters->reset_all(this->counters);
+               }
+               else
+               {
+                       this->counters->reset(this->counters, conn);
+               }
+       }
+       else
+       {
+               errmsg = "no counters available (plugin missing?)";
+       }
+
+       b->add_kv(b, "success", errmsg ? "no" : "yes");
+       if (errmsg)
+       {
+               b->add_kv(b, "errmsg", "%s", errmsg);
+       }
+       return b->finalize(b);
+}
+
 CALLBACK(version, vici_message_t*,
        private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
 {
@@ -1423,6 +1580,8 @@ static void manage_commands(private_vici_query_t *this, bool reg)
        manage_command(this, "list-conns", list_conns, reg);
        manage_command(this, "list-certs", list_certs, reg);
        manage_command(this, "get-algorithms", get_algorithms, reg);
+       manage_command(this, "get-counters", get_counters, reg);
+       manage_command(this, "reset-counters", reset_counters, reg);
        manage_command(this, "version", version, reg);
        manage_command(this, "stats", stats, reg);
 }