This patch moves the hardware packet miss recovery API from the netdev-offload to the dpif-offload provider. The API name has been changed from hw_miss_packet_recover() to hw_miss_packet_postprocess() to reflect that it may also be used for other tasks in the future, such as conntrack post-processing.
Signed-off-by: Eelco Chaudron <[email protected]> --- lib/dpif-netdev.c | 18 +++++++++++------- lib/dpif-offload-dpdk.c | 10 ++++++++++ lib/dpif-offload-provider.h | 12 ++++++++++++ lib/dpif-offload.c | 36 +++++++++++++++++++++++++++++++++++ lib/dpif-offload.h | 2 ++ lib/netdev-offload-dpdk.c | 3 +-- lib/netdev-offload-dpdk.h | 2 ++ lib/netdev-offload-provider.h | 6 ------ lib/netdev-offload.c | 33 +++----------------------------- lib/netdev-offload.h | 4 ++-- lib/netdev.c | 2 +- 11 files changed, 80 insertions(+), 48 deletions(-) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 82df85823..5d32a47b3 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -122,7 +122,7 @@ COVERAGE_DEFINE(datapath_drop_invalid_bond); COVERAGE_DEFINE(datapath_drop_invalid_tnl_port); COVERAGE_DEFINE(datapath_drop_rx_invalid_packet); #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */ -COVERAGE_DEFINE(datapath_drop_hw_miss_recover); +COVERAGE_DEFINE(datapath_drop_hw_miss_postprocess); #endif /* Protects against changes to 'dp_netdevs'. */ @@ -8423,14 +8423,18 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd, #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */ /* Restore the packet if HW processing was terminated before completion. */ struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq; - bool miss_api_supported; + bool postprocess_api_supported; + + atomic_read_relaxed(&rxq->port->netdev->hw_info.postprocess_api_supported, + &postprocess_api_supported); + if (postprocess_api_supported) { + int err = dpif_offload_netdev_hw_miss_packet_postprocess( + rxq->port->netdev, packet); - atomic_read_relaxed(&rxq->port->netdev->hw_info.miss_api_supported, - &miss_api_supported); - if (miss_api_supported) { - int err = netdev_hw_miss_packet_recover(rxq->port->netdev, packet); if (err && err != EOPNOTSUPP) { - COVERAGE_INC(datapath_drop_hw_miss_recover); + if (err != ECANCELED) { + COVERAGE_INC(datapath_drop_hw_miss_postprocess); + } return -1; } } diff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c index 76a8946c9..c8ae1adb2 100644 --- a/lib/dpif-offload-dpdk.c +++ b/lib/dpif-offload-dpdk.c @@ -286,6 +286,14 @@ dpif_offload_dpdk_netdev_flow_flush(const struct dpif_offload *offload return netdev_offload_dpdk_flow_flush(netdev); } +static int +dpif_offload_dpdk_netdev_hw_miss_packet_postprocess( + const struct dpif_offload *offload_ OVS_UNUSED, struct netdev *netdev, + struct dp_packet *packet) +{ + return netdev_offload_dpdk_hw_miss_packet_recover(netdev, packet); +} + struct dpif_offload_class dpif_offload_dpdk_class = { .type = "dpdk", .supported_dpif_types = (const char *const[]) { @@ -300,6 +308,8 @@ struct dpif_offload_class dpif_offload_dpdk_class = { .port_del = dpif_offload_dpdk_port_del, .flow_get_n_offloaded = dpif_offload_dpdk_get_n_offloaded, .netdev_flow_flush = dpif_offload_dpdk_netdev_flow_flush, + .netdev_hw_miss_packet_postprocess = \ + dpif_offload_dpdk_netdev_hw_miss_packet_postprocess, }; /* XXX: Temporary functions below, which will be removed once fully diff --git a/lib/dpif-offload-provider.h b/lib/dpif-offload-provider.h index 60d6c5321..78cf5d7fa 100644 --- a/lib/dpif-offload-provider.h +++ b/lib/dpif-offload-provider.h @@ -168,6 +168,18 @@ struct dpif_offload_class { /* Deletes all offloaded flows on this netdev. Return 0 if successful, * otherwise returns a positive errno value. */ int (*netdev_flow_flush)(const struct dpif_offload *, struct netdev *); + + /* Recover and/or set the packet state (contents and metadata) for + * continued processing in software, and perform any additional + * post-processing required by the offload provider. + * + * Return 0 if successful and the packet requires further processing; + * otherwise, return a positive errno value and take ownership of the + * packet if errno != EOPNOTSUPP. Return ECANCELED if the packet was + * fully consumed by the provider for non-error conditions. */ + int (*netdev_hw_miss_packet_postprocess)(const struct dpif_offload *, + struct netdev *, + struct dp_packet *); }; diff --git a/lib/dpif-offload.c b/lib/dpif-offload.c index 99cfe2aac..8ac0f8f96 100644 --- a/lib/dpif-offload.c +++ b/lib/dpif-offload.c @@ -846,6 +846,42 @@ dpif_offload_netdev_flush_flows(struct netdev *netdev) return EOPNOTSUPP; } +int +dpif_offload_netdev_hw_miss_packet_postprocess(struct netdev *netdev, + struct dp_packet *packet) +{ + const struct dpif_offload *offload; + bool postprocess_api_supported; + int rc; + + atomic_read_relaxed(&netdev->hw_info.postprocess_api_supported, + &postprocess_api_supported); + if (!postprocess_api_supported) { + return EOPNOTSUPP; + } + + offload = ovsrcu_get(const struct dpif_offload *, &netdev->dpif_offload); + + if (!offload || !offload->class->netdev_hw_miss_packet_postprocess) { + if (offload) { + /* Offload is configured and API unsupported by the port; + * avoid subsequent calls. */ + atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported, + false); + } + return EOPNOTSUPP; + } + + rc = offload->class->netdev_hw_miss_packet_postprocess(offload, netdev, + packet); + if (rc == EOPNOTSUPP) { + /* API unsupported by the port; avoid subsequent calls. */ + atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported, + false); + } + return rc; +} + struct dpif_offload_port_mgr * dpif_offload_port_mgr_init(void) diff --git a/lib/dpif-offload.h b/lib/dpif-offload.h index fb7edf269..fe73b278d 100644 --- a/lib/dpif-offload.h +++ b/lib/dpif-offload.h @@ -75,5 +75,7 @@ void dpif_offload_meter_del(const struct dpif *dpif, ofproto_meter_id meter_id, /* Netdev specific function, which can be used in the fast path. */ int dpif_offload_netdev_flush_flows(struct netdev *); +int dpif_offload_netdev_hw_miss_packet_postprocess(struct netdev *, + struct dp_packet *); #endif /* DPIF_OFFLOAD_H */ diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index d1781d8e4..c3d5e83f5 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -2685,7 +2685,7 @@ get_vport_netdev(const char *dpif_type, return aux.vport; } -static int +int netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *netdev, struct dp_packet *packet) { @@ -2803,5 +2803,4 @@ const struct netdev_flow_api netdev_offload_dpdk = { .init_flow_api = netdev_offload_dpdk_init_flow_api, .uninit_flow_api = netdev_offload_dpdk_uninit_flow_api, .flow_get = netdev_offload_dpdk_flow_get, - .hw_miss_packet_recover = netdev_offload_dpdk_hw_miss_packet_recover, }; diff --git a/lib/netdev-offload-dpdk.h b/lib/netdev-offload-dpdk.h index d5061b40c..475822e1b 100644 --- a/lib/netdev-offload-dpdk.h +++ b/lib/netdev-offload-dpdk.h @@ -24,5 +24,7 @@ struct netdev; * associated dpif offload provider. */ int netdev_offload_dpdk_flow_flush(struct netdev *); uint64_t netdev_offload_dpdk_flow_get_n_offloaded(struct netdev *); +int netdev_offload_dpdk_hw_miss_packet_recover(struct netdev *, + struct dp_packet *); #endif /* NETDEV_OFFLOAD_DPDK_H */ diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h index 898df8333..f762af19a 100644 --- a/lib/netdev-offload-provider.h +++ b/lib/netdev-offload-provider.h @@ -80,12 +80,6 @@ struct netdev_flow_api { int (*flow_del)(struct netdev *, const ovs_u128 *ufid, struct dpif_flow_stats *); - /* Recover the packet state (contents and data) for continued processing - * in software. - * Return 0 if successful, otherwise returns a positive errno value and - * takes ownership of a packet if errno != EOPNOTSUPP. */ - int (*hw_miss_packet_recover)(struct netdev *, struct dp_packet *); - /* Initializies the netdev flow api. * Return 0 if successful, otherwise returns a positive errno value. */ int (*init_flow_api)(struct netdev *); diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c index 0c4209290..be5787f4d 100644 --- a/lib/netdev-offload.c +++ b/lib/netdev-offload.c @@ -186,7 +186,8 @@ netdev_assign_flow_api(struct netdev *netdev) CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) { if (!rfa->flow_api->init_flow_api(netdev)) { ovs_refcount_ref(&rfa->refcnt); - atomic_store_relaxed(&netdev->hw_info.miss_api_supported, true); + atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported, + true); ovsrcu_set(&netdev->flow_api, rfa->flow_api); VLOG_INFO("%s: Assigned flow API '%s'.", netdev_get_name(netdev), rfa->flow_api->type); @@ -195,7 +196,7 @@ netdev_assign_flow_api(struct netdev *netdev) VLOG_DBG("%s: flow API '%s' is not suitable.", netdev_get_name(netdev), rfa->flow_api->type); } - atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false); + atomic_store_relaxed(&netdev->hw_info.postprocess_api_supported, false); VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev)); return -1; @@ -254,34 +255,6 @@ netdev_flow_put(struct netdev *netdev, struct match *match, : EOPNOTSUPP; } -int -netdev_hw_miss_packet_recover(struct netdev *netdev, - struct dp_packet *packet) -{ - const struct netdev_flow_api *flow_api; - bool miss_api_supported; - int rv; - - atomic_read_relaxed(&netdev->hw_info.miss_api_supported, - &miss_api_supported); - if (!miss_api_supported) { - return EOPNOTSUPP; - } - - flow_api = ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api); - if (!flow_api || !flow_api->hw_miss_packet_recover) { - return EOPNOTSUPP; - } - - rv = flow_api->hw_miss_packet_recover(netdev, packet); - if (rv == EOPNOTSUPP) { - /* API unsupported by the port; avoid subsequent calls. */ - atomic_store_relaxed(&netdev->hw_info.miss_api_supported, false); - } - - return rv; -} - int netdev_flow_get(struct netdev *netdev, struct match *match, struct nlattr **actions, const ovs_u128 *ufid, diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h index 2b32179ec..6006396b9 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -47,7 +47,8 @@ struct ovs_action_push_tnl; /* Offload-capable (HW) netdev information */ struct netdev_hw_info { bool oor; /* Out of Offload Resources ? */ - atomic_bool miss_api_supported; /* hw_miss_packet_recover() supported.*/ + /* Is hw_miss_packet_postprocess() supported.*/ + atomic_bool postprocess_api_supported; int offload_count; /* Offloaded flow count */ int pending_count; /* Pending (non-offloaded) flow count */ OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */ @@ -110,7 +111,6 @@ bool netdev_flow_dump_next(struct netdev_flow_dump *, struct match *, int netdev_flow_put(struct netdev *, struct match *, struct nlattr *actions, size_t actions_len, const ovs_u128 *, struct offload_info *, struct dpif_flow_stats *); -int netdev_hw_miss_packet_recover(struct netdev *, struct dp_packet *); int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions, const ovs_u128 *, struct dpif_flow_stats *, struct dpif_flow_attrs *, struct ofpbuf *wbuffer); diff --git a/lib/netdev.c b/lib/netdev.c index 6a05e9a7e..13f3d707e 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -435,7 +435,7 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) seq_read(netdev->reconfigure_seq); ovsrcu_set(&netdev->flow_api, NULL); netdev->hw_info.oor = false; - atomic_init(&netdev->hw_info.miss_api_supported, false); + atomic_init(&netdev->hw_info.postprocess_api_supported, false); netdev->node = shash_add(&netdev_shash, name, netdev); /* By default enable one tx and rx queue per netdev. */ -- 2.50.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
