summaryrefslogtreecommitdiff
path: root/ofproto/ofproto-dpif-rid.c
diff options
context:
space:
mode:
authorAndy Zhou <azhou@nicira.com>2014-01-27 01:18:30 -0800
committerAndy Zhou <azhou@nicira.com>2014-03-25 13:24:26 -0700
commitf537461746b9a605972fbddab66f092d96e65732 (patch)
treecbbbedea31fd41f7398506f61d0aedaed3925141 /ofproto/ofproto-dpif-rid.c
parenta79f29f20e556514259d8593de779fc1b15c4055 (diff)
downloadopenvswitch-f537461746b9a605972fbddab66f092d96e65732.tar.gz
ofproto-dpif: Added Per backer recirculation ID management
Recirculation ID needs to be unique per datapath. Its usage will be tracked by the backer that corresponds to the datapath. In theory, Recirculation ID can be any uint32_t value, except 0. This implementation limits to a smaller range just for ease of debugging. Make the range size 0 effectively disables recirculation. Signed-off-by: Andy Zhou <azhou@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'ofproto/ofproto-dpif-rid.c')
-rw-r--r--ofproto/ofproto-dpif-rid.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/ofproto/ofproto-dpif-rid.c b/ofproto/ofproto-dpif-rid.c
new file mode 100644
index 000000000..9e7e9a32e
--- /dev/null
+++ b/ofproto/ofproto-dpif-rid.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * 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 "hmap.h"
+#include "hash.h"
+#include "ovs-thread.h"
+#include "ofproto-dpif-rid.h"
+
+struct rid_map {
+ struct hmap map;
+};
+
+struct rid_node {
+ struct hmap_node node;
+ uint32_t recirc_id;
+};
+
+struct rid_pool {
+ struct rid_map ridmap;
+ uint32_t base; /* IDs in the range of [base, base + n_ids). */
+ uint32_t n_ids; /* Total number of ids in the pool. */
+ uint32_t next_free_id; /* Possible next free id. */
+};
+
+struct recirc_id_pool {
+ struct ovs_mutex lock;
+ struct rid_pool rids;
+};
+
+#define RECIRC_ID_BASE 300
+#define RECIRC_ID_N_IDS 1024
+
+static void rid_pool_init(struct rid_pool *rids,
+ uint32_t base, uint32_t n_ids);
+static void rid_pool_uninit(struct rid_pool *pool);
+static uint32_t rid_pool_alloc_id(struct rid_pool *pool);
+static void rid_pool_free_id(struct rid_pool *rids, uint32_t rid);
+static struct rid_node *rid_pool_find(struct rid_pool *rids, uint32_t id);
+static struct rid_node *rid_pool_add(struct rid_pool *rids, uint32_t id);
+
+struct recirc_id_pool *
+recirc_id_pool_create(void)
+{
+ struct recirc_id_pool *pool;
+
+ pool = xmalloc(sizeof *pool);
+ rid_pool_init(&pool->rids, RECIRC_ID_BASE, RECIRC_ID_N_IDS);
+ ovs_mutex_init(&pool->lock);
+
+ return pool;
+}
+
+void
+recirc_id_pool_destroy(struct recirc_id_pool *pool)
+{
+ rid_pool_uninit(&pool->rids);
+ ovs_mutex_destroy(&pool->lock);
+}
+
+uint32_t
+recirc_id_alloc(struct recirc_id_pool *pool)
+{
+ uint32_t id;
+
+ ovs_mutex_lock(&pool->lock);
+ id = rid_pool_alloc_id(&pool->rids);
+ ovs_mutex_unlock(&pool->lock);
+
+ return id;
+}
+
+void
+recirc_id_free(struct recirc_id_pool *pool, uint32_t id)
+{
+ ovs_mutex_lock(&pool->lock);
+ rid_pool_free_id(&pool->rids, id);
+ ovs_mutex_unlock(&pool->lock);
+}
+
+static void
+rid_pool_init(struct rid_pool *rids, uint32_t base, uint32_t n_ids)
+{
+ rids->base = base;
+ rids->n_ids = n_ids;
+ rids->next_free_id = base;
+ hmap_init(&rids->ridmap.map);
+}
+
+static void
+rid_pool_uninit(struct rid_pool *rids)
+{
+ struct rid_node *rid, *next;
+
+ HMAP_FOR_EACH_SAFE(rid, next, node, &rids->ridmap.map) {
+ hmap_remove(&rids->ridmap.map, &rid->node);
+ free(rid);
+ }
+
+ hmap_destroy(&rids->ridmap.map);
+}
+
+static struct rid_node *
+rid_pool_find(struct rid_pool *rids, uint32_t id)
+{
+ size_t hash;
+ struct rid_node *rid;
+
+ hash = hash_int(id, 0);
+ HMAP_FOR_EACH_WITH_HASH(rid, node, hash, &rids->ridmap.map) {
+ if (id == rid->recirc_id) {
+ return rid;
+ }
+ }
+ return NULL;
+}
+
+static struct rid_node *
+rid_pool_add(struct rid_pool *rids, uint32_t id)
+{
+ struct rid_node *rid = xmalloc(sizeof *rid);
+ size_t hash;
+
+ rid->recirc_id = id;
+ hash = hash_int(id, 0);
+ hmap_insert(&rids->ridmap.map, &rid->node, hash);
+ return rid;
+}
+
+static uint32_t
+rid_pool_alloc_id(struct rid_pool *rids)
+{
+ uint32_t id;
+
+ if (rids->n_ids == 0) {
+ return 0;
+ }
+
+ if (!(rid_pool_find(rids, rids->next_free_id))) {
+ id = rids->next_free_id;
+ goto found_free_id;
+ }
+
+ for(id = rids->base; id < rids->base + rids->n_ids; id++) {
+ if (rid_pool_find(rids, id)) {
+ goto found_free_id;
+ }
+ }
+
+ /* Not available. */
+ return 0;
+
+found_free_id:
+ rid_pool_add(rids, id);
+
+ if (id < rids->base + rids->n_ids) {
+ rids->next_free_id = id + 1;
+ } else {
+ rids->next_free_id = rids->base;
+ }
+
+ return id;
+}
+
+static void
+rid_pool_free_id(struct rid_pool *rids, uint32_t id)
+{
+ struct rid_node *rid;
+ if (id > rids->base && (id <= rids->base + rids->n_ids)) {
+ rid = rid_pool_find(rids, id);
+ if (rid) {
+ hmap_remove(&rids->ridmap.map, &rid->node);
+ }
+ }
+}