[ovs-dev] [bond megaflow v2 1/5] ofproto-dpif: Added Per backer recirculation ID management

Andy Zhou azhou at nicira.com
Tue Mar 11 23:56:17 UTC 2014


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 at nicira.com>

---
v1->v2:  No major changes.
         Comments about recirculation is added in ofproto-dpif.h in
         patch 4
---
 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 8c43ee9..252e6b4 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -238,6 +238,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;
@@ -254,6 +277,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. */
@@ -781,9 +808,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);
 }
 
@@ -901,6 +928,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;
 }
 
@@ -4474,6 +4504,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 d09e285..d57bf21 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;
@@ -119,6 +120,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




More information about the dev mailing list