Add connection name specific stroke counters
authorMartin Willi <martin@revosec.ch>
Fri, 15 Mar 2013 09:41:04 +0000 (10:41 +0100)
committerMartin Willi <martin@revosec.ch>
Fri, 15 Mar 2013 09:41:04 +0000 (10:41 +0100)
src/libcharon/plugins/stroke/stroke_counter.c
src/libcharon/plugins/stroke/stroke_counter.h
src/libcharon/plugins/stroke/stroke_socket.c
src/stroke/stroke.c
src/stroke/stroke_keywords.h
src/stroke/stroke_keywords.txt
src/stroke/stroke_msg.h

index 56eda94..e64415f 100644 (file)
@@ -16,6 +16,7 @@
 #include "stroke_counter.h"
 
 #include <threading/spinlock.h>
+#include <collections/hashtable.h>
 
 ENUM(stroke_counter_type_names,
        COUNTER_INIT_IKE_SA_REKEY, COUNTER_OUT_INFORMATIONAL_RSP,
@@ -55,16 +56,111 @@ struct private_stroke_counter_t {
        stroke_counter_t public;
 
        /**
-        * Counter values
+        * Global counter values
         */
        u_int64_t counter[COUNTER_MAX];
 
        /**
+        * Counters for specific connection names, char* => entry_t
+        */
+       hashtable_t *conns;
+
+       /**
         * Lock for counter values
         */
        spinlock_t *lock;
 };
 
+/**
+ * Counters for a specific connection name
+ */
+typedef struct {
+       /** connection name */
+       char *name;
+       /** counter values for connection */
+       u_int64_t counter[COUNTER_MAX];
+} entry_t;
+
+/**
+ * Destroy named entry
+ */
+static void destroy_entry(entry_t *this)
+{
+       free(this->name);
+       free(this);
+}
+
+/**
+ * Hashtable hash function
+ */
+static u_int hash(char *name)
+{
+       return chunk_hash(chunk_from_str(name));
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(char *a, char *b)
+{
+       return streq(a, b);
+}
+
+/**
+ * Get the name of an IKE_SA, but return NULL if it is not known yet
+ */
+static char *get_ike_sa_name(ike_sa_t *ike_sa)
+{
+       peer_cfg_t *peer_cfg;
+
+       peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+       if (peer_cfg)
+       {
+               return peer_cfg->get_name(peer_cfg);
+       }
+       return NULL;
+}
+
+/**
+ * Increase a counter for a named entry
+ */
+static void count_named(private_stroke_counter_t *this,
+                                               ike_sa_t *ike_sa, stroke_counter_type_t type)
+{
+       entry_t *entry;
+       char *name;
+
+       name = get_ike_sa_name(ike_sa);
+       if (name)
+       {
+               entry = this->conns->get(this->conns, name);
+               if (!entry)
+               {
+                       INIT(entry,
+                               .name = strdup(name),
+                       );
+                       this->conns->put(this->conns, entry->name, entry);
+               }
+               entry->counter[type]++;
+       }
+}
+
+/**
+ * Get a counter value for a specific connection name
+ */
+static u_int64_t get_named_count(private_stroke_counter_t *this,
+                                                                char *name, stroke_counter_type_t type)
+{
+       entry_t *entry;
+
+       entry = this->conns->get(this->conns, name);
+       if (entry)
+       {
+               return entry->counter[type];
+       }
+       return 0;
+}
+
 METHOD(listener_t, alert, bool,
        private_stroke_counter_t *this, ike_sa_t *ike_sa,
        alert_t alert, va_list args)
@@ -86,6 +182,7 @@ METHOD(listener_t, alert, bool,
 
        this->lock->lock(this->lock);
        this->counter[type]++;
+       count_named(this, ike_sa, type);
        this->lock->unlock(this->lock);
 
        return TRUE;
@@ -109,6 +206,7 @@ METHOD(listener_t, ike_rekey, bool,
 
        this->lock->lock(this->lock);
        this->counter[type]++;
+       count_named(this, old, type);
        this->lock->unlock(this->lock);
 
        return TRUE;
@@ -120,6 +218,7 @@ METHOD(listener_t, child_rekey, bool,
 {
        this->lock->lock(this->lock);
        this->counter[COUNTER_CHILD_SA_REKEY]++;
+       count_named(this, ike_sa, COUNTER_CHILD_SA_REKEY);
        this->lock->unlock(this->lock);
 
        return TRUE;
@@ -194,13 +293,14 @@ METHOD(listener_t, message_hook, bool,
 
        this->lock->lock(this->lock);
        this->counter[type]++;
+       count_named(this, ike_sa, type);
        this->lock->unlock(this->lock);
 
        return TRUE;
 }
 
 METHOD(stroke_counter_t, print, void,
-       private_stroke_counter_t *this, FILE *out)
+       private_stroke_counter_t *this, FILE *out, char *name)
 {
        u_int64_t counter[COUNTER_MAX];
        int i;
@@ -209,11 +309,25 @@ METHOD(stroke_counter_t, print, void,
        this->lock->lock(this->lock);
        for (i = 0; i < countof(this->counter); i++)
        {
-               counter[i] = this->counter[i];
+               if (name)
+               {
+                       counter[i] = get_named_count(this, name, i);
+               }
+               else
+               {
+                       counter[i] = this->counter[i];
+               }
        }
        this->lock->unlock(this->lock);
 
-       fprintf(out, "\nList of IKE counters:\n\n");
+       if (name)
+       {
+               fprintf(out, "\nList of IKE counters for '%s':\n\n", name);
+       }
+       else
+       {
+               fprintf(out, "\nList of IKE counters:\n\n");
+       }
 
        /* but do blocking write without the lock. */
        for (i = 0; i < countof(this->counter); i++)
@@ -225,6 +339,17 @@ METHOD(stroke_counter_t, print, void,
 METHOD(stroke_counter_t, destroy, void,
        private_stroke_counter_t *this)
 {
+       enumerator_t *enumerator;
+       char *name;
+       entry_t *entry;
+
+       enumerator = this->conns->create_enumerator(this->conns);
+       while (enumerator->enumerate(enumerator, &name, &entry))
+       {
+               destroy_entry(entry);
+       }
+       enumerator->destroy(enumerator);
+       this->conns->destroy(this->conns);
        this->lock->destroy(this->lock);
        free(this);
 }
@@ -247,6 +372,8 @@ stroke_counter_t *stroke_counter_create()
                        .print = _print,
                        .destroy = _destroy,
                },
+               .conns = hashtable_create((hashtable_hash_t)hash,
+                                                                 (hashtable_equals_t)equals, 4),
                .lock = spinlock_create(),
        );
 
index efaae0d..b39fcb8 100644 (file)
@@ -87,8 +87,9 @@ struct stroke_counter_t {
         * Print counter values to an output stream.
         *
         * @param out           output stream to write to
+        * @param name          connection name to get counters for, NULL for global
         */
-       void (*print)(stroke_counter_t *this, FILE *out);
+       void (*print)(stroke_counter_t *this, FILE *out, char *name);
 
        /**
         * Destroy a stroke_counter_t.
index 2771f01..ebb3c72 100644 (file)
@@ -388,17 +388,14 @@ static void stroke_status(private_stroke_socket_t *this,
 /**
  * list various information
  */
-static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
+static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
+                                               FILE *out)
 {
        if (msg->list.flags & LIST_CAINFOS)
        {
                this->ca->list(this->ca, msg, out);
        }
        this->list->list(this->list, msg, out);
-       if (msg->list.flags & LIST_COUNTERS)
-       {
-               this->counter->print(this->counter, out);
-       }
 }
 
 /**
@@ -505,6 +502,17 @@ static void stroke_user_creds(private_stroke_socket_t *this,
 }
 
 /**
+ * Print stroke counter values
+ */
+static void stroke_counters(private_stroke_socket_t *this,
+                                                         stroke_msg_t *msg, FILE *out)
+{
+       pop_string(msg, &msg->counters.name);
+
+       this->counter->print(this->counter, out, msg->counters.name);
+}
+
+/**
  * set the verbosity debug output
  */
 static void stroke_loglevel(private_stroke_socket_t *this,
@@ -665,6 +673,8 @@ static job_requeue_t process(stroke_job_context_t *ctx)
                case STR_USER_CREDS:
                        stroke_user_creds(this, msg, out);
                        break;
+               case STR_COUNTERS:
+                       stroke_counters(this, msg, out);
                default:
                        DBG1(DBG_CFG, "received unknown stroke");
                        break;
@@ -855,4 +865,3 @@ stroke_socket_t *stroke_socket_create()
 
        return &this->public;
 }
-
index e289296..1be275c 100644 (file)
@@ -266,7 +266,6 @@ static int list_flags[] = {
        LIST_OCSP,
        LIST_ALGS,
        LIST_PLUGINS,
-       LIST_COUNTERS,
        LIST_ALL
 };
 
@@ -365,6 +364,16 @@ static int user_credentials(char *name, char *user, char *pass)
        return send_stroke_msg(&msg);
 }
 
+static int counters(char *name)
+{
+       stroke_msg_t msg;
+
+       msg.type = STR_COUNTERS;
+       msg.length = offsetof(stroke_msg_t, buffer);
+       msg.counters.name = push_string(&msg, name);
+       return send_stroke_msg(&msg);
+}
+
 static int set_loglevel(char *type, u_int level)
 {
        stroke_msg_t msg;
@@ -419,7 +428,7 @@ static void exit_usage(char *error)
        printf("  Show list of authority and attribute certificates:\n");
        printf("    stroke listcacerts|listocspcerts|listaacerts|listacerts\n");
        printf("  Show list of end entity certificates, ca info records  and crls:\n");
-       printf("    stroke listcerts|listcainfos|listcrls|listcounters|listall\n");
+       printf("    stroke listcerts|listcainfos|listcrls|listall\n");
        printf("  Show list of supported algorithms:\n");
        printf("    stroke listalgs\n");
        printf("  Reload authority and attribute certificates:\n");
@@ -445,6 +454,8 @@ static void exit_usage(char *error)
        printf("    where: NAME is a connection name added with \"stroke add\"\n");
        printf("           USERNAME is the username\n");
        printf("           PASSWORD is the optional password, you'll be asked to enter it if not given\n");
+       printf("  Show IKE counters:\n");
+       printf("    stroke listcounters [connection-name]\n");
        exit_error(error);
 }
 
@@ -553,7 +564,6 @@ int main(int argc, char *argv[])
                case STROKE_LIST_OCSP:
                case STROKE_LIST_ALGS:
                case STROKE_LIST_PLUGINS:
-               case STROKE_LIST_COUNTERS:
                case STROKE_LIST_ALL:
                        res = list(token->kw, argc > 2 && strcmp(argv[2], "--utc") == 0);
                        break;
@@ -594,6 +604,16 @@ int main(int argc, char *argv[])
                        }
                        res = user_credentials(argv[2], argv[3], argc > 4 ? argv[4] : NULL);
                        break;
+               case STROKE_COUNTERS:
+                       if (argc > 2)
+                       {
+                               res = counters(argv[2]);
+                       }
+                       else
+                       {
+                               res = counters(NULL);
+                       }
+                       break;
                default:
                        exit_usage(NULL);
        }
index 0ad87b7..12abce1 100644 (file)
@@ -42,7 +42,6 @@ typedef enum {
        STROKE_LIST_OCSP,
        STROKE_LIST_ALGS,
        STROKE_LIST_PLUGINS,
-       STROKE_LIST_COUNTERS,
        STROKE_LIST_ALL,
        STROKE_REREAD_SECRETS,
        STROKE_REREAD_CACERTS,
@@ -59,6 +58,7 @@ typedef enum {
        STROKE_LEASES,
        STROKE_MEMUSAGE,
        STROKE_USER_CREDS,
+       STROKE_COUNTERS,
 } stroke_keyword_t;
 
 #define STROKE_LIST_FIRST              STROKE_LIST_PUBKEYS
@@ -71,4 +71,3 @@ typedef struct stroke_token stroke_token_t;
 extern const stroke_token_t* in_word_set(register const char *str, register unsigned int len);
 
 #endif /* _STROKE_KEYWORDS_H_ */
-
index 95b2981..12c5909 100644 (file)
@@ -49,7 +49,6 @@ listcrls,        STROKE_LIST_CRLS
 listocsp,        STROKE_LIST_OCSP
 listalgs,        STROKE_LIST_ALGS
 listplugins,     STROKE_LIST_PLUGINS
-listcounters,    STROKE_LIST_COUNTERS
 listall,         STROKE_LIST_ALL
 rereadsecrets,   STROKE_REREAD_SECRETS
 rereadcacerts,   STROKE_REREAD_CACERTS
@@ -66,3 +65,4 @@ exportx509,      STROKE_EXPORT_X509
 leases,          STROKE_LEASES
 memusage,        STROKE_MEMUSAGE
 user-creds,      STROKE_USER_CREDS
+listcounters,    STROKE_COUNTERS
index e972a59..494acba 100644 (file)
@@ -67,10 +67,8 @@ enum list_flag_t {
        LIST_ALGS =                     0x0400,
        /** list plugin information */
        LIST_PLUGINS =          0x0800,
-       /** list IKE counters */
-       LIST_COUNTERS =         0x1000,
        /** all list options */
-       LIST_ALL =                      0x1FFF,
+       LIST_ALL =                      0x0FFF,
 };
 
 typedef enum reread_flag_t reread_flag_t;
@@ -225,6 +223,8 @@ struct stroke_msg_t {
                STR_MEMUSAGE,
                /* set username and password for a connection */
                STR_USER_CREDS,
+               /* print counters */
+               STR_COUNTERS,
                /* more to come */
        } type;
 
@@ -354,6 +354,11 @@ struct stroke_msg_t {
                        char *username;
                        char *password;
                } user_creds;
+
+               /* data for STR_COUNTERS */
+               struct {
+                       char *name;
+               } counters;
        };
        char buffer[STROKE_BUF_LEN];
 };