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 <az...@nicira.com> --- v1->v2: No major changes. Comments about recirculation is added in ofproto-dpif.h in patch 4 V2-v3: Move reciruc_id management out of ofproto-dpif.c, into ofproto-dpif-rid.[ch]. Improves APIs along the way. Minor style improvments. --- ofproto/automake.mk | 2 + ofproto/ofproto-dpif-rid.c | 187 ++++++++++++++++++++++++++++++++++++++++++++ ofproto/ofproto-dpif-rid.h | 48 ++++++++++++ ofproto/ofproto-dpif.c | 25 +++++- ofproto/ofproto-dpif.h | 3 + 5 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 ofproto/ofproto-dpif-rid.c create mode 100644 ofproto/ofproto-dpif-rid.h diff --git a/ofproto/automake.mk b/ofproto/automake.mk index 448138b..cbdbd6f 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -31,6 +31,8 @@ ofproto_libofproto_la_SOURCES = \ ofproto/ofproto-dpif-mirror.h \ ofproto/ofproto-dpif-monitor.c \ ofproto/ofproto-dpif-monitor.h \ + ofproto/ofproto-dpif-rid.c \ + ofproto/ofproto-dpif-rid.h \ ofproto/ofproto-dpif-sflow.c \ ofproto/ofproto-dpif-sflow.h \ ofproto/ofproto-dpif-upcall.c \ diff --git a/ofproto/ofproto-dpif-rid.c b/ofproto/ofproto-dpif-rid.c new file mode 100644 index 0000000..e464e4c --- /dev/null +++ b/ofproto/ofproto-dpif-rid.c @@ -0,0 +1,187 @@ +/* + * 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); + } + } +} diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h new file mode 100644 index 0000000..4020205 --- /dev/null +++ b/ofproto/ofproto-dpif-rid.h @@ -0,0 +1,48 @@ +/* + * 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 diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 8ce439d..34b9889 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -53,6 +53,7 @@ #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" @@ -252,6 +253,8 @@ struct dpif_backer { 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. */ @@ -779,9 +782,9 @@ close_dpif_backer(struct dpif_backer *backer) 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); } @@ -803,6 +806,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp) struct shash_node *node; struct list garbage_list; struct odp_garbage *garbage, *next; + struct sset names; char *backer_name; const char *name; @@ -899,6 +903,8 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp) udpif_set_threads(backer->udpif, n_handlers, n_revalidators); } + backer->rid_pool = recirc_id_pool_create(); + return error; } @@ -4400,6 +4406,7 @@ ofproto_has_vlan_splinters(const struct ofproto_dpif *ofproto) 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) @@ -4607,6 +4614,22 @@ odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, odp_port_t odp_port) } } +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, diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 06fde3f..6fbc672 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -27,6 +27,7 @@ union user_action_cookie; struct dpif_flow_stats; +struct ofproto; struct ofproto_dpif; struct ofproto_packet_in; struct ofport_dpif; @@ -134,4 +135,6 @@ void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *); struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t); +uint32_t ofproto_dpif_alloc_recirc_id(struct ofproto_dpif *ofproto); +void ofproto_dpif_free_recirc_id(struct ofproto_dpif *ofproto, uint32_t recirc_id); #endif /* ofproto-dpif.h */ -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev