aboutsummaryrefslogtreecommitdiff
path: root/datapath/flow.c
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2010-04-02 16:46:18 -0400
committerJesse Gross <jesse@nicira.com>2010-04-19 09:11:57 -0400
commit8d5ebd839b86463c72239fe972001e4f1a367a7b (patch)
treee2721bfac92eecb77e23d643599ec95256dab2d8 /datapath/flow.c
parent3abc4a1a6c29ebecffeecedd582c64e0bb7d4c53 (diff)
datapath: Genericize hash table.
Currently the flow hash table assumes that it is storing flows. However, we will need additional types of hash tables in the future so remove assumptions about flows and convert the datapath to use the new table.
Diffstat (limited to 'datapath/flow.c')
-rw-r--r--datapath/flow.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/datapath/flow.c b/datapath/flow.c
index 8228da2e..548c729a 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -14,6 +14,7 @@
#include <linux/if_vlan.h>
#include <net/llc_pdu.h>
#include <linux/kernel.h>
+#include <linux/jhash.h>
#include <linux/jiffies.h>
#include <linux/llc.h>
#include <linux/module.h>
@@ -31,6 +32,7 @@
#include "compat.h"
struct kmem_cache *flow_cache;
+static unsigned int hash_seed;
struct arp_eth_header
{
@@ -134,7 +136,7 @@ struct sw_flow_actions *flow_actions_alloc(size_t n_actions)
/* Frees 'flow' immediately. */
-void flow_free(struct sw_flow *flow)
+static void flow_free(struct sw_flow *flow)
{
if (unlikely(!flow))
return;
@@ -142,6 +144,12 @@ void flow_free(struct sw_flow *flow)
kmem_cache_free(flow_cache, flow);
}
+void flow_free_tbl(struct tbl_node *node)
+{
+ struct sw_flow *flow = flow_cast(node);
+ flow_free(flow);
+}
+
/* RCU callback used by flow_deferred_free. */
static void rcu_free_flow_callback(struct rcu_head *rcu)
{
@@ -319,6 +327,24 @@ int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
return retval;
}
+struct sw_flow *flow_cast(const struct tbl_node *node)
+{
+ return container_of(node, struct sw_flow, tbl_node);
+}
+
+u32 flow_hash(const struct odp_flow_key *key)
+{
+ return jhash2((u32*)key, sizeof *key / sizeof(u32), hash_seed);
+}
+
+int flow_cmp(const struct tbl_node *node, void *key2_)
+{
+ const struct odp_flow_key *key1 = &flow_cast(node)->key;
+ const struct odp_flow_key *key2 = key2_;
+
+ return !memcmp(key1, key2, sizeof(struct odp_flow_key));
+}
+
/* Initializes the flow module.
* Returns zero if successful or a negative error code. */
int flow_init(void)
@@ -328,6 +354,8 @@ int flow_init(void)
if (flow_cache == NULL)
return -ENOMEM;
+ get_random_bytes(&hash_seed, sizeof hash_seed);
+
return 0;
}