From 5caaf64f202b5daaa6eda08aa279202b16524062 Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Wed, 6 Aug 2008 01:58:15 -0700 Subject: [PATCH] Properly track table match counts. --- datapath/chain.c | 20 +++----------------- datapath/chain.h | 1 - datapath/datapath.c | 2 +- datapath/table-hash.c | 6 ++++-- datapath/table-linear.c | 1 + datapath/table.h | 12 +++++++++--- switch/chain.c | 20 +++----------------- switch/chain.h | 1 - switch/datapath.c | 2 +- switch/table-hash.c | 2 ++ switch/table-linear.c | 1 + switch/table.h | 12 +++++++++--- 12 files changed, 34 insertions(+), 46 deletions(-) diff --git a/datapath/chain.c b/datapath/chain.c index 71e00ee6..87b8b793 100644 --- a/datapath/chain.c +++ b/datapath/chain.c @@ -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) { diff --git a/datapath/chain.h b/datapath/chain.h index 69f746f8..42208d69 100644 --- a/datapath/chain.h +++ b/datapath/chain.h @@ -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); diff --git a/datapath/datapath.c b/datapath/datapath.c index 980b91ec..193a4526 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -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; } diff --git a/datapath/table-hash.c b/datapath/table-hash.c index 96525ecf..1627a471 100644 --- a/datapath/table-hash.c +++ b/datapath/table-hash.c @@ -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; diff --git a/datapath/table-linear.c b/datapath/table-linear.c index b4d4a775..f0f162db 100644 --- a/datapath/table-linear.c +++ b/datapath/table-linear.c @@ -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; } diff --git a/datapath/table.h b/datapath/table.h index 12543352..26fd466c 100644 --- a/datapath/table.h +++ b/datapath/table.h @@ -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. */ diff --git a/switch/chain.c b/switch/chain.c index 1e45a44b..8419070b 100644 --- a/switch/chain.c +++ b/switch/chain.c @@ -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); - } -} diff --git a/switch/chain.h b/switch/chain.h index aa8945dc..7e5b0ad0 100644 --- a/switch/chain.h +++ b/switch/chain.h @@ -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 */ diff --git a/switch/datapath.c b/switch/datapath.c index 505ebf32..e1ae5186 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -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; } diff --git a/switch/table-hash.c b/switch/table-hash.c index 461a4636..9b632905 100644 --- a/switch/table-hash.c +++ b/switch/table-hash.c @@ -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, diff --git a/switch/table-linear.c b/switch/table-linear.c index ff9d60b6..43e56e9a 100644 --- a/switch/table-linear.c +++ b/switch/table-linear.c @@ -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; } diff --git a/switch/table.h b/switch/table.h index 5ce7f3bb..c31ffa69 100644 --- a/switch/table.h +++ b/switch/table.h @@ -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. */ -- 2.30.2