Skip to content

Commit

Permalink
dpif-netdev: Split out generic lookup function
Browse files Browse the repository at this point in the history
This commit splits the generic hash-lookup-verify function to
its own file, for cleaner seperation between optimized versions.

Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
Tested-by: Malvika Gupta <malvika.gupta@arm.com>
Acked-by: Ilya Maximets <i.maximets@samsung.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
  • Loading branch information
harry-van-haaren authored and istokes committed Jul 19, 2019
1 parent f5ace7c commit 92c7c87
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 68 deletions.
1 change: 1 addition & 0 deletions lib/automake.mk
Expand Up @@ -78,6 +78,7 @@ lib_libopenvswitch_la_SOURCES = \
lib/dp-packet.h \
lib/dp-packet.c \
lib/dpdk.h \
lib/dpif-netdev-lookup-generic.c \
lib/dpif-netdev.c \
lib/dpif-netdev.h \
lib/dpif-netdev-private.h \
Expand Down
98 changes: 98 additions & 0 deletions lib/dpif-netdev-lookup-generic.c
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 Nicira, Inc.
* Copyright (c) 2019 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <config.h>
#include "dpif-netdev.h"
#include "dpif-netdev-private.h"

#include "bitmap.h"
#include "cmap.h"

#include "dp-packet.h"
#include "dpif.h"
#include "dpif-netdev-perf.h"
#include "dpif-provider.h"
#include "flow.h"
#include "packets.h"
#include "pvector.h"

/* Returns a hash value for the bits of 'key' where there are 1-bits in
* 'mask'. */
static inline uint32_t
netdev_flow_key_hash_in_mask(const struct netdev_flow_key *key,
const struct netdev_flow_key *mask)
{
const uint64_t *p = miniflow_get_values(&mask->mf);
uint32_t hash = 0;
uint64_t value;

NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP (value, key, mask->mf.map) {
hash = hash_add64(hash, value & *p);
p++;
}

return hash_finish(hash, (p - miniflow_get_values(&mask->mf)) * 8);
}

uint32_t
dpcls_subtable_lookup_generic(struct dpcls_subtable *subtable,
uint32_t keys_map,
const struct netdev_flow_key *keys[],
struct dpcls_rule **rules)
{
int i;
uint32_t found_map;

/* Compute hashes for the remaining keys. Each search-key is
* masked with the subtable's mask to avoid hashing the wildcarded
* bits. */
uint32_t hashes[NETDEV_MAX_BURST];
ULLONG_FOR_EACH_1 (i, keys_map) {
hashes[i] = netdev_flow_key_hash_in_mask(keys[i], &subtable->mask);
}

/* Lookup. */
const struct cmap_node *nodes[NETDEV_MAX_BURST];
found_map = cmap_find_batch(&subtable->rules, keys_map, hashes, nodes);

/* Check results. When the i-th bit of found_map is set, it means
* that a set of nodes with a matching hash value was found for the
* i-th search-key. Due to possible hash collisions we need to check
* which of the found rules, if any, really matches our masked
* search-key. */
ULLONG_FOR_EACH_1 (i, found_map) {
struct dpcls_rule *rule;

CMAP_NODE_FOR_EACH (rule, cmap_node, nodes[i]) {
if (OVS_LIKELY(dpcls_rule_matches_key(rule, keys[i]))) {
rules[i] = rule;
/* Even at 20 Mpps the 32-bit hit_cnt cannot wrap
* within one second optimization interval. */
subtable->hit_cnt++;
goto next;
}
}

/* None of the found rules was a match. Reset the i-th bit to
* keep searching this key in the next subtable. */
ULLONG_SET0(found_map, i); /* Did not match. */
next:
; /* Keep Sparse happy. */
}

return found_map;
}
69 changes: 1 addition & 68 deletions lib/dpif-netdev.c
Expand Up @@ -252,8 +252,7 @@ static bool dpcls_lookup(struct dpcls *cls,
const struct netdev_flow_key *keys[],
struct dpcls_rule **rules, size_t cnt,
int *num_lookups_p);
bool dpcls_rule_matches_key(const struct dpcls_rule *rule,
const struct netdev_flow_key *target);

/* Set of supported meter flags */
#define DP_SUPPORTED_METER_FLAGS_MASK \
(OFPMF13_STATS | OFPMF13_PKTPS | OFPMF13_KBPS | OFPMF13_BURST)
Expand Down Expand Up @@ -2768,23 +2767,6 @@ netdev_flow_key_init_masked(struct netdev_flow_key *dst,
(dst_u64 - miniflow_get_values(&dst->mf)) * 8);
}

/* Returns a hash value for the bits of 'key' where there are 1-bits in
* 'mask'. */
static inline uint32_t
netdev_flow_key_hash_in_mask(const struct netdev_flow_key *key,
const struct netdev_flow_key *mask)
{
const uint64_t *p = miniflow_get_values(&mask->mf);
uint32_t hash = 0;
uint64_t value;

NETDEV_FLOW_KEY_FOR_EACH_IN_FLOWMAP(value, key, mask->mf.map) {
hash = hash_add64(hash, value & *p++);
}

return hash_finish(hash, (p - miniflow_get_values(&mask->mf)) * 8);
}

static inline bool
emc_entry_alive(struct emc_entry *ce)
{
Expand Down Expand Up @@ -7882,55 +7864,6 @@ dpcls_rule_matches_key(const struct dpcls_rule *rule,
return true;
}

uint32_t
dpcls_subtable_lookup_generic(struct dpcls_subtable *subtable,
uint32_t keys_map,
const struct netdev_flow_key *keys[],
struct dpcls_rule **rules)
{
int i;
uint32_t found_map;

/* Compute hashes for the remaining keys. Each search-key is
* masked with the subtable's mask to avoid hashing the wildcarded
* bits. */
uint32_t hashes[NETDEV_MAX_BURST];
ULLONG_FOR_EACH_1 (i, keys_map) {
hashes[i] = netdev_flow_key_hash_in_mask(keys[i],
&subtable->mask);
}

/* Lookup. */
const struct cmap_node *nodes[NETDEV_MAX_BURST];
found_map = cmap_find_batch(&subtable->rules, keys_map, hashes, nodes);

/* Check results. When the i-th bit of found_map is set, it means
* that a set of nodes with a matching hash value was found for the
* i-th search-key. Due to possible hash collisions we need to check
* which of the found rules, if any, really matches our masked
* search-key. */
ULLONG_FOR_EACH_1 (i, found_map) {
struct dpcls_rule *rule;

CMAP_NODE_FOR_EACH (rule, cmap_node, nodes[i]) {
if (OVS_LIKELY(dpcls_rule_matches_key(rule, keys[i]))) {
rules[i] = rule;
/* Even at 20 Mpps the 32-bit hit_cnt cannot wrap
* within one second optimization interval. */
subtable->hit_cnt++;
goto next;
}
}
/* None of the found rules was a match. Reset the i-th bit to
* keep searching this key in the next subtable. */
ULLONG_SET0(found_map, i); /* Did not match. */
next:
; /* Keep Sparse happy. */
}

return found_map;
}

/* For each miniflow in 'keys' performs a classifier lookup writing the result
* into the corresponding slot in 'rules'. If a particular entry in 'keys' is
* NULL it is skipped.
Expand Down

0 comments on commit 92c7c87

Please sign in to comment.