This patch adds a port dumping APIs similar to the dpif_port_dump_...() APIs.
Signed-off-by: Eelco Chaudron <[email protected]> --- v2 changes: - Fixed double spaces between two sentences in long comments. - Re-added accidentally removed port_del from assert check. --- lib/dpif-offload-dpdk.c | 32 +++++++ lib/dpif-offload-dummy.c | 62 +++++++++---- lib/dpif-offload-provider.h | 31 +++++++ lib/dpif-offload-tc.c | 32 +++++++ lib/dpif-offload.c | 168 ++++++++++++++++++++++++++++++++++++ lib/dpif-offload.h | 31 +++++++ 6 files changed, 341 insertions(+), 15 deletions(-) diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c index 6014db38c..211978f16 100644 --- a/lib/dpif-offload-dpdk.c +++ b/lib/dpif-offload-dpdk.c @@ -103,6 +103,35 @@ dpif_offload_dpdk_port_del(struct dpif_offload *offload_, odp_port_t port_no) return ret; } +static int +dpif_offload_dpdk_port_dump_start(const struct dpif_offload *offload_, + void **statep) +{ + struct dpif_offload_dpdk *offload = dpif_offload_dpdk_cast(offload_); + + return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep); +} + +static int +dpif_offload_dpdk_port_dump_next(const struct dpif_offload *offload_, + void *state, + struct dpif_offload_port *port) +{ + struct dpif_offload_dpdk *offload = dpif_offload_dpdk_cast(offload_); + + return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state, + port); +} + +static int +dpif_offload_dpdk_port_dump_done(const struct dpif_offload *offload_, + void *state) +{ + struct dpif_offload_dpdk *offload = dpif_offload_dpdk_cast(offload_); + + return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state); +} + static struct netdev * dpif_offload_dpdk_get_netdev(struct dpif_offload *offload_, odp_port_t port_no) { @@ -326,6 +355,9 @@ struct dpif_offload_class dpif_offload_dpdk_class = { .can_offload = dpif_offload_dpdk_can_offload, .port_add = dpif_offload_dpdk_port_add, .port_del = dpif_offload_dpdk_port_del, + .port_dump_start = dpif_offload_dpdk_port_dump_start, + .port_dump_next = dpif_offload_dpdk_port_dump_next, + .port_dump_done = dpif_offload_dpdk_port_dump_done, .flow_get_n_offloaded = dpif_offload_dpdk_get_n_offloaded, .get_netdev = dpif_offload_dpdk_get_netdev, .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush, diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c index cf4ac9df5..3a0d51295 100644 --- a/lib/dpif-offload-dummy.c +++ b/lib/dpif-offload-dummy.c @@ -97,6 +97,35 @@ dpif_offload_dummy_port_del(struct dpif_offload *dpif_offload, return 0; } +static int +dpif_offload_dummy_port_dump_start(const struct dpif_offload *offload_, + void **statep) +{ + struct dpif_offload_dummy *offload = dpif_offload_dummy_cast(offload_); + + return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep); +} + +static int +dpif_offload_dummy_port_dump_next(const struct dpif_offload *offload_, + void *state, + struct dpif_offload_port *port) +{ + struct dpif_offload_dummy *offload = dpif_offload_dummy_cast(offload_); + + return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state, + port); +} + +static int +dpif_offload_dummy_port_dump_done(const struct dpif_offload *offload_, + void *state) +{ + struct dpif_offload_dummy *offload = dpif_offload_dummy_cast(offload_); + + return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state); +} + static struct netdev * dpif_offload_dummy_get_netdev(struct dpif_offload *dpif_offload, odp_port_t port_no) @@ -250,21 +279,24 @@ dpif_offload_dummy_can_offload(struct dpif_offload *dpif_offload OVS_UNUSED, return is_dummy_netdev_class(netdev->netdev_class) ? true : false; } -#define DEFINE_DPIF_DUMMY_CLASS(NAME, TYPE_STR) \ - struct dpif_offload_class NAME = { \ - .type = TYPE_STR, \ - .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY, \ - .supported_dpif_types = (const char *const[]) { \ - "dummy", \ - NULL}, \ - .open = dpif_offload_dummy_open, \ - .close = dpif_offload_dummy_close, \ - .set_config = dpif_offload_dummy_set_config, \ - .get_debug = dpif_offload_dummy_get_debug, \ - .can_offload = dpif_offload_dummy_can_offload, \ - .port_add = dpif_offload_dummy_port_add, \ - .port_del = dpif_offload_dummy_port_del, \ - .get_netdev = dpif_offload_dummy_get_netdev, \ +#define DEFINE_DPIF_DUMMY_CLASS(NAME, TYPE_STR) \ + struct dpif_offload_class NAME = { \ + .type = TYPE_STR, \ + .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY, \ + .supported_dpif_types = (const char *const[]) { \ + "dummy", \ + NULL}, \ + .open = dpif_offload_dummy_open, \ + .close = dpif_offload_dummy_close, \ + .set_config = dpif_offload_dummy_set_config, \ + .get_debug = dpif_offload_dummy_get_debug, \ + .can_offload = dpif_offload_dummy_can_offload, \ + .port_add = dpif_offload_dummy_port_add, \ + .port_del = dpif_offload_dummy_port_del, \ + .port_dump_start = dpif_offload_dummy_port_dump_start, \ + .port_dump_next = dpif_offload_dummy_port_dump_next, \ + .port_dump_done = dpif_offload_dummy_port_dump_done, \ + .get_netdev = dpif_offload_dummy_get_netdev, \ } DEFINE_DPIF_DUMMY_CLASS(dpif_offload_dummy_class, "dummy"); diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h index faf871b2f..0bf1a036a 100644 --- a/lib/dpif-offload-provider.h +++ b/lib/dpif-offload-provider.h @@ -157,6 +157,30 @@ struct dpif_offload_class { void (*port_set_config)(struct dpif_offload *, odp_port_t port_no, const struct smap *cfg); + /* Attempts to begin dumping the ports in a dpif_offload. On success, + * returns 0 and initializes '*statep' with any data needed for iteration. + * On failure, returns a positive errno value. */ + int (*port_dump_start)(const struct dpif_offload *, void **statep); + + /* Attempts to retrieve another port from 'dpif_offload' for 'state', which + * was initialized by a successful call to the 'port_dump_start' function + * for 'dpif_offload'. On success, stores a new dpif_offload_port into + * 'port' and returns 0. Returns EOF if the end of the port table has been + * reached, or a positive errno value on error. This function will not be + * called again once it returns nonzero once for a given iteration (but + * the 'port_dump_done' function will be called afterward). + * + * The dpif provider retains ownership of the data stored in 'port'. It + * must remain valid until at least the next call to 'port_dump_next' or + * 'port_dump_done' for 'state'. */ + int (*port_dump_next)(const struct dpif_offload *, void *state, + struct dpif_offload_port *); + + /* Releases resources from 'dpif_offload' for 'state', which was + * initialized by a successful call to the 'port_dump_start' function for + * 'dpif_offload'. */ + int (*port_dump_done)(const struct dpif_offload *dpif, void *state); + /* Deletes all offloaded flows for this offload_provider. Return 0 if * successful, otherwise returns a positive errno value. */ int (*flow_flush)(const struct dpif_offload *); @@ -316,6 +340,13 @@ void dpif_offload_port_mgr_traverse_ports( struct dpif_offload_port_mgr *mgr, bool (*cb)(struct dpif_offload_port_mgr_port *, void *), void *aux); +int dpif_offload_port_mgr_port_dump_start(struct dpif_offload_port_mgr *, + void **statep); +int dpif_offload_port_mgr_port_dump_next(struct dpif_offload_port_mgr *, + void *state, + struct dpif_offload_port *); +int dpif_offload_port_mgr_port_dump_done(struct dpif_offload_port_mgr *, + void *state); #define DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH(PORT, PORT_MGR) \ CMAP_FOR_EACH (PORT, odp_port_node, &(PORT_MGR)->odp_port_to_port) diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c index e367a0ccd..26dc77cbe 100644 --- a/lib/dpif-offload-tc.c +++ b/lib/dpif-offload-tc.c @@ -127,6 +127,35 @@ dpif_offload_tc_port_del(struct dpif_offload *dpif_offload, return ret; } +static int +dpif_offload_tc_port_dump_start(const struct dpif_offload *offload_, + void **statep) +{ + struct dpif_offload_tc *offload = dpif_offload_tc_cast(offload_); + + return dpif_offload_port_mgr_port_dump_start(offload->port_mgr, statep); +} + +static int +dpif_offload_tc_port_dump_next(const struct dpif_offload *offload_, + void *state, + struct dpif_offload_port *port) +{ + struct dpif_offload_tc *offload = dpif_offload_tc_cast(offload_); + + return dpif_offload_port_mgr_port_dump_next(offload->port_mgr, state, + port); +} + +static int +dpif_offload_tc_port_dump_done(const struct dpif_offload *offload_, + void *state) +{ + struct dpif_offload_tc *offload = dpif_offload_tc_cast(offload_); + + return dpif_offload_port_mgr_port_dump_done(offload->port_mgr, state); +} + static struct netdev * dpif_offload_tc_get_netdev(struct dpif_offload *dpif_offload, odp_port_t port_no) @@ -571,6 +600,9 @@ struct dpif_offload_class dpif_offload_tc_class = { .can_offload = dpif_offload_tc_can_offload, .port_add = dpif_offload_tc_port_add, .port_del = dpif_offload_tc_port_del, + .port_dump_start = dpif_offload_tc_port_dump_start, + .port_dump_next = dpif_offload_tc_port_dump_next, + .port_dump_done = dpif_offload_tc_port_dump_done, .flow_flush = dpif_offload_tc_flow_flush, .flow_dump_create = dpif_offload_tc_flow_dump_create, .flow_dump_next = dpif_offload_tc_flow_dump_next, diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c index bd4669d5c..e20283af2 100644 --- a/lib/dpif-offload.c +++ b/lib/dpif-offload.c @@ -159,6 +159,9 @@ dp_offload_initialize(void) && base_dpif_offload_classes[i]->can_offload && base_dpif_offload_classes[i]->port_add && base_dpif_offload_classes[i]->port_del + && base_dpif_offload_classes[i]->port_dump_start + && base_dpif_offload_classes[i]->port_dump_next + && base_dpif_offload_classes[i]->port_dump_done && base_dpif_offload_classes[i]->get_netdev); ovs_assert((base_dpif_offload_classes[i]->flow_dump_create && @@ -1089,6 +1092,101 @@ dpif_offload_flow_dump_thread_destroy(struct dpif_flow_dump_thread *thread) free(thread->offload_threads); } +static bool +dpif_offload_get_next_offload_for_dump(struct dpif_offload_port_dump *dump) +{ + struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dump->dpif); + const struct dpif_offload *offload; + const struct dpif_offload *prev_offload; + + if (!dp_offload) { + dump->offload = NULL; + return false; + } + + prev_offload = dump->offload; + dump->offload = NULL; + + LIST_FOR_EACH (offload, dpif_list_node, + &dp_offload->offload_providers) { + if (!prev_offload) { + /* We need the first offload provider. */ + dump->offload = offload; + break; + } + if (offload->dpif_list_node.next != &dp_offload->offload_providers + && prev_offload == offload) { + /* This is the current offload provider, so we need the next + * one if available. If not we will exit with !dump->offload. */ + dump->offload = CONTAINER_OF(offload->dpif_list_node.next, + struct dpif_offload, dpif_list_node); + break; + } + } + + return dump->offload ? true : false; +} + +void +dpif_offload_port_dump_start(struct dpif_offload_port_dump *dump, + const struct dpif *dpif) +{ + memset(dump, 0, sizeof *dump); + dump->dpif = dpif; + if (!dpif_offload_get_next_offload_for_dump(dump)) { + dump->error = EOF; + } else { + dump->error = dump->offload->class->port_dump_start(dump->offload, + &dump->state); + } +} + +bool +dpif_offload_port_dump_next(struct dpif_offload_port_dump *dump, + struct dpif_offload_port *port) +{ + const struct dpif_offload *offload = dump->offload; + + while (true) { + + if (dump->error) { + break; + } + + dump->error = offload->class->port_dump_next(offload, dump->state, + port); + if (dump->error) { + offload->class->port_dump_done(offload, dump->state); + + if (dump->error != EOF) { + /* If the error is not EOF, we stop dumping ports from all + * providers and return it. */ + break; + } + + if (dpif_offload_get_next_offload_for_dump(dump)) { + offload = dump->offload; + dump->error = offload->class->port_dump_start(offload, + &dump->state); + continue; + } + } + break; + } + + return dump->error ? false : true; +} + +int +dpif_offload_port_dump_done(struct dpif_offload_port_dump *dump) +{ + if (!dump->error && dump->offload) { + dump->error = dump->offload->class->port_dump_done(dump->offload, + dump->state); + } + return dump->error == EOF ? 0 : dump->error; +} + struct netdev * dpif_offload_offload_get_netdev_by_port_id(struct dpif_offload *offload, odp_port_t port_no) @@ -1435,3 +1533,73 @@ dpif_offload_port_mgr_port_count(struct dpif_offload_port_mgr *mgr) { return cmap_count(&mgr->odp_port_to_port); } + +struct dpif_offload_port_mgr_dump_state { + struct netdev *last_netdev; + size_t port_index; + size_t port_count; + odp_port_t ports[]; +}; + +int +dpif_offload_port_mgr_port_dump_start(struct dpif_offload_port_mgr *mgr, + void **statep) +{ + size_t port_count = dpif_offload_port_mgr_port_count(mgr); + struct dpif_offload_port_mgr_dump_state *state; + struct dpif_offload_port_mgr_port *port; + size_t added_port_count = 0; + + state = xmalloc(sizeof *state + (port_count * sizeof(odp_port_t))); + + DPIF_OFFLOAD_PORT_MGR_PORT_FOR_EACH (port, mgr) { + if (added_port_count >= port_count) { + break; + } + + state->ports[added_port_count] = port->port_no; + added_port_count++; + } + state->port_count = added_port_count; + state->port_index = 0; + state->last_netdev = NULL; + + *statep = state; + return 0; +} + +int dpif_offload_port_mgr_port_dump_next(struct dpif_offload_port_mgr *mgr, + void *state_, + struct dpif_offload_port *port) +{ + struct dpif_offload_port_mgr_dump_state *state = state_; + struct dpif_offload_port_mgr_port *mgr_port; + + while (state->port_index < state->port_count) { + + mgr_port = dpif_offload_port_mgr_find_by_odp_port( + mgr, state->ports[state->port_index++]); + + if (mgr_port) { + port->netdev = netdev_ref(mgr_port->netdev); + port->port_no = mgr_port->port_no; + + netdev_close(state->last_netdev); + state->last_netdev = port->netdev; + return 0; + } + } + + return EOF; +} + +int +dpif_offload_port_mgr_port_dump_done( + struct dpif_offload_port_mgr *mgr OVS_UNUSED, void *state_) +{ + struct dpif_offload_port_mgr_dump_state *state = state_; + + netdev_close(state->last_netdev); + free(state); + return 0; +} diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h index 29211c96a..97a4029e9 100644 --- a/lib/dpif-offload.h +++ b/lib/dpif-offload.h @@ -102,6 +102,37 @@ enum dpif_offload_impl_type dpif_offload_get_impl_type_by_class( : (dpif_offload_dump_done(DUMP), false)); \ ) +struct dpif_offload_port { + struct netdev *netdev; + odp_port_t port_no; +}; + +struct dpif_offload_port_dump { + const struct dpif *dpif; + const struct dpif_offload *offload; + int error; + void *state; +}; + +void dpif_offload_port_dump_start(struct dpif_offload_port_dump *, + const struct dpif *); +bool dpif_offload_port_dump_next(struct dpif_offload_port_dump *, + struct dpif_offload_port *); +int dpif_offload_port_dump_done(struct dpif_offload_port_dump *); + +/* Iterates through each DPIF_OFFLOAD_PORT in DPIF, using DUMP as state. + * + * Arguments all have pointer type. + * + * If you break out of the loop, then you need to free the dump structure by + * hand using dpif_offload_port_dump_done(). */ +#define DPIF_OFFLOAD_PORT_FOR_EACH(DPIF_OFFLOAD_PORT, DUMP, DPIF) \ + for (dpif_offload_port_dump_start(DUMP, DPIF); \ + (dpif_offload_port_dump_next(DUMP, DPIF_OFFLOAD_PORT) \ + ? true \ + : (dpif_offload_port_dump_done(DUMP), false)); \ + ) + /* Netdev specific function, which can be used in the fast path. */ int dpif_offload_netdev_flush_flows(struct netdev *); -- 2.50.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
