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 71e00ee..87b8b79 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 69f746f..42208d6 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 980b91e..193a452 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 96525ec..1627a47 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 b4d4a77..f0f162d 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 1254335..26fd466 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 1e45a44..8419070 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 aa8945d..7e5b0ad 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 505ebf3..e1ae518 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 461a463..9b63290 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 ff9d60b..43e56e9 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 5ce7f3b..c31ffa6 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. */