--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef OFPROTO_DPIF_RID_H
+#define OFPROTO_DPIF_RID_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+struct recirc_id_pool;
+
+/*
+ * Recirculation ID pool.
+ * ======================
+ *
+ * Recirculation ID needs to be unique for each datapath. Recirculation
+ * ID pool keeps track recirculation ids.
+ *
+ * Typically, there is one recirculation ID pool for each backer.
+ *
+ * In theory, Recirculation ID can be any uint32_t value, except 0.
+ * The implementation usually limits it to a smaller range to ease
+ * debugging.
+ *
+ * Thread-safety
+ * =============
+ *
+ * All APIs are thread safe.
+ *
+ */
+struct recirc_id_pool *recirc_id_pool_create(void);
+void recirc_id_pool_destroy(struct recirc_id_pool *pool);
+uint32_t recirc_id_alloc(struct recirc_id_pool *pool);
+void recirc_id_free(struct recirc_id_pool *pool, uint32_t recirc_id);
+#endif
#include "ofproto-dpif-ipfix.h"
#include "ofproto-dpif-mirror.h"
#include "ofproto-dpif-monitor.h"
+#include "ofproto-dpif-rid.h"
#include "ofproto-dpif-sflow.h"
#include "ofproto-dpif-upcall.h"
#include "ofproto-dpif-xlate.h"
bool recv_set_enable; /* Enables or disables receiving packets. */
+ struct recirc_id_pool *rid_pool; /* Recirculation ID pool. */
+
/* True if the datapath supports variable-length
* OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions.
* False if the datapath supports only 8-byte (or shorter) userdata. */
ovs_rwlock_destroy(&backer->odp_to_ofport_lock);
hmap_destroy(&backer->odp_to_ofport_map);
shash_find_and_delete(&all_dpif_backers, backer->type);
+ recirc_id_pool_destroy(backer->rid_pool);
free(backer->type);
dpif_close(backer->dpif);
-
free(backer);
}
struct shash_node *node;
struct list garbage_list;
struct odp_garbage *garbage, *next;
+
struct sset names;
char *backer_name;
const char *name;
}
backer->variable_length_userdata = check_variable_length_userdata(backer);
backer->max_mpls_depth = check_max_mpls_depth(backer);
+ backer->rid_pool = recirc_id_pool_create();
if (backer->recv_set_enable) {
udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
return !hmap_is_empty(&ofproto->realdev_vid_map);
}
+
static ofp_port_t
vsp_realdev_to_vlandev__(const struct ofproto_dpif *ofproto,
ofp_port_t realdev_ofp_port, ovs_be16 vlan_tci)
}
}
+uint32_t
+ofproto_dpif_alloc_recirc_id(struct ofproto_dpif *ofproto)
+{
+ struct dpif_backer *backer = ofproto->backer;
+
+ return recirc_id_alloc(backer->rid_pool);
+}
+
+void
+ofproto_dpif_free_recirc_id(struct ofproto_dpif *ofproto, uint32_t recirc_id)
+{
+ struct dpif_backer *backer = ofproto->backer;
+
+ recirc_id_free(backer->rid_pool, recirc_id);
+}
+
const struct ofproto_class ofproto_dpif_class = {
init,
enumerate_types,