#include "dummy.h"
#include "dynamic-string.h"
#include "flow.h"
-#include "hmap.h"
+#include "cmap.h"
#include "latch.h"
#include "list.h"
#include "meta-flow.h"
/* Flows.
*
- * Readers of 'cls' and 'flow_table' must take a 'cls->rwlock' read lock.
+ * Readers of 'cls' must take a 'cls->rwlock' read lock.
+ *
+ * Writers of 'flow_table' must take the 'flow_mutex'.
*
- * Writers of 'cls' and 'flow_table' must take the 'flow_mutex' and then
- * the 'cls->rwlock' write lock. (The outer 'flow_mutex' allows writers to
- * atomically perform multiple operations on 'cls' and 'flow_table'.)
+ * Writers of 'cls' must take the 'flow_mutex' and then the 'cls->rwlock'
+ * write lock. (The outer 'flow_mutex' allows writers to atomically
+ * perform multiple operations on 'cls' and 'flow_table'.)
*/
struct ovs_mutex flow_mutex;
struct classifier cls; /* Classifier. Protected by cls.rwlock. */
- struct hmap flow_table OVS_GUARDED; /* Flow table. */
+ struct cmap flow_table OVS_GUARDED; /* Flow table. */
/* Queues.
*
const struct cls_rule cr; /* In owning dp_netdev's 'cls'. */
/* Hash table index by unmasked flow. */
- const struct hmap_node node; /* In owning dp_netdev's 'flow_table'. */
+ const struct cmap_node node; /* In owning dp_netdev's 'flow_table'. */
const struct flow flow; /* The flow that created this entry. */
/* Statistics.
ovs_mutex_init(&dp->flow_mutex);
classifier_init(&dp->cls, NULL);
- hmap_init(&dp->flow_table);
+ cmap_init(&dp->flow_table);
fat_rwlock_init(&dp->queue_rwlock);
fat_rwlock_destroy(&dp->queue_rwlock);
classifier_destroy(&dp->cls);
- hmap_destroy(&dp->flow_table);
+ cmap_destroy(&dp->flow_table);
ovs_mutex_destroy(&dp->flow_mutex);
seq_destroy(dp->port_seq);
cmap_destroy(&dp->ports);
struct dp_netdev_stats *bucket;
size_t i;
- fat_rwlock_rdlock(&dp->cls.rwlock);
- stats->n_flows = hmap_count(&dp->flow_table);
- fat_rwlock_unlock(&dp->cls.rwlock);
+ stats->n_flows = cmap_count(&dp->flow_table);
stats->n_hit = stats->n_missed = stats->n_lost = 0;
OVSTHREAD_STATS_FOR_EACH_BUCKET (bucket, i, &dp->stats) {
OVS_REQUIRES(dp->flow_mutex)
{
struct cls_rule *cr = CONST_CAST(struct cls_rule *, &flow->cr);
- struct hmap_node *node = CONST_CAST(struct hmap_node *, &flow->node);
+ struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
classifier_remove(&dp->cls, cr);
- hmap_remove(&dp->flow_table, node);
+ cmap_remove(&dp->flow_table, node, flow_hash(&flow->flow, 0));
ovsrcu_postpone(dp_netdev_flow_free, flow);
}
ovs_mutex_lock(&dp->flow_mutex);
fat_rwlock_wrlock(&dp->cls.rwlock);
- HMAP_FOR_EACH_SAFE (netdev_flow, next, node, &dp->flow_table) {
+ CMAP_FOR_EACH_SAFE (netdev_flow, next, node, &dp->flow_table) {
dp_netdev_remove_flow(dp, netdev_flow);
}
fat_rwlock_unlock(&dp->cls.rwlock);
static struct dp_netdev_flow *
dp_netdev_find_flow(const struct dp_netdev *dp, const struct flow *flow)
- OVS_REQ_RDLOCK(dp->cls.rwlock)
{
struct dp_netdev_flow *netdev_flow;
- HMAP_FOR_EACH_WITH_HASH (netdev_flow, node, flow_hash(flow, 0),
+ CMAP_FOR_EACH_WITH_HASH (netdev_flow, node, flow_hash(flow, 0),
&dp->flow_table) {
if (flow_equal(&netdev_flow->flow, flow)) {
return netdev_flow;
return error;
}
- fat_rwlock_rdlock(&dp->cls.rwlock);
netdev_flow = dp_netdev_find_flow(dp, &key);
- fat_rwlock_unlock(&dp->cls.rwlock);
if (netdev_flow) {
if (stats) {
match_init(&match, flow, wc);
cls_rule_init(CONST_CAST(struct cls_rule *, &netdev_flow->cr),
&match, NETDEV_RULE_PRIORITY);
+ cmap_insert(&dp->flow_table,
+ CONST_CAST(struct cmap_node *, &netdev_flow->node),
+ flow_hash(flow, 0));
fat_rwlock_wrlock(&dp->cls.rwlock);
classifier_insert(&dp->cls,
CONST_CAST(struct cls_rule *, &netdev_flow->cr));
- hmap_insert(&dp->flow_table,
- CONST_CAST(struct hmap_node *, &netdev_flow->node),
- flow_hash(flow, 0));
fat_rwlock_unlock(&dp->cls.rwlock);
return 0;
fat_rwlock_unlock(&dp->cls.rwlock);
if (!netdev_flow) {
if (put->flags & DPIF_FP_CREATE) {
- if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
+ if (cmap_count(&dp->flow_table) < MAX_FLOWS) {
if (put->stats) {
memset(put->stats, 0, sizeof *put->stats);
}
}
ovs_mutex_lock(&dp->flow_mutex);
- fat_rwlock_wrlock(&dp->cls.rwlock);
netdev_flow = dp_netdev_find_flow(dp, &key);
if (netdev_flow) {
if (del->stats) {
get_dpif_flow_stats(netdev_flow, del->stats);
}
+ fat_rwlock_wrlock(&dp->cls.rwlock);
dp_netdev_remove_flow(dp, netdev_flow);
+ fat_rwlock_unlock(&dp->cls.rwlock);
} else {
error = ENOENT;
}
- fat_rwlock_unlock(&dp->cls.rwlock);
ovs_mutex_unlock(&dp->flow_mutex);
return error;
struct dpif_netdev_flow_dump {
struct dpif_flow_dump up;
- uint32_t bucket;
- uint32_t offset;
+ struct cmap_position pos;
int status;
struct ovs_mutex mutex;
};
dump = xmalloc(sizeof *dump);
dpif_flow_dump_init(&dump->up, dpif_);
- dump->bucket = 0;
- dump->offset = 0;
+ memset(&dump->pos, 0, sizeof dump->pos);
dump->status = 0;
ovs_mutex_init(&dump->mutex);
ovs_mutex_lock(&dump->mutex);
if (!dump->status) {
- fat_rwlock_rdlock(&dp->cls.rwlock);
for (n_flows = 0; n_flows < MIN(max_flows, FLOW_DUMP_MAX_BATCH);
n_flows++) {
- struct hmap_node *node;
+ struct cmap_node *node;
- node = hmap_at_position(&dp->flow_table, &dump->bucket,
- &dump->offset);
+ node = cmap_next_position(&dp->flow_table, &dump->pos);
if (!node) {
dump->status = EOF;
break;
netdev_flows[n_flows] = CONTAINER_OF(node, struct dp_netdev_flow,
node);
}
- fat_rwlock_unlock(&dp->cls.rwlock);
}
ovs_mutex_unlock(&dump->mutex);