ofproto-dpif: Added Per backer recirculation ID management
authorAndy Zhou <azhou@nicira.com>
Mon, 27 Jan 2014 09:18:30 +0000 (01:18 -0800)
committerAndy Zhou <azhou@nicira.com>
Tue, 25 Mar 2014 20:24:26 +0000 (13:24 -0700)
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@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
ofproto/automake.mk
ofproto/ofproto-dpif-rid.c [new file with mode: 0644]
ofproto/ofproto-dpif-rid.h [new file with mode: 0644]
ofproto/ofproto-dpif.c
ofproto/ofproto-dpif.h

index 448138b..cbdbd6f 100644 (file)
@@ -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 (file)
index 0000000..9e7e9a3
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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 (file)
index 0000000..3344e2a
--- /dev/null
@@ -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
index 744aa8c..87a61f7 100644 (file)
@@ -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;
@@ -894,6 +898,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
     }
     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);
@@ -4400,6 +4405,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 +4613,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,
index 06fde3f..6fbc672 100644 (file)
@@ -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 */