net/sfc: allow ports without MAE privilege
[dpdk.git] / drivers / net / sfc / sfc_flow.c
index 9e6d810..d57235f 100644 (file)
@@ -22,6 +22,7 @@
 #include "sfc_rx.h"
 #include "sfc_filter.h"
 #include "sfc_flow.h"
+#include "sfc_flow_tunnel.h"
 #include "sfc_log.h"
 #include "sfc_dp_rx.h"
 #include "sfc_mae_counter.h"
@@ -1274,7 +1275,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
                spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
                spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
        } else {
-               if (mae->status != SFC_MAE_STATUS_SUPPORTED) {
+               if (mae->status != SFC_MAE_STATUS_ADMIN) {
                        rte_flow_error_set(error, ENOTSUP,
                                           RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
                                           attr, "Transfer is not supported");
@@ -1740,8 +1741,13 @@ sfc_flow_parse_mark(struct sfc_adapter *sa,
        struct sfc_flow_spec *spec = &flow->spec;
        struct sfc_flow_spec_filter *spec_filter = &spec->filter;
        const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+       uint32_t mark_max;
 
-       if (mark == NULL || mark->id > encp->enc_filter_action_mark_max)
+       mark_max = encp->enc_filter_action_mark_max;
+       if (sfc_flow_tunnel_is_active(sa))
+               mark_max = RTE_MIN(mark_max, SFC_FT_USER_MARK_MASK);
+
+       if (mark == NULL || mark->id > mark_max)
                return EINVAL;
 
        spec_filter->template.efs_flags |= EFX_FILTER_FLAG_ACTION_MARK;
@@ -2543,15 +2549,49 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
        struct sfc_flow_spec_mae *spec_mae = &spec->mae;
        int rc;
 
+       /*
+        * If the flow is meant to be a JUMP rule in tunnel offload,
+        * preparse its actions and save its properties in spec_mae.
+        */
+       rc = sfc_flow_tunnel_detect_jump_rule(sa, actions, spec_mae, error);
+       if (rc != 0)
+               goto fail;
+
        rc = sfc_mae_rule_parse_pattern(sa, pattern, spec_mae, error);
        if (rc != 0)
-               return rc;
+               goto fail;
+
+       if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
+               /*
+                * By design, this flow should be represented solely by the
+                * outer rule. But the HW/FW hasn't got support for setting
+                * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
+                * does it support outer rule counters. As a workaround, an
+                * action rule of lower priority is used to do the job.
+                *
+                * So don't skip sfc_mae_rule_parse_actions() below.
+                */
+       }
 
        rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
        if (rc != 0)
-               return rc;
+               goto fail;
+
+       if (spec_mae->ft != NULL) {
+               if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)
+                       spec_mae->ft->jump_rule_is_set = B_TRUE;
+
+               ++(spec_mae->ft->refcnt);
+       }
 
        return 0;
+
+fail:
+       /* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
+       spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
+       spec_mae->ft = NULL;
+
+       return rc;
 }
 
 static int
@@ -2891,6 +2931,11 @@ const struct rte_flow_ops sfc_flow_ops = {
        .flush = sfc_flow_flush,
        .query = sfc_flow_query,
        .isolate = sfc_flow_isolate,
+       .tunnel_decap_set = sfc_flow_tunnel_decap_set,
+       .tunnel_match = sfc_flow_tunnel_match,
+       .tunnel_action_decap_release = sfc_flow_tunnel_action_decap_release,
+       .tunnel_item_release = sfc_flow_tunnel_item_release,
+       .get_restore_info = sfc_flow_tunnel_get_restore_info,
 };
 
 void
@@ -2948,6 +2993,8 @@ sfc_flow_start(struct sfc_adapter *sa)
 
        SFC_ASSERT(sfc_adapter_is_locked(sa));
 
+       sfc_flow_tunnel_reset_hit_counters(sa);
+
        TAILQ_FOREACH(flow, &sa->flow_list, entries) {
                rc = sfc_flow_insert(sa, flow, NULL);
                if (rc != 0)