Properly track table match counts.
authorJustin Pettit <jpettit@nicira.com>
Wed, 6 Aug 2008 08:58:15 +0000 (01:58 -0700)
committerJustin Pettit <jpettit@nicira.com>
Wed, 6 Aug 2008 08:58:15 +0000 (01:58 -0700)
12 files changed:
datapath/chain.c
datapath/chain.h
datapath/datapath.c
datapath/table-hash.c
datapath/table-linear.c
datapath/table.h
switch/chain.c
switch/chain.h
switch/datapath.c
switch/table-hash.c
switch/table-linear.c
switch/table.h

index 71e00ee6fca7bbcbac6ae839ee9ff520553328cb..87b8b793e2fda988ab1637beae6f357394612c01 100644 (file)
@@ -72,8 +72,10 @@ struct sw_flow *chain_lookup(struct sw_chain *chain,
        for (i = 0; i < chain->n_tables; i++) {
                struct sw_table *t = chain->tables[i];
                struct sw_flow *flow = t->lookup(t, key);
-               if (flow)
+               if (flow) {
+                       t->n_matched++;
                        return flow;
+               }
        }
        return NULL;
 }
@@ -158,22 +160,6 @@ void chain_destroy(struct sw_chain *chain)
        kfree(chain);
 }
 
-/* Prints statistics for each of the tables in 'chain'. */
-void chain_print_stats(struct sw_chain *chain)
-{
-       int i;
-
-       printk("\n");
-       for (i = 0; i < chain->n_tables; i++) {
-               struct sw_table *t = chain->tables[i];
-               struct sw_table_stats stats;
-               t->stats(t, &stats);
-               printk("%s: %lu/%lu flows\n",
-                                       stats.name, stats.n_flows, stats.max_flows);
-       }
-}
-
-
 int chain_set_hw_hook(struct sw_table *(*create_hw_table)(void),
                      struct module *owner)
 {
index 69f746f8a2837db6ec5ef43ca5148d181f61395f..42208d694103a352839850af39dbcb269f28c96a 100644 (file)
@@ -27,7 +27,6 @@ int chain_insert(struct sw_chain *, struct sw_flow *);
 int chain_delete(struct sw_chain *, const struct sw_flow_key *, uint16_t, int);
 int chain_timeout(struct sw_chain *);
 void chain_destroy(struct sw_chain *);
-void chain_print_stats(struct sw_chain *);
 
 int chain_set_hw_hook(struct sw_table *(*create_hw_table)(void),
                      struct module *owner);
index 980b91ec86401f3c2eeb2c9f1cc7c9f44c25b485..193a4526da5957ccc5af519750f7289a264d4bd7 100644 (file)
@@ -1221,7 +1221,7 @@ static int table_stats_dump(struct datapath *dp, void *state,
                memset(ots->pad, 0, sizeof ots->pad);
                ots->max_entries = htonl(stats.max_flows);
                ots->active_count = htonl(stats.n_flows);
-               ots->matched_count = cpu_to_be64(0); /* FIXME */
+               ots->matched_count = cpu_to_be64(stats.n_matched);
        }
        return 0;
 }
index 96525ecfe9978a09ae35d411902cc2b94356f1b8..1627a471c1f010de970ee1e318d7e18d115422e3 100644 (file)
@@ -185,6 +185,7 @@ static void table_hash_stats(struct sw_table *swt,
        stats->name = "hash";
        stats->n_flows = th->n_flows;
        stats->max_flows = th->bucket_mask + 1;
+       stats->n_matched = swt->n_matched;
 }
 
 struct sw_table *table_hash_create(unsigned int polynomial,
@@ -193,7 +194,7 @@ struct sw_table *table_hash_create(unsigned int polynomial,
        struct sw_table_hash *th;
        struct sw_table *swt;
 
-       th = kmalloc(sizeof *th, GFP_KERNEL);
+       th = kzalloc(sizeof *th, GFP_KERNEL);
        if (th == NULL)
                return NULL;
 
@@ -308,6 +309,7 @@ static void table_hash2_stats(struct sw_table *swt,
        stats->name = "hash2";
        stats->n_flows = substats[0].n_flows + substats[1].n_flows;
        stats->max_flows = substats[0].max_flows + substats[1].max_flows;
+       stats->n_matched = swt->n_matched;
 }
 
 struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0,
@@ -317,7 +319,7 @@ struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0,
        struct sw_table_hash2 *t2;
        struct sw_table *swt;
 
-       t2 = kmalloc(sizeof *t2, GFP_KERNEL);
+       t2 = kzalloc(sizeof *t2, GFP_KERNEL);
        if (t2 == NULL)
                return NULL;
 
index b4d4a77551ed41c2b7f06475e63ec147c2dcc7d4..f0f162db072f5f8483572c223cc216be21cfbe0a 100644 (file)
@@ -158,6 +158,7 @@ static void table_linear_stats(struct sw_table *swt,
        stats->name = "linear";
        stats->n_flows = tl->n_flows;
        stats->max_flows = tl->max_flows;
+       stats->n_matched = swt->n_matched;
 }
 
 
index 12543352b80549eb0545a9c3372bb9dbfa1a3ad8..26fd466ca09f5f4c7dbe06bcaf273ffd9ebe2806 100644 (file)
@@ -12,9 +12,10 @@ struct datapath;
 
 /* Table statistics. */
 struct sw_table_stats {
-       const char *name;       /* Human-readable name. */
-       unsigned long int n_flows; /* Number of active flows. */
-       unsigned long int max_flows; /* Flow capacity. */
+       const char *name;                /* Human-readable name. */
+       unsigned int n_flows;        /* Number of active flows. */
+       unsigned int max_flows;      /* Flow capacity. */
+       unsigned long int n_matched; /* Number of packets that have hit. */
 };
 
 /* Position within an iteration of a sw_table.
@@ -31,6 +32,11 @@ struct sw_table_position {
  * rcu_read_lock.  destroy must be fully serialized.
  */
 struct sw_table {
+       /* Keep track of the number of packets that matched this table.  To
+        * make this 100% accurate, it should be atomic.  However, we're
+        * primarily concerned about speed. */
+       unsigned long int n_matched;
+
        /* Searches 'table' for a flow matching 'key', which must not have any
         * wildcard fields.  Returns the flow if successful, a null pointer
         * otherwise. */
index 1e45a44b65e4914a9949e44f93ad38ba2c946a9d..8419070b3417f470f2df74c064834bf9188afafc 100644 (file)
@@ -87,8 +87,10 @@ chain_lookup(struct sw_chain *chain, const struct sw_flow_key *key)
     for (i = 0; i < chain->n_tables; i++) {
         struct sw_table *t = chain->tables[i];
         struct sw_flow *flow = t->lookup(t, key);
-        if (flow)
+        if (flow) {
+            t->n_matched++;
             return flow;
+        }
     }
     return NULL;
 }
@@ -162,19 +164,3 @@ chain_destroy(struct sw_chain *chain)
     }
     free(chain);
 }
-
-/* Prints statistics for each of the tables in 'chain'. */
-void
-chain_print_stats(struct sw_chain *chain)
-{
-    int i;
-
-    printf("\n");
-    for (i = 0; i < chain->n_tables; i++) {
-        struct sw_table *t = chain->tables[i];
-        struct sw_table_stats stats;
-        t->stats(t, &stats);
-        printf("%s: %lu/%lu flows\n",
-               stats.name, stats.n_flows, stats.max_flows);
-    }
-}
index aa8945dcb339f8759c311c529b1e92296e01f5ce..7e5b0ad03ab7b7806d0cce412ba90bd597a861ef 100644 (file)
@@ -58,6 +58,5 @@ int chain_insert(struct sw_chain *, struct sw_flow *);
 int chain_delete(struct sw_chain *, const struct sw_flow_key *, uint16_t, int);
 void chain_timeout(struct sw_chain *, struct list *deleted);
 void chain_destroy(struct sw_chain *);
-void chain_print_stats(struct sw_chain *);
 
 #endif /* chain.h */
index 505ebf326b1245239771481a1f00c8028503fe60..e1ae51860591059be4d5f7f0119818a92ce3fa37 100644 (file)
@@ -1247,7 +1247,7 @@ static int table_stats_dump(struct datapath *dp, void *state,
         memset(ots->pad, 0, sizeof ots->pad);
         ots->max_entries = htonl(stats.max_flows);
         ots->active_count = htonl(stats.n_flows);
-        ots->matched_count = htonll(0); /* FIXME */
+        ots->matched_count = htonll(stats.n_matched);
     }
     return 0;
 }
index 461a4636f12a42f64eb83adf9d3545453435100e..9b632905e27c99046c157829563da6cfc3420f70 100644 (file)
@@ -199,6 +199,7 @@ static void table_hash_stats(struct sw_table *swt,
     stats->name = "hash";
     stats->n_flows = th->n_flows;
     stats->max_flows = th->bucket_mask + 1;
+    stats->n_matched = swt->n_matched;
 }
 
 struct sw_table *table_hash_create(unsigned int polynomial,
@@ -322,6 +323,7 @@ static void table_hash2_stats(struct sw_table *swt,
     stats->name = "hash2";
     stats->n_flows = substats[0].n_flows + substats[1].n_flows;
     stats->max_flows = substats[0].max_flows + substats[1].max_flows;
+    stats->n_matched = swt->n_matched;
 }
 
 struct sw_table *table_hash2_create(unsigned int poly0, unsigned int buckets0,
index ff9d60b69cd9fcf1ca9fefbf5f5b33e54bb5f17f..43e56e9ae58c92a2ca523bc6abda78cd388b7574 100644 (file)
@@ -183,6 +183,7 @@ static void table_linear_stats(struct sw_table *swt,
     stats->name = "linear";
     stats->n_flows = tl->n_flows;
     stats->max_flows = tl->max_flows;
+    stats->n_matched = swt->n_matched;
 }
 
 
index 5ce7f3bbccb43caaf792294bfd4d776bfcc6b8b6..c31ffa69be3280922cd2801c56cc1fd1c9f50927 100644 (file)
@@ -45,9 +45,10 @@ struct list;
 
 /* Table statistics. */
 struct sw_table_stats {
-    const char *name;       /* Human-readable name. */
-    unsigned long int n_flows; /* Number of active flows. */
-    unsigned long int max_flows; /* Flow capacity. */
+    const char *name;            /* Human-readable name. */
+    unsigned int n_flows;        /* Number of active flows. */
+    unsigned int max_flows;      /* Flow capacity. */
+    unsigned long int n_matched; /* Number of packets that have hit. */
 };
 
 /* Position within an iteration of a sw_table.
@@ -60,6 +61,11 @@ struct sw_table_position {
 
 /* A single table of flows.  */
 struct sw_table {
+    /* Keep track of the number of packets that matched this table.  To
+     * make this 100% accurate, it should be atomic.  However, we're
+     * primarily concerned about speed. */
+    unsigned long int n_matched;
+
     /* Searches 'table' for a flow matching 'key', which must not have any
      * wildcard fields.  Returns the flow if successful, a null pointer
      * otherwise. */