When dumping a collection of offload providers, take a
reference to prevent the collection from being destroyed.
Improved the abstraction by updating the iterator APIs to
use a void *state context, consistent with the dpif port
iterators.
Fixes: 7eb9ffac52e4 ("dpif-offload-provider: Add dpif-offload-provider
implementation.")
Signed-off-by: Eelco Chaudron <[email protected]>
---
lib/dpif-offload.c | 142 ++++++++++++++++++++++++-----------------
lib/dpif-offload.h | 24 +++----
ofproto/ofproto-dpif.c | 8 +--
3 files changed, 97 insertions(+), 77 deletions(-)
diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c
index 0b8be8b058..6437bca427 100644
--- a/lib/dpif-offload.c
+++ b/lib/dpif-offload.c
@@ -188,6 +188,25 @@ dpif_get_offload_provider_collection(const struct dpif
*dpif)
&dpif->offload_provider_collection);
}
+static struct dpif_offload_provider_collection*
+dpif_get_offload_provider_collection_with_ref(const struct dpif *dpif)
+{
+ struct dpif_offload_provider_collection *collection;
+
+ ovs_mutex_lock(&dpif_offload_mutex);
+
+ collection = ovsrcu_get(struct dpif_offload_provider_collection *,
+ &dpif->offload_provider_collection);
+
+ if (!collection || !ovs_refcount_try_ref_rcu(&collection->ref_cnt)) {
+ collection = NULL;
+ }
+
+ ovs_mutex_unlock(&dpif_offload_mutex);
+
+ return collection;
+}
+
static void
dpif_attach_offload_provider_collection(
struct dpif *dpif, struct dpif_offload_provider_collection *collection)
@@ -354,6 +373,26 @@ provider_collection_free_rcu(
free(collection);
}
+static void
+dpif_offload_unref_collection(
+ struct dpif_offload_provider_collection *collection)
+{
+ if (!collection) {
+ return;
+ }
+
+ /* Take dpif_offload_mutex so that, if collection->ref_cnt falls to
+ * zero, we can't get a new reference to 'collection' through the
+ * 'dpif_offload_providers' shash. */
+ ovs_mutex_lock(&dpif_offload_mutex);
+ if (ovs_refcount_unref_relaxed(&collection->ref_cnt) == 1) {
+ shash_find_and_delete(&dpif_offload_providers,
+ collection->dpif_name);
+ ovsrcu_postpone(provider_collection_free_rcu, collection);
+ }
+ ovs_mutex_unlock(&dpif_offload_mutex);
+}
+
void
dpif_detach_offload_providers(struct dpif *dpif)
{
@@ -361,16 +400,7 @@ dpif_detach_offload_providers(struct dpif *dpif)
collection = dpif_get_offload_provider_collection(dpif);
if (collection) {
- /* Take dpif_offload_mutex so that, if collection->ref_cnt falls to
- * zero, we can't get a new reference to 'collection' through the
- * 'dpif_offload_providers' shash. */
- ovs_mutex_lock(&dpif_offload_mutex);
- if (ovs_refcount_unref_relaxed(&collection->ref_cnt) == 1) {
- shash_find_and_delete(&dpif_offload_providers,
- collection->dpif_name);
- ovsrcu_postpone(provider_collection_free_rcu, collection);
- }
- ovs_mutex_unlock(&dpif_offload_mutex);
+ dpif_offload_unref_collection(collection);
ovsrcu_set(&dpif->offload_provider_collection, NULL);
}
}
@@ -636,80 +666,78 @@ dpif_offload_port_offloaded_by(const struct dpif *dpif,
odp_port_t port_no)
return offload_return;
}
+struct dpif_offload_dump_state {
+ const struct dpif_offload_provider_collection *collection;
+ struct dpif_offload *entry;
+ int error;
+};
+
void
-dpif_offload_dump_start(struct dpif_offload_dump *dump,
- const struct dpif *dpif)
+dpif_offload_dump_start(const struct dpif *dpif, void **statep)
{
- memset(dump, 0, sizeof *dump);
- dump->dpif = dpif;
+ struct dpif_offload_dump_state *state;
+
+ state = xzalloc(sizeof *state);
+ state->collection = dpif_get_offload_provider_collection_with_ref(dpif);
+ if (!state->collection) {
+ state->error = EIDRM;
+ }
+
+ *statep = state;
}
bool
-dpif_offload_dump_next(struct dpif_offload_dump *dump,
- struct dpif_offload **offload)
+dpif_offload_dump_next(void *state_, struct dpif_offload **offload)
{
- struct dpif_offload_provider_collection *collection;
+ struct dpif_offload_dump_state *state = state_;
- if (!offload || !dump || dump->error) {
+ if (!offload || !state || state->error || !state->collection) {
return false;
}
- collection = dpif_get_offload_provider_collection(dump->dpif);
- if (!collection) {
- return false;
- }
-
- if (dump->state) {
- struct dpif_offload *offload_entry;
- bool valid_member = false;
+ if (state->entry) {
+ struct dpif_offload *entry = state->entry;
- /* In theory, list entries should not be removed. However, in case
- * someone calls this during destruction and the node has disappeared,
- * we will return EIDRM (Identifier removed). */
- LIST_FOR_EACH (offload_entry, dpif_list_node, &collection->list) {
- if (offload_entry == dump->state) {
- valid_member = true;
- break;
- }
+ LIST_FOR_EACH_CONTINUE (entry, dpif_list_node,
+ &state->collection->list) {
+ state->entry = entry;
+ *offload = entry;
+ return true;
}
- if (valid_member) {
- offload_entry = dump->state;
-
- LIST_FOR_EACH_CONTINUE (offload_entry, dpif_list_node,
- &collection->list) {
- *offload = offload_entry;
- dump->state = offload_entry;
- return true;
- }
-
- dump->error = EOF;
- } else {
- dump->error = EIDRM;
- }
+ state->error = EOF;
} else {
/* Get the first entry in the list. */
- struct dpif_offload *offload_entry;
+ struct dpif_offload *entry;
- LIST_FOR_EACH (offload_entry, dpif_list_node, &collection->list) {
+ LIST_FOR_EACH (entry, dpif_list_node, &state->collection->list) {
break;
}
- if (offload_entry) {
- *offload = offload_entry;
- dump->state = offload_entry;
+ if (entry) {
+ state->entry = entry;
+ *offload = entry;
} else {
- dump->error = EOF;
+ state->error = EOF;
}
}
- return !dump->error;
+ return !state->error;
}
int
-dpif_offload_dump_done(struct dpif_offload_dump *dump)
+dpif_offload_dump_done(void *state_)
{
- return dump->error == EOF ? 0 : dump->error;
+ struct dpif_offload_dump_state *state = state_;
+ int error;
+
+ dpif_offload_unref_collection(
+ CONST_CAST(struct dpif_offload_provider_collection *,
+ state->collection));
+ error = state->error == EOF ? 0 : state->error;
+ free(state);
+
+ return error;
}
void
diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h
index 65bba2f0ed..f7328db9a7 100644
--- a/lib/dpif-offload.h
+++ b/lib/dpif-offload.h
@@ -23,13 +23,6 @@
struct dpif_offload_class;
struct dpif_offload;
-/* Structure used by the dpif_offload_dump_* functions. */
-struct dpif_offload_dump {
- const struct dpif *dpif;
- int error;
- void *state;
-};
-
/* Definition of the DPIF offload implementation type.
*
* The 'DPIF_OFFLOAD_IMPL_FLOWS_DPIF_SYNCED' implementation has a single view,
@@ -64,10 +57,9 @@ const char *dpif_offload_type(const struct dpif_offload *);
bool dpif_offload_get_debug(const struct dpif_offload *, struct ds *,
struct json *);
void dpif_offload_flow_flush(struct dpif *);
-void dpif_offload_dump_start(struct dpif_offload_dump *, const struct dpif *);
-bool dpif_offload_dump_next(struct dpif_offload_dump *,
- struct dpif_offload **);
-int dpif_offload_dump_done(struct dpif_offload_dump *);
+void dpif_offload_dump_start(const struct dpif *, void **statep);
+bool dpif_offload_dump_next(void *state, struct dpif_offload **);
+int dpif_offload_dump_done(void *state);
uint64_t dpif_offload_flow_count(const struct dpif *);
uint64_t dpif_offload_flow_count_by_impl(const struct dpif *,
enum dpif_offload_impl_type);
@@ -94,11 +86,11 @@ enum dpif_offload_impl_type
dpif_offload_get_impl_type_by_class(
*
* If you break out of the loop, then you need to free the dump structure by
* hand using dpif_offload_dump_done(). */
-#define DPIF_OFFLOAD_FOR_EACH(DPIF_OFFLOAD, DUMP, DPIF) \
- for (dpif_offload_dump_start(DUMP, DPIF); \
- (dpif_offload_dump_next(DUMP, &DPIF_OFFLOAD) \
- ? true \
- : (dpif_offload_dump_done(DUMP), false)); \
+#define DPIF_OFFLOAD_FOR_EACH(DPIF_OFFLOAD, DUMP_STATE, DPIF) \
+ for (dpif_offload_dump_start(DPIF, &DUMP_STATE); \
+ (dpif_offload_dump_next(DUMP_STATE, &DPIF_OFFLOAD) \
+ ? true \
+ : (dpif_offload_dump_done(DUMP_STATE), false)); \
)
struct dpif_offload_port {
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 523b603754..a02afe8ef3 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6712,12 +6712,12 @@ done:
static void
dpif_offload_show_backer_text(const struct dpif_backer *backer, struct ds *ds)
{
- struct dpif_offload_dump dump;
struct dpif_offload *offload;
+ void *dump_state;
ds_put_format(ds, "%s:\n", dpif_name(backer->dpif));
- DPIF_OFFLOAD_FOR_EACH (offload, &dump, backer->dpif) {
+ DPIF_OFFLOAD_FOR_EACH (offload, dump_state, backer->dpif) {
ds_put_format(ds, " %s\n", dpif_offload_type(offload));
dpif_offload_get_debug(offload, ds, NULL);
}
@@ -6730,10 +6730,10 @@ dpif_offload_show_backer_json(struct json *backers,
struct json *json_providers = json_object_create();
struct json *json_priority = json_array_create_empty();
struct json *json_backer = json_object_create();
- struct dpif_offload_dump dump;
struct dpif_offload *offload;
+ void *dump_state;
- DPIF_OFFLOAD_FOR_EACH (offload, &dump, backer->dpif) {
+ DPIF_OFFLOAD_FOR_EACH (offload, dump_state, backer->dpif) {
struct json *debug_data = json_object_create();
json_array_add(json_priority,
--
2.52.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev