From 0023a1cb45400262820cc69c9dbd15fc8a95eb48 Mon Sep 17 00:00:00 2001 From: Daniele Di Proietto Date: Sat, 6 Sep 2014 08:10:43 +0000 Subject: [PATCH] dpif-netdev: Store miniflow length in exact match cache This optimization is done to avoid calling count_1bits(), which, if the popcnt istruction is not available might is slow. popcnt may not be available because: - We are running on old hardware - (more likely) We're using a generic build (i.e. packaged OVS from a distro), not tuned for the specific CPU Signed-off-by: Daniele Di Proietto Acked-by: Jarno Rajahalme --- lib/dpif-netdev.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 3ebe3760f..7e27acf2b 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -130,6 +130,7 @@ struct netdev_flow_key { struct emc_entry { uint32_t hash; + uint32_t mf_len; struct netdev_flow_key mf; struct dp_netdev_flow *flow; }; @@ -410,6 +411,7 @@ emc_cache_init(struct emc_cache *flow_cache) for (i = 0; i < ARRAY_SIZE(flow_cache->entries); i++) { flow_cache->entries[i].flow = NULL; flow_cache->entries[i].hash = 0; + flow_cache->entries[i].mf_len = 0; miniflow_initialize(&flow_cache->entries[i].mf.flow, flow_cache->entries[i].mf.buf); } @@ -1248,11 +1250,10 @@ netdev_flow_key_size(uint32_t flow_u32s) /* Used to compare 'netdev_flow_key's (miniflows) in the exact match cache. */ static inline bool netdev_flow_key_equal(const struct netdev_flow_key *a, - const struct netdev_flow_key *b) + const struct netdev_flow_key *b, + uint32_t size) { - uint32_t size = count_1bits(a->flow.map); - - return !memcmp(a, b, netdev_flow_key_size(size)); + return !memcmp(a, b, size); } static inline void @@ -1260,7 +1261,7 @@ netdev_flow_key_clone(struct netdev_flow_key *dst, const struct netdev_flow_key *src, uint32_t size) { - memcpy(dst, src, netdev_flow_key_size(size)); + memcpy(dst, src, size); } static inline bool @@ -1294,8 +1295,11 @@ emc_change_entry(struct emc_entry *ce, struct dp_netdev_flow *flow, } } if (mf) { - netdev_flow_key_clone(&ce->mf, mf, count_1bits(mf->flow.map)); + uint32_t mf_len = netdev_flow_key_size(count_1bits(mf->flow.map)); + + netdev_flow_key_clone(&ce->mf, mf, mf_len); ce->hash = hash; + ce->mf_len = mf_len; } } @@ -1309,7 +1313,8 @@ emc_insert(struct emc_cache *cache, const struct miniflow *mf, uint32_t hash, EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, hash) { if (current_entry->hash == hash && netdev_flow_key_equal(¤t_entry->mf, - miniflow_to_netdev_flow_key(mf))) { + miniflow_to_netdev_flow_key(mf), + current_entry->mf_len)) { /* We found the entry with the 'mf' miniflow */ emc_change_entry(current_entry, flow, NULL, 0); @@ -1340,7 +1345,8 @@ emc_lookup(struct emc_cache *cache, const struct miniflow *mf, uint32_t hash) EMC_FOR_EACH_POS_WITH_HASH(cache, current_entry, hash) { if (current_entry->hash == hash && emc_entry_alive(current_entry) && netdev_flow_key_equal(¤t_entry->mf, - miniflow_to_netdev_flow_key(mf))) { + miniflow_to_netdev_flow_key(mf), + current_entry->mf_len)) { /* We found the entry with the 'mf' miniflow */ return current_entry->flow;