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> --- ofproto/ofproto-dpif.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++- ofproto/ofproto-dpif.h | 4 ++ 2 files changed, 155 insertions(+), 1 deletion(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index cc1e9d5..b79f335 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -236,6 +236,29 @@ COVERAGE_DEFINE(rev_port_toggled); COVERAGE_DEFINE(rev_flow_table); COVERAGE_DEFINE(rev_mac_learning); +/* A map for recirculation ID allocation. */ +struct rid_map { + struct hmap map; +}; + +struct rid_node { + struct hmap_node node; + uint32_t recirc_id; +}; + +struct recirc_id_set { + 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 set. */ + uint32_t next_free_id; /* Possible next free id. */ +}; + +static void recirc_id_set_init(struct recirc_id_set *set, uint32_t base, + uint32_t n_ids); +static void recirc_id_set_uninit(struct recirc_id_set *set); +static uint32_t recirc_id_alloc(struct recirc_id_set *set); +static void recirc_id_free(struct recirc_id_set *set, uint32_t recirc_id); + /* All datapaths of a given type share a single dpif backer instance. */ struct dpif_backer { char *type; @@ -252,6 +275,10 @@ struct dpif_backer { bool recv_set_enable; /* Enables or disables receiving packets. */ + /* Recirculation. */ + struct ovs_mutex recirc_id_lock; /* lock for recirc_ids */ + struct recirc_id_set rids; /* Managing recirculation ID. */ + /* 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. */ @@ -768,9 +795,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_set_uninit(&backer->rids); free(backer->type); dpif_close(backer->dpif); - free(backer); } @@ -886,6 +913,9 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp) udpif_set_threads(backer->udpif, n_handlers, n_revalidators); } + ovs_mutex_init(&backer->recirc_id_lock); + recirc_id_set_init(&backer->rids, 0, 0); + return error; } @@ -4359,6 +4389,126 @@ vsp_add(struct ofport_dpif *port, ofp_port_t realdev_ofp_port, int vid) ovs_mutex_unlock(&ofproto->vsp_mutex); } +static void +recirc_id_set_init(struct recirc_id_set *set, uint32_t base, + uint32_t n_ids) +{ + set->base = base; + set->n_ids = n_ids; + set->next_free_id = base; + hmap_init(&set->ridmap.map); +} + +static void +recirc_id_set_uninit(struct recirc_id_set *set) +{ + struct rid_node *rid, *next; + + HMAP_FOR_EACH_SAFE(rid, next, node, &set->ridmap.map) { + hmap_remove(&set->ridmap.map, &rid->node); + free(rid); + } + + hmap_destroy(&set->ridmap.map); +} + +static struct rid_node * +ridset_find(struct recirc_id_set *set, uint32_t id) +{ + size_t hash; + struct rid_node *rid; + + hash = hash_int(id, 0); + HMAP_FOR_EACH_WITH_HASH(rid, node, hash, &set->ridmap.map) { + if (id == rid->recirc_id) { + return rid; + } + } + return NULL; +} + +static struct rid_node * +ridset_add(struct recirc_id_set *set, uint32_t id) +{ + struct rid_node *rid = xmalloc(sizeof *rid); + size_t hash; + + rid->recirc_id = id; + hash = hash_int(id, 0); + hmap_insert(&set->ridmap.map, &rid->node, hash); + return rid; +} + +static uint32_t +recirc_id_alloc(struct recirc_id_set *set) +{ + uint32_t id; + + if (set->n_ids == 0) + return 0; + + if (!(ridset_find(set, set->next_free_id))) { + id = set->next_free_id; + goto found_free_id; + } + + for (id = set->base; id < set->base + set->n_ids; id++) { + if ((ridset_find(set, id))) + goto found_free_id; + } + + /* Not available. */ + return 0; + +found_free_id: + ridset_add(set, id); + + if (id < set->base + set->n_ids) { + set->next_free_id = id + 1; + } else { + set->next_free_id = set->base; + } + + return id; +} + +static void +recirc_id_free(struct recirc_id_set *set, uint32_t recirc_id) +{ + struct rid_node *rid; + if (recirc_id > set->base && (recirc_id <= set->base + set->n_ids)) { + rid = ridset_find(set, recirc_id); + if (rid) { + hmap_remove(&set->ridmap.map, &rid->node); + } + } +} + +uint32_t +ofproto_dpif_alloc_recirc_id(struct ofproto *ofproto_) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct dpif_backer *backer = ofproto->backer; + uint32_t id; + + ovs_mutex_lock(&backer->recirc_id_lock); + id = recirc_id_alloc(&backer->rids); + ovs_mutex_unlock(&backer->recirc_id_lock); + + return id; +} + +void +ofproto_dpif_free_recirc_id(struct ofproto *ofproto_, uint32_t recirc_id) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct dpif_backer *backer = ofproto->backer; + + ovs_mutex_lock(&backer->recirc_id_lock); + recirc_id_free(&backer->rids, recirc_id); + ovs_mutex_unlock(&backer->recirc_id_lock); +} + static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port) { diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 5da0b5d..898448a 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; @@ -117,6 +118,9 @@ void ofproto_dpif_send_packet_in(struct ofproto_dpif *, int ofproto_dpif_send_packet(const struct ofport_dpif *, struct ofpbuf *); void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *); +uint32_t ofproto_dpif_alloc_recirc_id(struct ofproto *ofproto_); +void ofproto_dpif_free_recirc_id(struct ofproto *ofproto_, uint32_t recirc_id); + struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t); #endif /* ofproto-dpif.h */ -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev