[ovs-dev] [bond megaflow v3 2/4] ofproto-dpif: Added Per backer recirculation ID management

Andy Zhou azhou at nicira.com
Sat Mar 22 02:48:54 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

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




More information about the dev mailing list