dpif-netdev: Add HW miss packet state recover logic.
Recover the packet if it was partially processed by the HW. Fallback to
lookup flow by mark association.
Acked-by: Sriharsha Basavapatna
Tested-by: Emma Finn
Tested-by: Marko Kovacevic
@@ -113,6 +113,7 @@ COVERAGE_DEFINE(datapath_drop_invalid_port);
COVERAGE_DEFINE(datapath_drop_invalid_bond);
COVERAGE_DEFINE(datapath_drop_invalid_tnl_port);
COVERAGE_DEFINE(datapath_drop_rx_invalid_packet);
+COVERAGE_DEFINE(datapath_drop_hw_miss_recover);
/* Protects against changes to 'dp_netdevs'. */
static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;
@@ -7094,6 +7095,39 @@ smc_lookup_batch(struct dp_netdev_pmd_thread *pmd,
pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SMC_HIT, n_smc_hit);
}
+static struct tx_port * pmd_send_port_cache_lookup(
+ const struct dp_netdev_pmd_thread *pmd, odp_port_t port_no);
+
+static inline int
+dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd,
+ odp_port_t port_no,
+ struct dp_packet *packet,
+ struct dp_netdev_flow **flow)
+{
+ struct tx_port *p;
+ uint32_t mark;
+
+ /* Restore the packet if HW processing was terminated before completion. */
+ p = pmd_send_port_cache_lookup(pmd, port_no);
+ if (OVS_LIKELY(p)) {
+ int err = netdev_hw_miss_packet_recover(p->port->netdev, packet);
+
+ if (err && err != EOPNOTSUPP) {
+ COVERAGE_INC(datapath_drop_hw_miss_recover);
+ return -1;
+ }
+ }
+
+ /* If no mark, no flow to find. */
+ if (!dp_packet_has_flow_mark(packet, &mark)) {
+ *flow = NULL;
+ return 0;
+ }
+
+ *flow = mark_to_flow_find(pmd, mark);
+ return 0;
+}
+
/* Try to process all ('cnt') the 'packets' using only the datapath flow cache
* 'pmd->flow_cache'. If a flow is not found for a packet 'packets[i]', the
* miniflow is copied into 'keys' and the packet pointer is moved at the
@@ -7138,7 +7172,6 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,
DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, packets_) {
struct dp_netdev_flow *flow;
- uint32_t mark;
if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
dp_packet_delete(packet);
@@ -7157,9 +7190,13 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,
pkt_metadata_init(&packet->md, port_no);
}
- if ((*recirc_depth_get() == 0) &&
- dp_packet_has_flow_mark(packet, &mark)) {
- flow = mark_to_flow_find(pmd, mark);
+ if (netdev_is_flow_api_enabled() && *recirc_depth_get() == 0) {
+ if (OVS_UNLIKELY(dp_netdev_hw_flow(pmd, port_no, packet, &flow))) {
+ /* Packet restoration failed and it was dropped, do not
+ * continue processing.
+ */
+ continue;
+ }
if (OVS_LIKELY(flow)) {
tcp_flags = parse_tcp_flags(packet);
if (OVS_LIKELY(batch_enable)) {
