@@ -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;
}
}
@@ -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
@@ -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 *);
};
@@ -835,6 +835,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)
@@ -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 */
@@ -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,
};
@@ -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 */
@@ -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 *);
@@ -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,
@@ -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);
@@ -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. */
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 <echaudro@redhat.com> --- 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(-)