Introduce per-offload-provider implementation types and remove the synced_dp abstraction from the dpif level. The new API allows querying the offload implementation type and which provider offloads a given port.
Signed-off-by: Eelco Chaudron <echau...@redhat.com> --- lib/dpif-netdev.c | 1 - lib/dpif-netlink.c | 1 - lib/dpif-offload-dummy.c | 1 + lib/dpif-offload-provider.h | 4 ++ lib/dpif-offload-rte_flow.c | 1 + lib/dpif-offload-tc.c | 1 + lib/dpif-offload.c | 73 +++++++++++++++++++++++++++++++++++ lib/dpif-offload.h | 25 ++++++++++++ lib/dpif-provider.h | 8 ---- lib/dpif.c | 6 --- lib/dpif.h | 1 - ofproto/ofproto-dpif-upcall.c | 28 +++++++++----- 12 files changed, 124 insertions(+), 26 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 710c14447..45dcd569a 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -9953,7 +9953,6 @@ dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t bond_id, const struct dpif_class dpif_netdev_class = { "netdev", true, /* cleanup_required */ - true, /* synced_dp_layers */ dpif_netdev_init, dpif_netdev_enumerate, dpif_netdev_port_open_type, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 2df91a98e..0515f4ebd 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -4330,7 +4330,6 @@ dpif_netlink_cache_set_size(struct dpif *dpif_, uint32_t level, uint32_t size) const struct dpif_class dpif_netlink_class = { "system", false, /* cleanup_required */ - false, /* synced_dp_layers */ NULL, /* init */ dpif_netlink_enumerate, NULL, diff --git a/lib/dpif-offload-dummy.c b/lib/dpif-offload-dummy.c index b15d2192d..546a4f8d5 100644 --- a/lib/dpif-offload-dummy.c +++ b/lib/dpif-offload-dummy.c @@ -254,6 +254,7 @@ dpif_offload_dummy_can_offload(struct dpif_offload *dpif_offload OVS_UNUSED, #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}, \ diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h index 68e13843c..abb3e2469 100644 --- a/lib/dpif-offload-provider.h +++ b/lib/dpif-offload-provider.h @@ -18,6 +18,7 @@ #define DPIF_OFFLOAD_PROVIDER_H #include "cmap.h" +#include "dpif-offload.h" #include "dpif-provider.h" #include "ovs-thread.h" #include "smap.h" @@ -96,6 +97,9 @@ struct dpif_offload_class { * 'struct dpif_class' definition. */ const char *const *supported_dpif_types; + /* Type of implementation for this DPIF offload provider. */ + enum dpif_offload_impl_type impl_type; + /* Called when the dpif offload provider class is registered. Note that * this is the global initialization, not the per dpif one. */ int (*init)(void); diff --git a/lib/dpif-offload-rte_flow.c b/lib/dpif-offload-rte_flow.c index e5c40fb12..fead1f3ef 100644 --- a/lib/dpif-offload-rte_flow.c +++ b/lib/dpif-offload-rte_flow.c @@ -314,6 +314,7 @@ dpif_offload_rte_netdev_hw_miss_packet_recover( struct dpif_offload_class dpif_offload_rte_flow_class = { .type = "rte_flow", + .impl_type = DPIF_OFFLOAD_IMPL_SYNC, .supported_dpif_types = (const char *const[]) { "netdev", NULL}, diff --git a/lib/dpif-offload-tc.c b/lib/dpif-offload-tc.c index 961953961..e0358d091 100644 --- a/lib/dpif-offload-tc.c +++ b/lib/dpif-offload-tc.c @@ -560,6 +560,7 @@ dpif_offload_tc_flow_dump_thread_destroy( struct dpif_offload_class dpif_offload_tc_class = { .type = "tc", + .impl_type = DPIF_OFFLOAD_IMPL_HW_ONLY, .supported_dpif_types = (const char *const[]) { "system", NULL}, diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c index b2967b754..6fb4c66e1 100644 --- a/lib/dpif-offload.c +++ b/lib/dpif-offload.c @@ -560,6 +560,26 @@ dpif_offload_port_set_config(struct dpif *dpif, odp_port_t port_no, } } +struct dpif_offload * +dpif_offload_port_offloaded_by(const struct dpif *dpif, odp_port_t port_no) +{ + struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif); + struct dpif_offload *offload, *offload_return = NULL; + + if (!dp_offload || !dpif_offload_is_offload_enabled()) { + return NULL; + } + + LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) { + if (offload->class->get_netdev(offload, port_no)) { + offload_return = offload; + break; + } + } + + return offload_return; +} + void dpif_offload_dump_start(struct dpif_offload_dump *dump, const struct dpif *dpif) @@ -732,6 +752,37 @@ dpif_offload_flow_flush(struct dpif *dpif) } } +enum dpif_offload_impl_type +dpif_offload_get_impl_type(const struct dpif_offload *offload) +{ + return offload->class->impl_type; +} + +enum dpif_offload_impl_type +dpif_offload_get_impl_type_by_class(const char *type) +{ + enum dpif_offload_impl_type impl_type = DPIF_OFFLOAD_IMPL_NONE; + struct shash_node *node; + + /* For backwards compatibility 'dpdk' is the same as 'rte_flow'. */ + if (!strcmp(type, "dpdk")) { + type = "rte_flow"; + } + + ovs_mutex_lock(&dpif_offload_mutex); + SHASH_FOR_EACH (node, &dpif_offload_classes) { + const struct dpif_offload_class *class = node->data; + + if (!strcmp(type, class->type)) { + impl_type = class->impl_type; + break; + } + } + ovs_mutex_unlock(&dpif_offload_mutex); + + return impl_type; +} + uint64_t dpif_offload_flow_get_n_offloaded(const struct dpif *dpif) { @@ -752,6 +803,28 @@ dpif_offload_flow_get_n_offloaded(const struct dpif *dpif) return flow_count; } +uint64_t +dpif_offload_flow_get_n_offloaded_by_impl(const struct dpif *dpif, + enum dpif_offload_impl_type type) +{ + struct dp_offload *dp_offload = dpif_offload_get_dp_offload(dpif); + const struct dpif_offload *offload; + uint64_t flow_count = 0; + + if (!dp_offload || !dpif_offload_is_offload_enabled()) { + return 0; + } + + LIST_FOR_EACH (offload, dpif_list_node, &dp_offload->offload_providers) { + if (offload->class->flow_get_n_offloaded + && type == dpif_offload_get_impl_type(offload)) { + flow_count += offload->class->flow_get_n_offloaded(offload); + } + } + + return flow_count; +} + void dpif_offload_meter_set(const struct dpif *dpif, ofproto_meter_id meter_id, struct ofputil_meter_config *config) diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h index 265585c49..8409323f7 100644 --- a/lib/dpif-offload.h +++ b/lib/dpif-offload.h @@ -30,6 +30,23 @@ struct dpif_offload_dump { void *state; }; +/* Definition of the DPIF offload implementation type. + * + * The 'DPIF_OFFLOAD_IMPL_SYNC' implementation has a single view, the offload + * provider is responsible for synchronizing flows and statistics through the + * dpif flow operations. An example of this is rte_flow (DPDK offload). + * + * The 'DPIF_OFFLOAD_IMPL_HW_ONLY' implementation tries to install a hardware + * flow first. If successful, no dpif-layer software flow will be installed. + * Offload-specific callbacks are then used to manage the flow and query + * statistics. An example of this is kernel TC. + */ +enum dpif_offload_impl_type { + DPIF_OFFLOAD_IMPL_NONE, + DPIF_OFFLOAD_IMPL_SYNC, + DPIF_OFFLOAD_IMPL_HW_ONLY, +}; + /* Global functions. */ void dpif_offload_set_global_cfg(const struct ovsrec_open_vswitch *); @@ -52,6 +69,8 @@ bool dpif_offload_dump_next(struct dpif_offload_dump *, struct dpif_offload **); int dpif_offload_dump_done(struct dpif_offload_dump *); uint64_t dpif_offload_flow_get_n_offloaded(const struct dpif *); +uint64_t dpif_offload_flow_get_n_offloaded_by_impl( + const struct dpif *, enum dpif_offload_impl_type); void dpif_offload_meter_set(const struct dpif *dpif, ofproto_meter_id meter_id, struct ofputil_meter_config *); void dpif_offload_meter_get(const struct dpif *dpif, ofproto_meter_id meter_id, @@ -63,6 +82,12 @@ struct netdev *dpif_offload_get_netdev_by_port_id(struct dpif *, odp_port_t); struct netdev *dpif_offload_offload_get_netdev_by_port_id( struct dpif_offload *, odp_port_t); +struct dpif_offload *dpif_offload_port_offloaded_by(const struct dpif *, + odp_port_t); +enum dpif_offload_impl_type dpif_offload_get_impl_type( + const struct dpif_offload *); +enum dpif_offload_impl_type dpif_offload_get_impl_type_by_class( + const char *type); /* Iterates through each DPIF_OFFLOAD in DPIF, using DUMP as state. * diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 91e7ddcfa..02bcae12f 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -164,14 +164,6 @@ struct dpif_class { * datapaths that can not exist without it (e.g. netdev datapath). */ bool cleanup_required; - /* If 'true' the specific dpif implementation synchronizes the various - * datapath implementation layers, i.e., the dpif's layer in combination - * with the underlying netdev offload layers. For example, dpif-netlink - * does not sync its kernel flows with the tc ones, i.e., only one gets - * installed. On the other hand, dpif-netdev installs both flows, - * internally keeps track of both, and represents them as one. */ - bool synced_dp_layers; - /* Called when the dpif provider is registered, typically at program * startup. Returning an error from this function will prevent any * datapath with this class from being created. diff --git a/lib/dpif.c b/lib/dpif.c index 721f6afc7..8c40bec18 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -2135,9 +2135,3 @@ dpif_cache_set_size(struct dpif *dpif, uint32_t level, uint32_t size) ? dpif->dpif_class->cache_set_size(dpif, level, size) : EOPNOTSUPP; } - -bool -dpif_synced_dp_layers(struct dpif *dpif) -{ - return dpif->dpif_class->synced_dp_layers; -} diff --git a/lib/dpif.h b/lib/dpif.h index 473eacb2f..f3301ae85 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -943,7 +943,6 @@ char *dpif_get_dp_version(const struct dpif *); bool dpif_supports_tnl_push_pop(const struct dpif *); bool dpif_may_support_explicit_drop_action(const struct dpif *); bool dpif_may_support_psample(const struct dpif *); -bool dpif_synced_dp_layers(struct dpif *); /* Log functions. */ struct vlog_module; diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index d0c537bc9..b324793f0 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -826,12 +826,8 @@ udpif_get_n_flows(struct udpif *udpif) atomic_store_relaxed(&udpif->n_flows_timestamp, now); dpif_get_dp_stats(udpif->dpif, &stats); flow_count = stats.n_flows; - - if (!dpif_synced_dp_layers(udpif->dpif)) { - /* If the dpif layer does not sync the flows, we need to include - * the hardware offloaded flows separately. */ - flow_count += dpif_offload_flow_get_n_offloaded(udpif->dpif); - } + flow_count += dpif_offload_flow_get_n_offloaded_by_impl( + udpif->dpif, DPIF_OFFLOAD_IMPL_HW_ONLY); atomic_store_relaxed(&udpif->n_flows, flow_count); ovs_mutex_unlock(&udpif->n_flows_mutex); @@ -2802,6 +2798,21 @@ udpif_update_used(struct udpif *udpif, struct udpif_key *ukey, return stats->used; } +static bool +did_dp_hw_only_offload_change(const char *old_type, const char *new_type) +{ + enum dpif_offload_impl_type old_impl = old_type ? + dpif_offload_get_impl_type_by_class(old_type) : DPIF_OFFLOAD_IMPL_NONE; + enum dpif_offload_impl_type new_impl = new_type ? + dpif_offload_get_impl_type_by_class(new_type) : DPIF_OFFLOAD_IMPL_NONE; + + if (old_impl != new_impl && (old_impl == DPIF_OFFLOAD_IMPL_HW_ONLY || + new_impl == DPIF_OFFLOAD_IMPL_HW_ONLY)) { + return true; + } + return false; +} + static void revalidate(struct revalidator *revalidator) { @@ -2900,9 +2911,8 @@ revalidate(struct revalidator *revalidator) ukey->offloaded = f->attrs.offloaded; if (!ukey->dp_layer - || (!dpif_synced_dp_layers(udpif->dpif) - && strcmp(ukey->dp_layer, f->attrs.dp_layer))) { - + || did_dp_hw_only_offload_change(ukey->dp_layer, + f->attrs.dp_layer)) { if (ukey->dp_layer) { /* The dp_layer has changed this is probably due to an * earlier revalidate cycle moving it to/from hw offload. -- 2.50.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev