LCOV - code coverage report
Current view: top level - drivers/net/sfc - sfc_mae.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 2044 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 95 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 1204 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *
       3                 :            :  * Copyright(c) 2019-2021 Xilinx, Inc.
       4                 :            :  * Copyright(c) 2019 Solarflare Communications Inc.
       5                 :            :  *
       6                 :            :  * This software was jointly developed between OKTET Labs (under contract
       7                 :            :  * for Solarflare) and Solarflare Communications, Inc.
       8                 :            :  */
       9                 :            : 
      10                 :            : #include <stdbool.h>
      11                 :            : 
      12                 :            : #include <rte_byteorder.h>
      13                 :            : #include <rte_bitops.h>
      14                 :            : #include <rte_common.h>
      15                 :            : #include <rte_vxlan.h>
      16                 :            : 
      17                 :            : #include "efx.h"
      18                 :            : 
      19                 :            : #include "sfc.h"
      20                 :            : #include "sfc_flow_tunnel.h"
      21                 :            : #include "sfc_mae_counter.h"
      22                 :            : #include "sfc_mae_ct.h"
      23                 :            : #include "sfc_log.h"
      24                 :            : #include "sfc_switch.h"
      25                 :            : #include "sfc_service.h"
      26                 :            : 
      27                 :            : static int
      28                 :          0 : sfc_mae_assign_ethdev_mport(struct sfc_adapter *sa,
      29                 :            :                             efx_mport_sel_t *mportp)
      30                 :            : {
      31                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
      32                 :            : 
      33                 :          0 :         return efx_mae_mport_by_pcie_function(encp->enc_pf, encp->enc_vf,
      34                 :            :                                               mportp);
      35                 :            : }
      36                 :            : 
      37                 :            : static int
      38                 :          0 : sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
      39                 :            :                             efx_mport_sel_t *mportp)
      40                 :            : {
      41                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
      42                 :            :         int rc = 0;
      43                 :            : 
      44         [ #  # ]:          0 :         if (encp->enc_mae_admin) {
      45                 :            :                 /*
      46                 :            :                  * This ethdev sits on MAE admin PF. The represented
      47                 :            :                  * entity is the network port assigned to that PF.
      48                 :            :                  */
      49                 :          0 :                 rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, mportp);
      50                 :            :         } else {
      51                 :            :                 /*
      52                 :            :                  * This ethdev sits on unprivileged PF / VF. The entity
      53                 :            :                  * represented by the ethdev can change dynamically
      54                 :            :                  * as MAE admin changes default traffic rules.
      55                 :            :                  *
      56                 :            :                  * For the sake of simplicity, do not fill in the m-port
      57                 :            :                  * and assume that flow rules should not be allowed to
      58                 :            :                  * reference the entity represented by this ethdev.
      59                 :            :                  */
      60                 :          0 :                 efx_mae_mport_invalid(mportp);
      61                 :            :         }
      62                 :            : 
      63                 :          0 :         return rc;
      64                 :            : }
      65                 :            : 
      66                 :            : static int
      67                 :          0 : sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
      68                 :            :                               uint32_t nb_action_counters_max,
      69                 :            :                               uint32_t nb_conntrack_counters_max)
      70                 :            : {
      71                 :            :         int ret;
      72                 :            : 
      73                 :          0 :         ret = sfc_mae_counters_init(&registry->action_counters,
      74                 :            :                                     nb_action_counters_max);
      75         [ #  # ]:          0 :         if (ret != 0)
      76                 :            :                 return ret;
      77                 :            : 
      78                 :          0 :         registry->action_counters.type = EFX_COUNTER_TYPE_ACTION;
      79                 :            : 
      80                 :          0 :         ret = sfc_mae_counters_init(&registry->conntrack_counters,
      81                 :            :                                     nb_conntrack_counters_max);
      82         [ #  # ]:          0 :         if (ret != 0)
      83                 :            :                 return ret;
      84                 :            : 
      85                 :          0 :         registry->conntrack_counters.type = EFX_COUNTER_TYPE_CONNTRACK;
      86                 :            : 
      87                 :          0 :         return 0;
      88                 :            : }
      89                 :            : 
      90                 :            : static void
      91                 :            : sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
      92                 :            : {
      93                 :          0 :         sfc_mae_counters_fini(&registry->conntrack_counters);
      94                 :          0 :         sfc_mae_counters_fini(&registry->action_counters);
      95                 :          0 : }
      96                 :            : 
      97                 :            : struct rte_flow *
      98                 :          0 : sfc_mae_repr_flow_create(struct sfc_adapter *sa, int prio, uint16_t port_id,
      99                 :            :                          enum rte_flow_action_type dst_type,
     100                 :            :                          enum rte_flow_item_type src_type)
     101                 :            : {
     102                 :          0 :         const struct rte_flow_item_ethdev item_spec = { .port_id = port_id };
     103                 :          0 :         const struct rte_flow_action_ethdev action = { .port_id = port_id };
     104                 :            :         const void *item_mask = &rte_flow_item_ethdev_mask;
     105                 :          0 :         struct rte_flow_attr attr = { .transfer = 1 };
     106                 :          0 :         const struct rte_flow_action actions[] = {
     107                 :            :                 { .type = dst_type, .conf = &action },
     108                 :            :                 { .type = RTE_FLOW_ACTION_TYPE_END }
     109                 :            :         };
     110                 :          0 :         const struct rte_flow_item items[] = {
     111                 :            :                 { .type = src_type, .mask = item_mask, .spec = &item_spec },
     112                 :            :                 { .type = RTE_FLOW_ITEM_TYPE_END }
     113                 :            :         };
     114                 :            :         struct sfc_mae *mae = &sa->mae;
     115                 :            :         struct rte_flow_error error;
     116                 :            : 
     117   [ #  #  #  # ]:          0 :         if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
     118                 :          0 :                 sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
     119                 :            :                         mae->nb_action_rule_prios_max);
     120                 :          0 :                 return NULL;
     121                 :            :         }
     122         [ #  # ]:          0 :         if (prio < 0)
     123                 :          0 :                 prio = mae->nb_action_rule_prios_max - 1;
     124                 :            : 
     125                 :          0 :         attr.priority = prio;
     126                 :            : 
     127                 :          0 :         return sfc_flow_create_locked(sa, true, &attr, items, actions, &error);
     128                 :            : }
     129                 :            : 
     130                 :            : void
     131                 :          0 : sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow)
     132                 :            : {
     133                 :            :         struct rte_flow_error error;
     134                 :            :         int rc;
     135                 :            : 
     136                 :          0 :         rc = sfc_flow_destroy_locked(sa, flow, &error);
     137         [ #  # ]:          0 :         if (rc != 0)
     138                 :          0 :                 sfc_err(sa, "failed to destroy the internal flow");
     139                 :          0 : }
     140                 :            : 
     141                 :            : int
     142                 :          0 : sfc_mae_attach(struct sfc_adapter *sa)
     143                 :            : {
     144                 :            :         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
     145                 :          0 :         struct sfc_mae_switch_port_request switch_port_request = {0};
     146                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
     147                 :            :         efx_mport_sel_t ethdev_mport;
     148                 :            :         efx_mport_sel_t entity_mport;
     149                 :            :         struct sfc_mae *mae = &sa->mae;
     150                 :            :         struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
     151                 :            :         efx_mae_limits_t limits;
     152                 :            :         int rc;
     153                 :            : 
     154                 :          0 :         sfc_log_init(sa, "entry");
     155                 :            : 
     156         [ #  # ]:          0 :         if (!encp->enc_mae_supported) {
     157                 :          0 :                 mae->status = SFC_MAE_STATUS_UNSUPPORTED;
     158                 :          0 :                 return 0;
     159                 :            :         }
     160                 :            : 
     161         [ #  # ]:          0 :         if (encp->enc_mae_admin) {
     162                 :          0 :                 sfc_log_init(sa, "init MAE");
     163                 :          0 :                 rc = efx_mae_init(sa->nic);
     164         [ #  # ]:          0 :                 if (rc != 0)
     165                 :          0 :                         goto fail_mae_init;
     166                 :            : 
     167                 :          0 :                 sfc_log_init(sa, "get MAE limits");
     168                 :          0 :                 rc = efx_mae_get_limits(sa->nic, &limits);
     169         [ #  # ]:          0 :                 if (rc != 0)
     170                 :          0 :                         goto fail_mae_get_limits;
     171                 :            : 
     172                 :          0 :                 sfc_log_init(sa, "init MAE counter record registry");
     173                 :          0 :                 rc = sfc_mae_counter_registry_init(&mae->counter_registry,
     174                 :            :                                         limits.eml_max_n_action_counters,
     175                 :            :                                         limits.eml_max_n_conntrack_counters);
     176         [ #  # ]:          0 :                 if (rc != 0) {
     177                 :          0 :                         sfc_err(sa, "failed to init record registry for %u AR and %u CT counters: %s",
     178                 :            :                                 limits.eml_max_n_action_counters,
     179                 :            :                                 limits.eml_max_n_conntrack_counters,
     180                 :            :                                 rte_strerror(rc));
     181                 :          0 :                         goto fail_counter_registry_init;
     182                 :            :                 }
     183                 :            :         }
     184                 :            : 
     185                 :          0 :         sfc_log_init(sa, "assign ethdev MPORT");
     186                 :          0 :         rc = sfc_mae_assign_ethdev_mport(sa, &ethdev_mport);
     187         [ #  # ]:          0 :         if (rc != 0)
     188                 :          0 :                 goto fail_mae_assign_ethdev_mport;
     189                 :            : 
     190                 :          0 :         sfc_log_init(sa, "assign entity MPORT");
     191                 :          0 :         rc = sfc_mae_assign_entity_mport(sa, &entity_mport);
     192         [ #  # ]:          0 :         if (rc != 0)
     193                 :          0 :                 goto fail_mae_assign_entity_mport;
     194                 :            : 
     195                 :          0 :         sfc_log_init(sa, "assign RTE switch domain");
     196                 :          0 :         rc = sfc_mae_assign_switch_domain(sa, &mae->switch_domain_id);
     197         [ #  # ]:          0 :         if (rc != 0)
     198                 :          0 :                 goto fail_mae_assign_switch_domain;
     199                 :            : 
     200                 :          0 :         sfc_log_init(sa, "assign RTE switch port");
     201                 :          0 :         switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
     202                 :          0 :         switch_port_request.ethdev_mportp = &ethdev_mport;
     203                 :          0 :         switch_port_request.entity_mportp = &entity_mport;
     204                 :          0 :         switch_port_request.ethdev_port_id = sas->port_id;
     205                 :          0 :         switch_port_request.port_data.indep.mae_admin =
     206                 :          0 :                 encp->enc_mae_admin == B_TRUE;
     207                 :          0 :         rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
     208                 :            :                                         &switch_port_request,
     209                 :            :                                         &mae->switch_port_id);
     210         [ #  # ]:          0 :         if (rc != 0)
     211                 :          0 :                 goto fail_mae_assign_switch_port;
     212                 :            : 
     213         [ #  # ]:          0 :         if (encp->enc_mae_admin) {
     214                 :          0 :                 sfc_log_init(sa, "allocate encap. header bounce buffer");
     215                 :          0 :                 bounce_eh->buf_size = limits.eml_encap_header_size_limit;
     216                 :          0 :                 bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh",
     217                 :            :                                             bounce_eh->buf_size, 0);
     218         [ #  # ]:          0 :                 if (bounce_eh->buf == NULL) {
     219                 :            :                         rc = ENOMEM;
     220                 :          0 :                         goto fail_mae_alloc_bounce_eh;
     221                 :            :                 }
     222                 :            : 
     223                 :          0 :                 sfc_log_init(sa, "allocate bounce action set pointer array");
     224                 :          0 :                 mae->bounce_aset_ptrs = rte_calloc("sfc_mae_bounce_aset_ptrs",
     225                 :            :                                         EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES,
     226                 :            :                                         sizeof(*mae->bounce_aset_ptrs), 0);
     227         [ #  # ]:          0 :                 if (mae->bounce_aset_ptrs == NULL) {
     228                 :            :                         rc = ENOMEM;
     229                 :          0 :                         goto fail_mae_alloc_bounce_aset_ptrs;
     230                 :            :                 }
     231                 :            : 
     232                 :          0 :                 sfc_log_init(sa, "allocate bounce action set contexts");
     233                 :          0 :                 mae->bounce_aset_ctxs = rte_calloc("sfc_mae_bounce_aset_ctxs",
     234                 :            :                                         EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES,
     235                 :            :                                         sizeof(*mae->bounce_aset_ctxs), 0);
     236         [ #  # ]:          0 :                 if (mae->bounce_aset_ctxs == NULL) {
     237                 :            :                         rc = ENOMEM;
     238                 :          0 :                         goto fail_mae_alloc_bounce_aset_ctxs;
     239                 :            :                 }
     240                 :            : 
     241                 :          0 :                 sfc_log_init(sa, "allocate bounce action set ID array");
     242                 :          0 :                 mae->bounce_aset_ids = rte_calloc("sfc_mae_bounce_aset_ids",
     243                 :            :                                         EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES,
     244                 :            :                                         sizeof(*mae->bounce_aset_ids), 0);
     245         [ #  # ]:          0 :                 if (mae->bounce_aset_ids == NULL) {
     246                 :            :                         rc = ENOMEM;
     247                 :          0 :                         goto fail_mae_alloc_bounce_aset_ids;
     248                 :            :                 }
     249                 :            : 
     250                 :          0 :                 mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
     251                 :          0 :                 mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
     252                 :          0 :                 mae->encap_types_supported = limits.eml_encap_types_supported;
     253                 :            :         }
     254                 :            : 
     255                 :          0 :         TAILQ_INIT(&mae->outer_rules);
     256                 :          0 :         TAILQ_INIT(&mae->mac_addrs);
     257                 :          0 :         TAILQ_INIT(&mae->encap_headers);
     258                 :          0 :         TAILQ_INIT(&mae->counters);
     259                 :          0 :         TAILQ_INIT(&mae->action_sets);
     260                 :          0 :         TAILQ_INIT(&mae->action_set_lists);
     261                 :          0 :         TAILQ_INIT(&mae->action_rules);
     262                 :            : 
     263         [ #  # ]:          0 :         if (encp->enc_mae_admin)
     264                 :          0 :                 mae->status = SFC_MAE_STATUS_ADMIN;
     265                 :            :         else
     266                 :          0 :                 mae->status = SFC_MAE_STATUS_SUPPORTED;
     267                 :            : 
     268                 :          0 :         sfc_log_init(sa, "done");
     269                 :            : 
     270                 :          0 :         return 0;
     271                 :            : 
     272                 :            : fail_mae_alloc_bounce_aset_ids:
     273                 :          0 :         rte_free(mae->bounce_aset_ctxs);
     274                 :            : 
     275                 :          0 : fail_mae_alloc_bounce_aset_ctxs:
     276                 :          0 :         rte_free(mae->bounce_aset_ptrs);
     277                 :            : 
     278                 :          0 : fail_mae_alloc_bounce_aset_ptrs:
     279                 :          0 :         rte_free(mae->bounce_eh.buf);
     280                 :            : 
     281                 :          0 : fail_mae_alloc_bounce_eh:
     282                 :          0 : fail_mae_assign_switch_port:
     283                 :          0 : fail_mae_assign_switch_domain:
     284                 :          0 : fail_mae_assign_entity_mport:
     285                 :          0 : fail_mae_assign_ethdev_mport:
     286         [ #  # ]:          0 :         if (encp->enc_mae_admin)
     287                 :            :                 sfc_mae_counter_registry_fini(&mae->counter_registry);
     288                 :            : 
     289                 :          0 : fail_counter_registry_init:
     290                 :          0 : fail_mae_get_limits:
     291         [ #  # ]:          0 :         if (encp->enc_mae_admin)
     292                 :          0 :                 efx_mae_fini(sa->nic);
     293                 :            : 
     294                 :          0 : fail_mae_init:
     295                 :          0 :         sfc_log_init(sa, "failed %d", rc);
     296                 :            : 
     297                 :          0 :         return rc;
     298                 :            : }
     299                 :            : 
     300                 :            : void
     301                 :          0 : sfc_mae_detach(struct sfc_adapter *sa)
     302                 :            : {
     303                 :            :         struct sfc_mae *mae = &sa->mae;
     304                 :          0 :         enum sfc_mae_status status_prev = mae->status;
     305                 :            : 
     306                 :          0 :         sfc_log_init(sa, "entry");
     307                 :            : 
     308                 :          0 :         mae->nb_action_rule_prios_max = 0;
     309                 :          0 :         mae->status = SFC_MAE_STATUS_UNKNOWN;
     310                 :            : 
     311         [ #  # ]:          0 :         if (status_prev != SFC_MAE_STATUS_ADMIN)
     312                 :            :                 return;
     313                 :            : 
     314                 :          0 :         rte_free(mae->bounce_aset_ids);
     315                 :          0 :         rte_free(mae->bounce_aset_ctxs);
     316                 :          0 :         rte_free(mae->bounce_aset_ptrs);
     317                 :          0 :         rte_free(mae->bounce_eh.buf);
     318                 :            :         sfc_mae_counter_registry_fini(&mae->counter_registry);
     319                 :            : 
     320                 :          0 :         efx_mae_fini(sa->nic);
     321                 :            : 
     322                 :          0 :         sfc_log_init(sa, "done");
     323                 :            : }
     324                 :            : 
     325                 :            : static struct sfc_mae_outer_rule *
     326                 :          0 : sfc_mae_outer_rule_attach(struct sfc_adapter *sa,
     327                 :            :                           const efx_mae_match_spec_t *match_spec,
     328                 :            :                           efx_tunnel_protocol_t encap_type)
     329                 :            : {
     330                 :            :         struct sfc_mae_outer_rule *rule;
     331                 :            :         struct sfc_mae *mae = &sa->mae;
     332                 :            : 
     333                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     334                 :            : 
     335         [ #  # ]:          0 :         TAILQ_FOREACH(rule, &mae->outer_rules, entries) {
     336         [ #  # ]:          0 :                 if (efx_mae_match_specs_equal(rule->match_spec, match_spec) &&
     337         [ #  # ]:          0 :                     rule->encap_type == encap_type) {
     338                 :          0 :                         sfc_dbg(sa, "attaching to outer_rule=%p", rule);
     339                 :          0 :                         ++(rule->refcnt);
     340                 :          0 :                         return rule;
     341                 :            :                 }
     342                 :            :         }
     343                 :            : 
     344                 :            :         return NULL;
     345                 :            : }
     346                 :            : 
     347                 :            : static int
     348                 :          0 : sfc_mae_outer_rule_add(struct sfc_adapter *sa,
     349                 :            :                        efx_mae_match_spec_t *match_spec,
     350                 :            :                        efx_tunnel_protocol_t encap_type,
     351                 :            :                        struct sfc_mae_outer_rule **rulep)
     352                 :            : {
     353                 :            :         struct sfc_mae_outer_rule *rule;
     354                 :            :         struct sfc_mae *mae = &sa->mae;
     355                 :            : 
     356                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     357                 :            : 
     358                 :          0 :         rule = rte_zmalloc("sfc_mae_outer_rule", sizeof(*rule), 0);
     359         [ #  # ]:          0 :         if (rule == NULL)
     360                 :            :                 return ENOMEM;
     361                 :            : 
     362                 :          0 :         rule->refcnt = 1;
     363                 :          0 :         rule->match_spec = match_spec;
     364                 :          0 :         rule->encap_type = encap_type;
     365                 :            : 
     366                 :          0 :         rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
     367                 :            : 
     368                 :          0 :         TAILQ_INSERT_TAIL(&mae->outer_rules, rule, entries);
     369                 :            : 
     370                 :          0 :         *rulep = rule;
     371                 :            : 
     372                 :          0 :         sfc_dbg(sa, "added outer_rule=%p", rule);
     373                 :            : 
     374                 :          0 :         return 0;
     375                 :            : }
     376                 :            : 
     377                 :            : static void
     378                 :          0 : sfc_mae_outer_rule_del(struct sfc_adapter *sa,
     379                 :            :                        struct sfc_mae_outer_rule *rule)
     380                 :            : {
     381                 :            :         struct sfc_mae *mae = &sa->mae;
     382                 :            : 
     383         [ #  # ]:          0 :         if (rule == NULL)
     384                 :            :                 return;
     385                 :            : 
     386                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     387                 :            :         SFC_ASSERT(rule->refcnt != 0);
     388                 :            : 
     389                 :          0 :         --(rule->refcnt);
     390                 :            : 
     391         [ #  # ]:          0 :         if (rule->refcnt != 0)
     392                 :            :                 return;
     393                 :            : 
     394         [ #  # ]:          0 :         if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
     395         [ #  # ]:          0 :             rule->fw_rsrc.refcnt != 0) {
     396                 :          0 :                 sfc_err(sa, "deleting outer_rule=%p abandons its FW resource: OR_ID=0x%08x, refcnt=%u",
     397                 :            :                         rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
     398                 :            :         }
     399                 :            : 
     400                 :          0 :         efx_mae_match_spec_fini(sa->nic, rule->match_spec);
     401                 :            : 
     402         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->outer_rules, rule, entries);
     403                 :          0 :         sfc_dbg(sa, "deleted outer_rule=%p", rule);
     404                 :          0 :         rte_free(rule);
     405                 :            : }
     406                 :            : 
     407                 :            : static int
     408                 :          0 : sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
     409                 :            :                           struct sfc_mae_outer_rule *rule,
     410                 :            :                           efx_mae_match_spec_t *match_spec_action)
     411                 :            : {
     412                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     413                 :            :         int rc;
     414                 :            : 
     415         [ #  # ]:          0 :         if (rule == NULL)
     416                 :            :                 return 0;
     417                 :            : 
     418                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     419                 :            : 
     420                 :            :         fw_rsrc = &rule->fw_rsrc;
     421                 :            : 
     422         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     423                 :            :                 SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
     424                 :            :                 SFC_ASSERT(rule->match_spec != NULL);
     425                 :            : 
     426                 :          0 :                 rc = efx_mae_outer_rule_insert(sa->nic, rule->match_spec,
     427                 :            :                                                rule->encap_type,
     428                 :            :                                                &fw_rsrc->rule_id);
     429         [ #  # ]:          0 :                 if (rc != 0) {
     430                 :          0 :                         sfc_err(sa, "failed to enable outer_rule=%p: %s",
     431                 :            :                                 rule, strerror(rc));
     432                 :          0 :                         return rc;
     433                 :            :                 }
     434                 :            :         }
     435                 :            : 
     436         [ #  # ]:          0 :         if (match_spec_action == NULL)
     437                 :          0 :                 goto skip_action_rule;
     438                 :            : 
     439                 :          0 :         rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
     440                 :          0 :                                                   &fw_rsrc->rule_id);
     441         [ #  # ]:          0 :         if (rc != 0) {
     442         [ #  # ]:          0 :                 if (fw_rsrc->refcnt == 0) {
     443                 :          0 :                         (void)efx_mae_outer_rule_remove(sa->nic,
     444                 :            :                                                         &fw_rsrc->rule_id);
     445                 :          0 :                         fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
     446                 :            :                 }
     447                 :            : 
     448                 :          0 :                 sfc_err(sa, "can't match on outer rule ID: %s", strerror(rc));
     449                 :            : 
     450                 :          0 :                 return rc;
     451                 :            :         }
     452                 :            : 
     453                 :          0 : skip_action_rule:
     454         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     455                 :          0 :                 sfc_dbg(sa, "enabled outer_rule=%p: OR_ID=0x%08x",
     456                 :            :                         rule, fw_rsrc->rule_id.id);
     457                 :            :         }
     458                 :            : 
     459                 :          0 :         ++(fw_rsrc->refcnt);
     460                 :            : 
     461                 :          0 :         return 0;
     462                 :            : }
     463                 :            : 
     464                 :            : static void
     465                 :          0 : sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
     466                 :            :                            struct sfc_mae_outer_rule *rule,
     467                 :            :                            efx_mae_match_spec_t *match_spec_action)
     468                 :            : {
     469                 :          0 :         efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
     470                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     471                 :            :         int rc;
     472                 :            : 
     473         [ #  # ]:          0 :         if (rule == NULL)
     474                 :          0 :                 return;
     475                 :            : 
     476                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     477                 :            : 
     478                 :            :         fw_rsrc = &rule->fw_rsrc;
     479                 :            : 
     480         [ #  # ]:          0 :         if (match_spec_action == NULL)
     481                 :          0 :                 goto skip_action_rule;
     482                 :            : 
     483                 :          0 :         rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
     484                 :            :                                                   &invalid_rule_id);
     485         [ #  # ]:          0 :         if (rc != 0) {
     486                 :          0 :                 sfc_err(sa, "cannot restore match on invalid outer rule ID: %s",
     487                 :            :                         strerror(rc));
     488                 :          0 :                 return;
     489                 :            :         }
     490                 :            : 
     491                 :          0 : skip_action_rule:
     492         [ #  # ]:          0 :         if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
     493         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
     494                 :          0 :                 sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
     495                 :            :                         rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
     496                 :          0 :                 return;
     497                 :            :         }
     498                 :            : 
     499         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
     500                 :          0 :                 rc = efx_mae_outer_rule_remove(sa->nic, &fw_rsrc->rule_id);
     501         [ #  # ]:          0 :                 if (rc == 0) {
     502                 :          0 :                         sfc_dbg(sa, "disabled outer_rule=%p with OR_ID=0x%08x",
     503                 :            :                                 rule, fw_rsrc->rule_id.id);
     504                 :            :                 } else {
     505                 :          0 :                         sfc_err(sa, "failed to disable outer_rule=%p with OR_ID=0x%08x: %s",
     506                 :            :                                 rule, fw_rsrc->rule_id.id, strerror(rc));
     507                 :            :                 }
     508                 :          0 :                 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
     509                 :            :         }
     510                 :            : 
     511                 :          0 :         --(fw_rsrc->refcnt);
     512                 :            : }
     513                 :            : 
     514                 :            : static struct sfc_mae_mac_addr *
     515                 :          0 : sfc_mae_mac_addr_attach(struct sfc_adapter *sa,
     516                 :            :                         const uint8_t addr_bytes[EFX_MAC_ADDR_LEN])
     517                 :            : {
     518                 :            :         struct sfc_mae_mac_addr *mac_addr;
     519                 :            :         struct sfc_mae *mae = &sa->mae;
     520                 :            : 
     521                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     522                 :            : 
     523         [ #  # ]:          0 :         TAILQ_FOREACH(mac_addr, &mae->mac_addrs, entries) {
     524         [ #  # ]:          0 :                 if (memcmp(mac_addr->addr_bytes, addr_bytes,
     525                 :            :                            EFX_MAC_ADDR_LEN) == 0) {
     526                 :          0 :                         sfc_dbg(sa, "attaching to mac_addr=%p", mac_addr);
     527                 :          0 :                         ++(mac_addr->refcnt);
     528                 :          0 :                         return mac_addr;
     529                 :            :                 }
     530                 :            :         }
     531                 :            : 
     532                 :            :         return NULL;
     533                 :            : }
     534                 :            : 
     535                 :            : static int
     536                 :          0 : sfc_mae_mac_addr_add(struct sfc_adapter *sa,
     537                 :            :                      const uint8_t addr_bytes[EFX_MAC_ADDR_LEN],
     538                 :            :                      struct sfc_mae_mac_addr **mac_addrp)
     539                 :            : {
     540                 :            :         struct sfc_mae_mac_addr *mac_addr;
     541                 :            :         struct sfc_mae *mae = &sa->mae;
     542                 :            : 
     543                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     544                 :            : 
     545                 :          0 :         mac_addr = rte_zmalloc("sfc_mae_mac_addr", sizeof(*mac_addr), 0);
     546         [ #  # ]:          0 :         if (mac_addr == NULL)
     547                 :            :                 return ENOMEM;
     548                 :            : 
     549         [ #  # ]:          0 :         rte_memcpy(mac_addr->addr_bytes, addr_bytes, EFX_MAC_ADDR_LEN);
     550                 :            : 
     551                 :          0 :         mac_addr->refcnt = 1;
     552                 :          0 :         mac_addr->fw_rsrc.mac_id.id = EFX_MAE_RSRC_ID_INVALID;
     553                 :            : 
     554                 :          0 :         TAILQ_INSERT_TAIL(&mae->mac_addrs, mac_addr, entries);
     555                 :            : 
     556                 :          0 :         *mac_addrp = mac_addr;
     557                 :            : 
     558                 :          0 :         sfc_dbg(sa, "added mac_addr=%p", mac_addr);
     559                 :            : 
     560                 :          0 :         return 0;
     561                 :            : }
     562                 :            : 
     563                 :            : static void
     564                 :          0 : sfc_mae_mac_addr_del(struct sfc_adapter *sa, struct sfc_mae_mac_addr *mac_addr)
     565                 :            : {
     566                 :            :         struct sfc_mae *mae = &sa->mae;
     567                 :            : 
     568         [ #  # ]:          0 :         if (mac_addr == NULL)
     569                 :            :                 return;
     570                 :            : 
     571                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     572                 :            :         SFC_ASSERT(mac_addr->refcnt != 0);
     573                 :            : 
     574                 :          0 :         --(mac_addr->refcnt);
     575                 :            : 
     576         [ #  # ]:          0 :         if (mac_addr->refcnt != 0)
     577                 :            :                 return;
     578                 :            : 
     579         [ #  # ]:          0 :         if (mac_addr->fw_rsrc.mac_id.id != EFX_MAE_RSRC_ID_INVALID ||
     580         [ #  # ]:          0 :             mac_addr->fw_rsrc.refcnt != 0) {
     581                 :          0 :                 sfc_err(sa, "deleting mac_addr=%p abandons its FW resource: MAC_ID=0x%08x, refcnt=%u",
     582                 :            :                         mac_addr, mac_addr->fw_rsrc.mac_id.id,
     583                 :            :                         mac_addr->fw_rsrc.refcnt);
     584                 :            :         }
     585                 :            : 
     586         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->mac_addrs, mac_addr, entries);
     587                 :          0 :         sfc_dbg(sa, "deleted mac_addr=%p", mac_addr);
     588                 :          0 :         rte_free(mac_addr);
     589                 :            : }
     590                 :            : 
     591                 :            : enum sfc_mae_mac_addr_type {
     592                 :            :         SFC_MAE_MAC_ADDR_DST,
     593                 :            :         SFC_MAE_MAC_ADDR_SRC
     594                 :            : };
     595                 :            : 
     596                 :            : static int
     597                 :          0 : sfc_mae_mac_addr_enable(struct sfc_adapter *sa,
     598                 :            :                         struct sfc_mae_mac_addr *mac_addr,
     599                 :            :                         enum sfc_mae_mac_addr_type type,
     600                 :            :                         efx_mae_actions_t *aset_spec)
     601                 :            : {
     602                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     603                 :            :         int rc = 0;
     604                 :            : 
     605         [ #  # ]:          0 :         if (mac_addr == NULL)
     606                 :            :                 return 0;
     607                 :            : 
     608                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     609                 :            : 
     610                 :            :         fw_rsrc = &mac_addr->fw_rsrc;
     611                 :            : 
     612         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     613                 :            :                 SFC_ASSERT(fw_rsrc->mac_id.id == EFX_MAE_RSRC_ID_INVALID);
     614                 :            : 
     615                 :          0 :                 rc = efx_mae_mac_addr_alloc(sa->nic, mac_addr->addr_bytes,
     616                 :            :                                             &fw_rsrc->mac_id);
     617         [ #  # ]:          0 :                 if (rc != 0) {
     618                 :          0 :                         sfc_err(sa, "failed to enable mac_addr=%p: %s",
     619                 :            :                                 mac_addr, strerror(rc));
     620                 :          0 :                         return rc;
     621                 :            :                 }
     622                 :            :         }
     623                 :            : 
     624      [ #  #  # ]:          0 :         switch (type) {
     625                 :          0 :         case SFC_MAE_MAC_ADDR_DST:
     626                 :          0 :                 rc = efx_mae_action_set_fill_in_dst_mac_id(aset_spec,
     627                 :          0 :                                                            &fw_rsrc->mac_id);
     628                 :          0 :                 break;
     629                 :          0 :         case SFC_MAE_MAC_ADDR_SRC:
     630                 :          0 :                 rc = efx_mae_action_set_fill_in_src_mac_id(aset_spec,
     631                 :          0 :                                                            &fw_rsrc->mac_id);
     632                 :          0 :                 break;
     633                 :            :         default:
     634                 :            :                 rc = EINVAL;
     635                 :            :                 break;
     636                 :            :         }
     637                 :            : 
     638         [ #  # ]:          0 :         if (rc != 0) {
     639         [ #  # ]:          0 :                 if (fw_rsrc->refcnt == 0) {
     640                 :          0 :                         (void)efx_mae_mac_addr_free(sa->nic, &fw_rsrc->mac_id);
     641                 :          0 :                         fw_rsrc->mac_id.id = EFX_MAE_RSRC_ID_INVALID;
     642                 :            :                 }
     643                 :            : 
     644                 :          0 :                 sfc_err(sa, "cannot fill in MAC address entry ID: %s",
     645                 :            :                         strerror(rc));
     646                 :            : 
     647                 :          0 :                 return rc;
     648                 :            :         }
     649                 :            : 
     650         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     651                 :          0 :                 sfc_dbg(sa, "enabled mac_addr=%p: MAC_ID=0x%08x",
     652                 :            :                         mac_addr, fw_rsrc->mac_id.id);
     653                 :            :         }
     654                 :            : 
     655                 :          0 :         ++(fw_rsrc->refcnt);
     656                 :            : 
     657                 :          0 :         return 0;
     658                 :            : }
     659                 :            : 
     660                 :            : static void
     661                 :          0 : sfc_mae_mac_addr_disable(struct sfc_adapter *sa,
     662                 :            :                          struct sfc_mae_mac_addr *mac_addr)
     663                 :            : {
     664                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     665                 :            :         int rc;
     666                 :            : 
     667         [ #  # ]:          0 :         if (mac_addr == NULL)
     668                 :            :                 return;
     669                 :            : 
     670                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     671                 :            : 
     672                 :            :         fw_rsrc = &mac_addr->fw_rsrc;
     673                 :            : 
     674         [ #  # ]:          0 :         if (fw_rsrc->mac_id.id == EFX_MAE_RSRC_ID_INVALID ||
     675         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
     676                 :          0 :                 sfc_err(sa, "failed to disable mac_addr=%p: already disabled; MAC_ID=0x%08x, refcnt=%u",
     677                 :            :                         mac_addr, fw_rsrc->mac_id.id, fw_rsrc->refcnt);
     678                 :          0 :                 return;
     679                 :            :         }
     680                 :            : 
     681         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
     682                 :          0 :                 rc = efx_mae_mac_addr_free(sa->nic, &fw_rsrc->mac_id);
     683         [ #  # ]:          0 :                 if (rc == 0) {
     684                 :          0 :                         sfc_dbg(sa, "disabled mac_addr=%p with MAC_ID=0x%08x",
     685                 :            :                                 mac_addr, fw_rsrc->mac_id.id);
     686                 :            :                 } else {
     687                 :          0 :                         sfc_err(sa, "failed to disable mac_addr=%p with MAC_ID=0x%08x: %s",
     688                 :            :                                 mac_addr, fw_rsrc->mac_id.id, strerror(rc));
     689                 :            :                 }
     690                 :          0 :                 fw_rsrc->mac_id.id = EFX_MAE_RSRC_ID_INVALID;
     691                 :            :         }
     692                 :            : 
     693                 :          0 :         --(fw_rsrc->refcnt);
     694                 :            : }
     695                 :            : 
     696                 :            : static struct sfc_mae_encap_header *
     697                 :          0 : sfc_mae_encap_header_attach(struct sfc_adapter *sa,
     698                 :            :                             const struct sfc_mae_bounce_eh *bounce_eh)
     699                 :            : {
     700                 :            :         struct sfc_mae_encap_header *encap_header;
     701                 :            :         struct sfc_mae *mae = &sa->mae;
     702                 :            : 
     703                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     704                 :            : 
     705         [ #  # ]:          0 :         TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) {
     706         [ #  # ]:          0 :                 if (encap_header->indirect)
     707                 :          0 :                         continue;
     708                 :            : 
     709         [ #  # ]:          0 :                 if (encap_header->size == bounce_eh->size &&
     710         [ #  # ]:          0 :                     memcmp(encap_header->buf, bounce_eh->buf,
     711                 :            :                            bounce_eh->size) == 0) {
     712                 :          0 :                         sfc_dbg(sa, "attaching to encap_header=%p",
     713                 :            :                                 encap_header);
     714                 :          0 :                         ++(encap_header->refcnt);
     715                 :          0 :                         return encap_header;
     716                 :            :                 }
     717                 :            :         }
     718                 :            : 
     719                 :            :         return NULL;
     720                 :            : }
     721                 :            : 
     722                 :            : static int
     723                 :          0 : sfc_mae_encap_header_add(struct sfc_adapter *sa,
     724                 :            :                          const struct sfc_mae_bounce_eh *bounce_eh,
     725                 :            :                          struct sfc_mae_encap_header **encap_headerp)
     726                 :            : {
     727                 :            :         struct sfc_mae_encap_header *encap_header;
     728                 :            :         struct sfc_mae *mae = &sa->mae;
     729                 :            : 
     730                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     731                 :            : 
     732                 :          0 :         encap_header = rte_zmalloc("sfc_mae_encap_header",
     733                 :            :                                    sizeof(*encap_header), 0);
     734         [ #  # ]:          0 :         if (encap_header == NULL)
     735                 :            :                 return ENOMEM;
     736                 :            : 
     737                 :          0 :         encap_header->size = bounce_eh->size;
     738                 :            : 
     739                 :          0 :         encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
     740                 :            :                                        encap_header->size, 0);
     741         [ #  # ]:          0 :         if (encap_header->buf == NULL) {
     742                 :          0 :                 rte_free(encap_header);
     743                 :          0 :                 return ENOMEM;
     744                 :            :         }
     745                 :            : 
     746         [ #  # ]:          0 :         rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size);
     747                 :            : 
     748                 :          0 :         encap_header->refcnt = 1;
     749                 :          0 :         encap_header->type = bounce_eh->type;
     750                 :          0 :         encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID;
     751                 :            : 
     752                 :          0 :         TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries);
     753                 :            : 
     754                 :          0 :         *encap_headerp = encap_header;
     755                 :            : 
     756                 :          0 :         sfc_dbg(sa, "added encap_header=%p", encap_header);
     757                 :            : 
     758                 :          0 :         return 0;
     759                 :            : }
     760                 :            : 
     761                 :            : static void
     762                 :          0 : sfc_mae_encap_header_del(struct sfc_adapter *sa,
     763                 :            :                        struct sfc_mae_encap_header *encap_header)
     764                 :            : {
     765                 :            :         struct sfc_mae *mae = &sa->mae;
     766                 :            : 
     767         [ #  # ]:          0 :         if (encap_header == NULL)
     768                 :            :                 return;
     769                 :            : 
     770                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     771                 :            :         SFC_ASSERT(encap_header->refcnt != 0);
     772                 :            : 
     773                 :          0 :         --(encap_header->refcnt);
     774                 :            : 
     775         [ #  # ]:          0 :         if (encap_header->refcnt != 0)
     776                 :            :                 return;
     777                 :            : 
     778         [ #  # ]:          0 :         if (encap_header->fw_rsrc.eh_id.id != EFX_MAE_RSRC_ID_INVALID ||
     779         [ #  # ]:          0 :             encap_header->fw_rsrc.refcnt != 0) {
     780                 :          0 :                 sfc_err(sa, "deleting encap_header=%p abandons its FW resource: EH_ID=0x%08x, refcnt=%u",
     781                 :            :                         encap_header, encap_header->fw_rsrc.eh_id.id,
     782                 :            :                         encap_header->fw_rsrc.refcnt);
     783                 :            :         }
     784                 :            : 
     785         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->encap_headers, encap_header, entries);
     786                 :          0 :         sfc_dbg(sa, "deleted encap_header=%p", encap_header);
     787                 :            : 
     788                 :          0 :         rte_free(encap_header->buf);
     789                 :          0 :         rte_free(encap_header);
     790                 :            : }
     791                 :            : 
     792                 :            : static int
     793                 :          0 : sfc_mae_encap_header_update(struct sfc_adapter *sa,
     794                 :            :                             struct sfc_mae_encap_header *encap_header)
     795                 :            : {
     796                 :            :         const struct sfc_mae_bounce_eh *bounce_eh = &sa->mae.bounce_eh;
     797                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     798                 :            :         uint8_t *buf;
     799                 :            :         int ret;
     800                 :            : 
     801         [ #  # ]:          0 :         if (bounce_eh->type != encap_header->type ||
     802         [ #  # ]:          0 :             bounce_eh->size == 0)
     803                 :            :                 return EINVAL;
     804                 :            : 
     805                 :          0 :         buf = rte_malloc("sfc_mae_encap_header_buf", bounce_eh->size, 0);
     806         [ #  # ]:          0 :         if (buf == NULL)
     807                 :            :                 return ENOMEM;
     808                 :            : 
     809         [ #  # ]:          0 :         rte_memcpy(buf, bounce_eh->buf, bounce_eh->size);
     810                 :            : 
     811                 :            :         fw_rsrc = &encap_header->fw_rsrc;
     812                 :            : 
     813         [ #  # ]:          0 :         if (fw_rsrc->refcnt > 0) {
     814                 :            :                 SFC_ASSERT(fw_rsrc->eh_id.id != EFX_MAE_RSRC_ID_INVALID);
     815                 :            : 
     816                 :          0 :                 ret = efx_mae_encap_header_update(sa->nic, &fw_rsrc->eh_id,
     817                 :            :                                                   encap_header->type, buf,
     818                 :            :                                                   bounce_eh->size);
     819         [ #  # ]:          0 :                 if (ret != 0) {
     820                 :          0 :                         sfc_err(sa, "failed to update encap_header=%p: %s",
     821                 :            :                                 encap_header, strerror(ret));
     822                 :          0 :                         rte_free(buf);
     823                 :          0 :                         return ret;
     824                 :            :                 }
     825                 :            :         }
     826                 :            : 
     827                 :          0 :         encap_header->size = bounce_eh->size;
     828                 :          0 :         rte_free(encap_header->buf);
     829                 :          0 :         encap_header->buf = buf;
     830                 :            : 
     831                 :          0 :         sfc_dbg(sa, "updated encap_header=%p", encap_header);
     832                 :            : 
     833                 :          0 :         return 0;
     834                 :            : }
     835                 :            : 
     836                 :            : static int
     837                 :          0 : sfc_mae_encap_header_enable(struct sfc_adapter *sa,
     838                 :            :                             struct sfc_mae_encap_header *encap_header,
     839                 :            :                             efx_mae_actions_t *action_set_spec)
     840                 :            : {
     841                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     842                 :            :         int rc;
     843                 :            : 
     844         [ #  # ]:          0 :         if (encap_header == NULL)
     845                 :            :                 return 0;
     846                 :            : 
     847                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     848                 :            : 
     849                 :            :         fw_rsrc = &encap_header->fw_rsrc;
     850                 :            : 
     851         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     852                 :            :                 SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID);
     853                 :            :                 SFC_ASSERT(encap_header->buf != NULL);
     854                 :            :                 SFC_ASSERT(encap_header->size != 0);
     855                 :            : 
     856                 :          0 :                 rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type,
     857                 :            :                                                 encap_header->buf,
     858                 :            :                                                 encap_header->size,
     859                 :            :                                                 &fw_rsrc->eh_id);
     860         [ #  # ]:          0 :                 if (rc != 0) {
     861                 :          0 :                         sfc_err(sa, "failed to enable encap_header=%p: %s",
     862                 :            :                                 encap_header, strerror(rc));
     863                 :          0 :                         return rc;
     864                 :            :                 }
     865                 :            :         }
     866                 :            : 
     867                 :          0 :         rc = efx_mae_action_set_fill_in_eh_id(action_set_spec,
     868                 :          0 :                                               &fw_rsrc->eh_id);
     869         [ #  # ]:          0 :         if (rc != 0) {
     870         [ #  # ]:          0 :                 if (fw_rsrc->refcnt == 0) {
     871                 :          0 :                         (void)efx_mae_encap_header_free(sa->nic,
     872                 :            :                                                         &fw_rsrc->eh_id);
     873                 :          0 :                         fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
     874                 :            :                 }
     875                 :            : 
     876                 :          0 :                 sfc_err(sa, "can't fill in encap. header ID: %s", strerror(rc));
     877                 :            : 
     878                 :          0 :                 return rc;
     879                 :            :         }
     880                 :            : 
     881         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
     882                 :          0 :                 sfc_dbg(sa, "enabled encap_header=%p: EH_ID=0x%08x",
     883                 :            :                         encap_header, fw_rsrc->eh_id.id);
     884                 :            :         }
     885                 :            : 
     886                 :          0 :         ++(fw_rsrc->refcnt);
     887                 :            : 
     888                 :          0 :         return 0;
     889                 :            : }
     890                 :            : 
     891                 :            : static void
     892                 :          0 : sfc_mae_encap_header_disable(struct sfc_adapter *sa,
     893                 :            :                              struct sfc_mae_encap_header *encap_header)
     894                 :            : {
     895                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     896                 :            :         int rc;
     897                 :            : 
     898         [ #  # ]:          0 :         if (encap_header == NULL)
     899                 :            :                 return;
     900                 :            : 
     901                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     902                 :            : 
     903                 :            :         fw_rsrc = &encap_header->fw_rsrc;
     904                 :            : 
     905         [ #  # ]:          0 :         if (fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID ||
     906         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
     907                 :          0 :                 sfc_err(sa, "failed to disable encap_header=%p: already disabled; EH_ID=0x%08x, refcnt=%u",
     908                 :            :                         encap_header, fw_rsrc->eh_id.id, fw_rsrc->refcnt);
     909                 :          0 :                 return;
     910                 :            :         }
     911                 :            : 
     912         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
     913                 :          0 :                 rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id);
     914         [ #  # ]:          0 :                 if (rc == 0) {
     915                 :          0 :                         sfc_dbg(sa, "disabled encap_header=%p with EH_ID=0x%08x",
     916                 :            :                                 encap_header, fw_rsrc->eh_id.id);
     917                 :            :                 } else {
     918                 :          0 :                         sfc_err(sa, "failed to disable encap_header=%p with EH_ID=0x%08x: %s",
     919                 :            :                                 encap_header, fw_rsrc->eh_id.id, strerror(rc));
     920                 :            :                 }
     921                 :          0 :                 fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
     922                 :            :         }
     923                 :            : 
     924                 :          0 :         --(fw_rsrc->refcnt);
     925                 :            : }
     926                 :            : 
     927                 :            : static int
     928                 :          0 : sfc_mae_counter_add(struct sfc_adapter *sa,
     929                 :            :                     const struct sfc_mae_counter *counter_tmp,
     930                 :            :                     struct sfc_mae_counter **counterp)
     931                 :            : {
     932                 :            :         struct sfc_mae_counter *counter;
     933                 :            :         struct sfc_mae *mae = &sa->mae;
     934                 :            : 
     935                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     936                 :            : 
     937                 :          0 :         counter = rte_zmalloc("sfc_mae_counter", sizeof(*counter), 0);
     938         [ #  # ]:          0 :         if (counter == NULL)
     939                 :            :                 return ENOMEM;
     940                 :            : 
     941         [ #  # ]:          0 :         if (counter_tmp != NULL) {
     942                 :          0 :                 counter->rte_id_valid = counter_tmp->rte_id_valid;
     943                 :          0 :                 counter->rte_id = counter_tmp->rte_id;
     944                 :          0 :                 counter->type = counter_tmp->type;
     945                 :            :         } else {
     946                 :          0 :                 counter->type = EFX_COUNTER_TYPE_ACTION;
     947                 :            :         }
     948                 :            : 
     949                 :          0 :         counter->fw_rsrc.counter_id.id = EFX_MAE_RSRC_ID_INVALID;
     950                 :          0 :         counter->refcnt = 1;
     951                 :            : 
     952                 :          0 :         TAILQ_INSERT_TAIL(&mae->counters, counter, entries);
     953                 :          0 :         *counterp = counter;
     954                 :            : 
     955                 :          0 :         sfc_dbg(sa, "added counter=%p", counter);
     956                 :            : 
     957                 :          0 :         return 0;
     958                 :            : }
     959                 :            : 
     960                 :            : static void
     961                 :          0 : sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
     962                 :            : {
     963                 :            :         struct sfc_mae *mae = &sa->mae;
     964                 :            : 
     965         [ #  # ]:          0 :         if (counter == NULL)
     966                 :            :                 return;
     967                 :            : 
     968                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
     969                 :            :         SFC_ASSERT(counter->refcnt != 0);
     970                 :            : 
     971                 :          0 :         --(counter->refcnt);
     972                 :            : 
     973         [ #  # ]:          0 :         if (counter->refcnt == 1)
     974                 :          0 :                 counter->ft_switch_hit_counter = NULL;
     975                 :            : 
     976         [ #  # ]:          0 :         if (counter->refcnt != 0)
     977                 :            :                 return;
     978                 :            : 
     979         [ #  # ]:          0 :         if (counter->fw_rsrc.counter_id.id != EFX_MAE_RSRC_ID_INVALID ||
     980                 :            :             counter->fw_rsrc.refcnt != 0) {
     981                 :          0 :                 sfc_err(sa, "deleting counter=%p abandons its FW resource: COUNTER_ID=0x%x-#%u, refcnt=%u",
     982                 :            :                         counter, counter->type, counter->fw_rsrc.counter_id.id,
     983                 :            :                         counter->fw_rsrc.refcnt);
     984                 :            :         }
     985                 :            : 
     986         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->counters, counter, entries);
     987                 :          0 :         sfc_dbg(sa, "deleted counter=%p", counter);
     988                 :          0 :         rte_free(counter);
     989                 :            : }
     990                 :            : 
     991                 :            : static int
     992                 :          0 : sfc_mae_counter_enable(struct sfc_adapter *sa, struct sfc_mae_counter *counter,
     993                 :            :                        efx_mae_actions_t *action_set_spec)
     994                 :            : {
     995                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
     996                 :            :         int rc;
     997                 :            : 
     998         [ #  # ]:          0 :         if (counter == NULL)
     999                 :            :                 return 0;
    1000                 :            : 
    1001                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1002                 :            : 
    1003                 :            :         fw_rsrc = &counter->fw_rsrc;
    1004                 :            : 
    1005         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
    1006                 :            :                 SFC_ASSERT(fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID);
    1007                 :            : 
    1008                 :          0 :                 rc = sfc_mae_counter_fw_rsrc_enable(sa, counter);
    1009         [ #  # ]:          0 :                 if (rc != 0) {
    1010                 :          0 :                         sfc_err(sa, "failed to enable counter=%p: %s",
    1011                 :            :                                 counter, rte_strerror(rc));
    1012                 :          0 :                         return rc;
    1013                 :            :                 }
    1014                 :            :         }
    1015                 :            : 
    1016         [ #  # ]:          0 :         if (action_set_spec != NULL) {
    1017                 :          0 :                 rc = efx_mae_action_set_fill_in_counter_id(
    1018                 :          0 :                                         action_set_spec, &fw_rsrc->counter_id);
    1019         [ #  # ]:          0 :                 if (rc != 0) {
    1020         [ #  # ]:          0 :                         if (fw_rsrc->refcnt == 0) {
    1021                 :          0 :                                 (void)sfc_mae_counter_fw_rsrc_disable(sa, counter);
    1022                 :          0 :                                 fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
    1023                 :            :                         }
    1024                 :            : 
    1025                 :          0 :                         sfc_err(sa, "cannot fill in counter ID: %s",
    1026                 :            :                                 strerror(rc));
    1027                 :          0 :                         return rc;
    1028                 :            :                 }
    1029                 :            :         }
    1030                 :            : 
    1031         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
    1032                 :          0 :                 sfc_dbg(sa, "enabled counter=%p: COUNTER_ID=0x%x-#%u",
    1033                 :            :                         counter, counter->type, fw_rsrc->counter_id.id);
    1034                 :            :         }
    1035                 :            : 
    1036                 :          0 :         ++(fw_rsrc->refcnt);
    1037                 :            : 
    1038                 :          0 :         return 0;
    1039                 :            : }
    1040                 :            : 
    1041                 :            : static void
    1042                 :          0 : sfc_mae_counter_disable(struct sfc_adapter *sa, struct sfc_mae_counter *counter)
    1043                 :            : {
    1044                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1045                 :            :         int rc;
    1046                 :            : 
    1047         [ #  # ]:          0 :         if (counter == NULL)
    1048                 :            :                 return;
    1049                 :            : 
    1050                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1051                 :            : 
    1052                 :            :         fw_rsrc = &counter->fw_rsrc;
    1053                 :            : 
    1054         [ #  # ]:          0 :         if (fw_rsrc->counter_id.id == EFX_MAE_RSRC_ID_INVALID ||
    1055         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
    1056                 :          0 :                 sfc_err(sa, "failed to disable counter=%p: already disabled; COUNTER_ID=0x%x-#%u, refcnt=%u",
    1057                 :            :                         counter, counter->type, fw_rsrc->counter_id.id, fw_rsrc->refcnt);
    1058                 :          0 :                 return;
    1059                 :            :         }
    1060                 :            : 
    1061         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
    1062                 :            :                 uint32_t counter_id = fw_rsrc->counter_id.id;
    1063                 :            : 
    1064                 :          0 :                 rc = sfc_mae_counter_fw_rsrc_disable(sa, counter);
    1065         [ #  # ]:          0 :                 if (rc == 0) {
    1066                 :          0 :                         sfc_dbg(sa, "disabled counter=%p with COUNTER_ID=0x%x-#%u",
    1067                 :            :                                 counter, counter->type, counter_id);
    1068                 :            :                 } else {
    1069                 :          0 :                         sfc_err(sa, "failed to disable counter=%p with COUNTER_ID=0x%x-#%u: %s",
    1070                 :            :                                 counter, counter->type, counter_id, strerror(rc));
    1071                 :            :                 }
    1072                 :            : 
    1073                 :          0 :                 fw_rsrc->counter_id.id = EFX_MAE_RSRC_ID_INVALID;
    1074                 :            :         }
    1075                 :            : 
    1076                 :          0 :         --(fw_rsrc->refcnt);
    1077                 :            : }
    1078                 :            : 
    1079                 :            : static struct sfc_mae_action_set *
    1080                 :          0 : sfc_mae_action_set_attach(struct sfc_adapter *sa,
    1081                 :            :                           const struct sfc_mae_aset_ctx *ctx)
    1082                 :            : {
    1083                 :            :         struct sfc_mae_action_set *action_set;
    1084                 :            :         struct sfc_mae *mae = &sa->mae;
    1085                 :            : 
    1086                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1087                 :            : 
    1088         [ #  # ]:          0 :         TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
    1089         [ #  # ]:          0 :                 if (action_set->encap_header == ctx->encap_header &&
    1090         [ #  # ]:          0 :                     action_set->dst_mac_addr == ctx->dst_mac &&
    1091         [ #  # ]:          0 :                     action_set->src_mac_addr == ctx->src_mac &&
    1092   [ #  #  #  # ]:          0 :                     action_set->counter == ctx->counter &&
    1093                 :          0 :                     efx_mae_action_set_specs_equal(action_set->spec,
    1094                 :          0 :                                                    ctx->spec)) {
    1095                 :          0 :                         sfc_dbg(sa, "attaching to action_set=%p", action_set);
    1096                 :          0 :                         ++(action_set->refcnt);
    1097                 :          0 :                         return action_set;
    1098                 :            :                 }
    1099                 :            :         }
    1100                 :            : 
    1101                 :            :         return NULL;
    1102                 :            : }
    1103                 :            : 
    1104                 :            : static int
    1105                 :          0 : sfc_mae_action_set_add(struct sfc_adapter *sa,
    1106                 :            :                        const struct sfc_mae_aset_ctx *ctx,
    1107                 :            :                        struct sfc_mae_action_set **action_setp)
    1108                 :            : {
    1109                 :            :         struct sfc_mae_action_set *action_set;
    1110                 :            :         struct sfc_mae *mae = &sa->mae;
    1111                 :            : 
    1112                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1113                 :            : 
    1114                 :          0 :         action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
    1115         [ #  # ]:          0 :         if (action_set == NULL) {
    1116                 :          0 :                 sfc_err(sa, "failed to alloc action set");
    1117                 :          0 :                 return ENOMEM;
    1118                 :            :         }
    1119                 :            : 
    1120                 :          0 :         action_set->refcnt = 1;
    1121                 :          0 :         action_set->spec = ctx->spec;
    1122                 :          0 :         action_set->encap_header = ctx->encap_header;
    1123                 :          0 :         action_set->dst_mac_addr = ctx->dst_mac;
    1124                 :          0 :         action_set->src_mac_addr = ctx->src_mac;
    1125                 :          0 :         action_set->counter = ctx->counter;
    1126                 :            : 
    1127                 :          0 :         action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
    1128                 :            : 
    1129                 :          0 :         TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
    1130                 :            : 
    1131                 :          0 :         *action_setp = action_set;
    1132                 :            : 
    1133                 :          0 :         sfc_dbg(sa, "added action_set=%p", action_set);
    1134                 :            : 
    1135                 :          0 :         return 0;
    1136                 :            : }
    1137                 :            : 
    1138                 :            : static void
    1139                 :          0 : sfc_mae_action_set_del(struct sfc_adapter *sa,
    1140                 :            :                        struct sfc_mae_action_set *action_set)
    1141                 :            : {
    1142                 :            :         struct sfc_mae *mae = &sa->mae;
    1143                 :            : 
    1144         [ #  # ]:          0 :         if (action_set == NULL)
    1145                 :            :                 return;
    1146                 :            : 
    1147                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1148                 :            :         SFC_ASSERT(action_set->refcnt != 0);
    1149                 :            : 
    1150                 :          0 :         --(action_set->refcnt);
    1151                 :            : 
    1152         [ #  # ]:          0 :         if (action_set->refcnt != 0)
    1153                 :            :                 return;
    1154                 :            : 
    1155         [ #  # ]:          0 :         if (action_set->fw_rsrc.aset_id.id != EFX_MAE_RSRC_ID_INVALID ||
    1156                 :            :             action_set->fw_rsrc.refcnt != 0) {
    1157                 :          0 :                 sfc_err(sa, "deleting action_set=%p abandons its FW resource: AS_ID=0x%08x, refcnt=%u",
    1158                 :            :                         action_set, action_set->fw_rsrc.aset_id.id,
    1159                 :            :                         action_set->fw_rsrc.refcnt);
    1160                 :            :         }
    1161                 :            : 
    1162                 :          0 :         efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
    1163                 :          0 :         sfc_mae_encap_header_del(sa, action_set->encap_header);
    1164                 :          0 :         sfc_mae_mac_addr_del(sa, action_set->dst_mac_addr);
    1165                 :          0 :         sfc_mae_mac_addr_del(sa, action_set->src_mac_addr);
    1166                 :          0 :         sfc_mae_counter_del(sa, action_set->counter);
    1167         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->action_sets, action_set, entries);
    1168                 :          0 :         sfc_dbg(sa, "deleted action_set=%p", action_set);
    1169                 :          0 :         rte_free(action_set);
    1170                 :            : }
    1171                 :            : 
    1172                 :            : static int
    1173                 :          0 : sfc_mae_action_set_enable(struct sfc_adapter *sa,
    1174                 :            :                           struct sfc_mae_action_set *action_set)
    1175                 :            : {
    1176                 :            :         struct sfc_mae_encap_header *encap_header;
    1177                 :            :         struct sfc_mae_mac_addr *dst_mac_addr;
    1178                 :            :         struct sfc_mae_mac_addr *src_mac_addr;
    1179                 :            :         struct sfc_mae_counter *counter;
    1180                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1181                 :            :         int rc;
    1182                 :            : 
    1183         [ #  # ]:          0 :         if (action_set == NULL)
    1184                 :            :                 return 0;
    1185                 :            : 
    1186                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1187                 :            : 
    1188                 :          0 :         encap_header = action_set->encap_header;
    1189                 :          0 :         dst_mac_addr = action_set->dst_mac_addr;
    1190                 :          0 :         src_mac_addr = action_set->src_mac_addr;
    1191                 :            :         fw_rsrc = &action_set->fw_rsrc;
    1192                 :          0 :         counter = action_set->counter;
    1193                 :            : 
    1194         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
    1195                 :            :                 SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
    1196                 :            :                 SFC_ASSERT(action_set->spec != NULL);
    1197                 :            : 
    1198                 :          0 :                 rc = sfc_mae_mac_addr_enable(sa, dst_mac_addr,
    1199                 :            :                                              SFC_MAE_MAC_ADDR_DST,
    1200                 :            :                                              action_set->spec);
    1201         [ #  # ]:          0 :                 if (rc != 0)
    1202                 :            :                         return rc;
    1203                 :            : 
    1204                 :          0 :                 rc = sfc_mae_mac_addr_enable(sa, src_mac_addr,
    1205                 :            :                                              SFC_MAE_MAC_ADDR_SRC,
    1206                 :            :                                              action_set->spec);
    1207         [ #  # ]:          0 :                 if (rc != 0) {
    1208                 :          0 :                         sfc_mae_mac_addr_disable(sa, dst_mac_addr);
    1209                 :          0 :                         return rc;
    1210                 :            :                 }
    1211                 :            : 
    1212                 :          0 :                 rc = sfc_mae_encap_header_enable(sa, encap_header,
    1213                 :            :                                                  action_set->spec);
    1214         [ #  # ]:          0 :                 if (rc != 0) {
    1215                 :          0 :                         sfc_mae_mac_addr_disable(sa, src_mac_addr);
    1216                 :          0 :                         sfc_mae_mac_addr_disable(sa, dst_mac_addr);
    1217                 :          0 :                         return rc;
    1218                 :            :                 }
    1219                 :            : 
    1220         [ #  # ]:          0 :                 if (counter != NULL) {
    1221                 :          0 :                         rc = sfc_mae_counter_start(sa);
    1222         [ #  # ]:          0 :                         if (rc != 0) {
    1223                 :          0 :                                 sfc_err(sa, "failed to start MAE counters support: %s",
    1224                 :            :                                         rte_strerror(rc));
    1225                 :          0 :                                 sfc_mae_encap_header_disable(sa, encap_header);
    1226                 :          0 :                                 sfc_mae_mac_addr_disable(sa, src_mac_addr);
    1227                 :          0 :                                 sfc_mae_mac_addr_disable(sa, dst_mac_addr);
    1228                 :          0 :                                 return rc;
    1229                 :            :                         }
    1230                 :            :                 }
    1231                 :            : 
    1232                 :          0 :                 rc = sfc_mae_counter_enable(sa, counter, action_set->spec);
    1233         [ #  # ]:          0 :                 if (rc != 0) {
    1234                 :          0 :                         sfc_mae_encap_header_disable(sa, encap_header);
    1235                 :          0 :                         sfc_mae_mac_addr_disable(sa, src_mac_addr);
    1236                 :          0 :                         sfc_mae_mac_addr_disable(sa, dst_mac_addr);
    1237                 :          0 :                         return rc;
    1238                 :            :                 }
    1239                 :            : 
    1240                 :          0 :                 rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
    1241                 :            :                                               &fw_rsrc->aset_id);
    1242         [ #  # ]:          0 :                 if (rc != 0) {
    1243                 :          0 :                         sfc_err(sa, "failed to enable action_set=%p: %s",
    1244                 :            :                                 action_set, strerror(rc));
    1245                 :            : 
    1246                 :          0 :                         sfc_mae_encap_header_disable(sa, encap_header);
    1247                 :          0 :                         sfc_mae_mac_addr_disable(sa, src_mac_addr);
    1248                 :          0 :                         sfc_mae_mac_addr_disable(sa, dst_mac_addr);
    1249                 :          0 :                         sfc_mae_counter_disable(sa, counter);
    1250                 :          0 :                         return rc;
    1251                 :            :                 }
    1252                 :            : 
    1253                 :          0 :                 sfc_dbg(sa, "enabled action_set=%p: AS_ID=0x%08x",
    1254                 :            :                         action_set, fw_rsrc->aset_id.id);
    1255                 :            :         }
    1256                 :            : 
    1257                 :          0 :         ++(fw_rsrc->refcnt);
    1258                 :            : 
    1259                 :          0 :         return 0;
    1260                 :            : }
    1261                 :            : 
    1262                 :            : static void
    1263                 :          0 : sfc_mae_action_set_disable(struct sfc_adapter *sa,
    1264                 :            :                            struct sfc_mae_action_set *action_set)
    1265                 :            : {
    1266                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1267                 :            :         int rc;
    1268                 :            : 
    1269         [ #  # ]:          0 :         if (action_set == NULL)
    1270                 :            :                 return;
    1271                 :            : 
    1272                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1273                 :            : 
    1274                 :            :         fw_rsrc = &action_set->fw_rsrc;
    1275                 :            : 
    1276         [ #  # ]:          0 :         if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
    1277         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
    1278                 :          0 :                 sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
    1279                 :            :                         action_set, fw_rsrc->aset_id.id, fw_rsrc->refcnt);
    1280                 :          0 :                 return;
    1281                 :            :         }
    1282                 :            : 
    1283         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
    1284                 :          0 :                 efx_mae_action_set_clear_fw_rsrc_ids(action_set->spec);
    1285                 :            : 
    1286                 :          0 :                 rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
    1287         [ #  # ]:          0 :                 if (rc == 0) {
    1288                 :          0 :                         sfc_dbg(sa, "disabled action_set=%p with AS_ID=0x%08x",
    1289                 :            :                                 action_set, fw_rsrc->aset_id.id);
    1290                 :            :                 } else {
    1291                 :          0 :                         sfc_err(sa, "failed to disable action_set=%p with AS_ID=0x%08x: %s",
    1292                 :            :                                 action_set, fw_rsrc->aset_id.id, strerror(rc));
    1293                 :            :                 }
    1294                 :          0 :                 fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
    1295                 :            : 
    1296                 :          0 :                 sfc_mae_encap_header_disable(sa, action_set->encap_header);
    1297                 :          0 :                 sfc_mae_mac_addr_disable(sa, action_set->src_mac_addr);
    1298                 :          0 :                 sfc_mae_mac_addr_disable(sa, action_set->dst_mac_addr);
    1299                 :          0 :                 sfc_mae_counter_disable(sa, action_set->counter);
    1300                 :            :         }
    1301                 :            : 
    1302                 :          0 :         --(fw_rsrc->refcnt);
    1303                 :            : }
    1304                 :            : 
    1305                 :            : static struct sfc_mae_action_set_list *
    1306                 :          0 : sfc_mae_action_set_list_attach(struct sfc_adapter *sa)
    1307                 :            : {
    1308                 :            :         struct sfc_mae_action_set_list *action_set_list;
    1309                 :            :         struct sfc_mae *mae = &sa->mae;
    1310                 :            : 
    1311                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1312                 :            : 
    1313         [ #  # ]:          0 :         TAILQ_FOREACH(action_set_list, &mae->action_set_lists, entries) {
    1314         [ #  # ]:          0 :                 if (action_set_list->nb_action_sets != mae->nb_bounce_asets)
    1315                 :          0 :                         continue;
    1316                 :            : 
    1317                 :          0 :                 if (memcmp(action_set_list->action_sets, mae->bounce_aset_ptrs,
    1318                 :            :                            sizeof(struct sfc_mae_action_set *) *
    1319         [ #  # ]:          0 :                            mae->nb_bounce_asets) == 0) {
    1320                 :          0 :                         sfc_dbg(sa, "attaching to action_set_list=%p",
    1321                 :            :                                 action_set_list);
    1322                 :          0 :                         ++(action_set_list->refcnt);
    1323                 :          0 :                         return action_set_list;
    1324                 :            :                 }
    1325                 :            :         }
    1326                 :            : 
    1327                 :            :         return NULL;
    1328                 :            : }
    1329                 :            : 
    1330                 :            : static int
    1331                 :          0 : sfc_mae_action_set_list_add(struct sfc_adapter *sa,
    1332                 :            :                             struct sfc_mae_action_set_list **action_set_listp)
    1333                 :            : {
    1334                 :            :         struct sfc_mae_action_set_list *action_set_list;
    1335                 :            :         struct sfc_mae *mae = &sa->mae;
    1336                 :            : 
    1337                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1338                 :            : 
    1339                 :          0 :         action_set_list = rte_zmalloc("sfc_mae_action_set_list",
    1340                 :            :                                       sizeof(*action_set_list), 0);
    1341         [ #  # ]:          0 :         if (action_set_list == NULL) {
    1342                 :          0 :                 sfc_err(sa, "failed to allocate action set list");
    1343                 :          0 :                 return ENOMEM;
    1344                 :            :         }
    1345                 :            : 
    1346                 :          0 :         action_set_list->refcnt = 1;
    1347                 :          0 :         action_set_list->nb_action_sets = mae->nb_bounce_asets;
    1348                 :          0 :         action_set_list->fw_rsrc.aset_list_id.id = EFX_MAE_RSRC_ID_INVALID;
    1349                 :            : 
    1350                 :          0 :         action_set_list->action_sets =
    1351                 :          0 :                 rte_calloc("sfc_mae_action_set_list_action_sets",
    1352                 :            :                            action_set_list->nb_action_sets,
    1353                 :            :                            sizeof(struct sfc_mae_action_set *), 0);
    1354         [ #  # ]:          0 :         if (action_set_list->action_sets == NULL) {
    1355                 :          0 :                 sfc_err(sa, "failed to allocate action set list");
    1356                 :          0 :                 rte_free(action_set_list);
    1357                 :          0 :                 return ENOMEM;
    1358                 :            :         }
    1359                 :            : 
    1360                 :          0 :         rte_memcpy(action_set_list->action_sets, mae->bounce_aset_ptrs,
    1361                 :            :                    sizeof(struct sfc_mae_action_set *) *
    1362         [ #  # ]:          0 :                    action_set_list->nb_action_sets);
    1363                 :            : 
    1364                 :          0 :         TAILQ_INSERT_TAIL(&mae->action_set_lists, action_set_list, entries);
    1365                 :            : 
    1366                 :          0 :         *action_set_listp = action_set_list;
    1367                 :            : 
    1368                 :          0 :         sfc_dbg(sa, "added action_set_list=%p", action_set_list);
    1369                 :            : 
    1370                 :          0 :         return 0;
    1371                 :            : }
    1372                 :            : 
    1373                 :            : static void
    1374                 :          0 : sfc_mae_action_set_list_del(struct sfc_adapter *sa,
    1375                 :            :                             struct sfc_mae_action_set_list *action_set_list)
    1376                 :            : {
    1377                 :            :         struct sfc_mae *mae = &sa->mae;
    1378                 :            :         unsigned int i;
    1379                 :            : 
    1380         [ #  # ]:          0 :         if (action_set_list == NULL)
    1381                 :            :                 return;
    1382                 :            : 
    1383                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1384                 :            :         SFC_ASSERT(action_set_list->refcnt != 0);
    1385                 :            : 
    1386                 :          0 :         --(action_set_list->refcnt);
    1387                 :            : 
    1388         [ #  # ]:          0 :         if (action_set_list->refcnt != 0)
    1389                 :            :                 return;
    1390                 :            : 
    1391                 :          0 :         if (action_set_list->fw_rsrc.aset_list_id.id !=
    1392         [ #  # ]:          0 :             EFX_MAE_RSRC_ID_INVALID || action_set_list->fw_rsrc.refcnt != 0) {
    1393                 :          0 :                 sfc_err(sa, "deleting action_set_list=%p abandons its FW resource: ASL_ID=0x%08x, refcnt=%u",
    1394                 :            :                         action_set_list,
    1395                 :            :                         action_set_list->fw_rsrc.aset_list_id.id,
    1396                 :            :                         action_set_list->fw_rsrc.refcnt);
    1397                 :            :         }
    1398                 :            : 
    1399         [ #  # ]:          0 :         for (i = 0; i < action_set_list->nb_action_sets; ++i)
    1400                 :          0 :                 sfc_mae_action_set_del(sa, action_set_list->action_sets[i]);
    1401                 :            : 
    1402         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->action_set_lists, action_set_list, entries);
    1403                 :          0 :         sfc_dbg(sa, "deleted action_set_list=%p", action_set_list);
    1404                 :            : 
    1405                 :          0 :         rte_free(action_set_list->action_sets);
    1406                 :          0 :         rte_free(action_set_list);
    1407                 :            : }
    1408                 :            : 
    1409                 :            : static int
    1410                 :          0 : sfc_mae_action_set_list_enable(struct sfc_adapter *sa,
    1411                 :            :                                struct sfc_mae_action_set_list *action_set_list)
    1412                 :            : {
    1413                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1414                 :            :         unsigned int i;
    1415                 :            :         unsigned int j;
    1416                 :            :         int rc;
    1417                 :            : 
    1418         [ #  # ]:          0 :         if (action_set_list == NULL)
    1419                 :            :                 return 0;
    1420                 :            : 
    1421                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1422                 :            : 
    1423                 :            :         fw_rsrc = &action_set_list->fw_rsrc;
    1424                 :            : 
    1425         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
    1426                 :            :                 struct sfc_mae *mae = &sa->mae;
    1427                 :            : 
    1428                 :            :                 SFC_ASSERT(fw_rsrc->aset_list_id.id == EFX_MAE_RSRC_ID_INVALID);
    1429                 :            : 
    1430         [ #  # ]:          0 :                 for (i = 0; i < action_set_list->nb_action_sets; ++i) {
    1431                 :            :                         const struct sfc_mae_fw_rsrc *as_fw_rsrc;
    1432                 :            : 
    1433                 :          0 :                         rc = sfc_mae_action_set_enable(sa,
    1434                 :          0 :                                                 action_set_list->action_sets[i]);
    1435         [ #  # ]:          0 :                         if (rc != 0)
    1436                 :          0 :                                 goto fail_action_set_enable;
    1437                 :            : 
    1438                 :          0 :                         as_fw_rsrc = &action_set_list->action_sets[i]->fw_rsrc;
    1439                 :          0 :                         mae->bounce_aset_ids[i].id = as_fw_rsrc->aset_id.id;
    1440                 :            :                 }
    1441                 :            : 
    1442                 :          0 :                 rc = efx_mae_action_set_list_alloc(sa->nic,
    1443                 :            :                                                 action_set_list->nb_action_sets,
    1444                 :          0 :                                                 mae->bounce_aset_ids,
    1445                 :            :                                                 &fw_rsrc->aset_list_id);
    1446         [ #  # ]:          0 :                 if (rc != 0) {
    1447                 :          0 :                         sfc_err(sa, "failed to enable action_set_list=%p: %s",
    1448                 :            :                                 action_set_list, strerror(rc));
    1449                 :          0 :                         goto fail_action_set_list_alloc;
    1450                 :            :                 }
    1451                 :            : 
    1452                 :          0 :                 sfc_dbg(sa, "enabled action_set_list=%p: ASL_ID=0x%08x",
    1453                 :            :                         action_set_list, fw_rsrc->aset_list_id.id);
    1454                 :            :         }
    1455                 :            : 
    1456                 :          0 :         ++(fw_rsrc->refcnt);
    1457                 :            : 
    1458                 :          0 :         return 0;
    1459                 :            : 
    1460                 :            : fail_action_set_list_alloc:
    1461                 :          0 : fail_action_set_enable:
    1462         [ #  # ]:          0 :         for (j = 0; j < i; ++j)
    1463                 :          0 :                 sfc_mae_action_set_disable(sa, action_set_list->action_sets[j]);
    1464                 :            : 
    1465                 :            :         return rc;
    1466                 :            : }
    1467                 :            : 
    1468                 :            : static void
    1469                 :          0 : sfc_mae_action_set_list_disable(struct sfc_adapter *sa,
    1470                 :            :                                 struct sfc_mae_action_set_list *action_set_list)
    1471                 :            : {
    1472                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1473                 :            :         int rc;
    1474                 :            : 
    1475         [ #  # ]:          0 :         if (action_set_list == NULL)
    1476                 :            :                 return;
    1477                 :            : 
    1478                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1479                 :            : 
    1480                 :            :         fw_rsrc = &action_set_list->fw_rsrc;
    1481                 :            : 
    1482         [ #  # ]:          0 :         if (fw_rsrc->aset_list_id.id == EFX_MAE_RSRC_ID_INVALID ||
    1483         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
    1484                 :          0 :                 sfc_err(sa, "failed to disable action_set_list=%p: already disabled; ASL_ID=0x%08x, refcnt=%u",
    1485                 :            :                         action_set_list, fw_rsrc->aset_list_id.id,
    1486                 :            :                         fw_rsrc->refcnt);
    1487                 :          0 :                 return;
    1488                 :            :         }
    1489                 :            : 
    1490         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
    1491                 :            :                 unsigned int i;
    1492                 :            : 
    1493                 :          0 :                 rc = efx_mae_action_set_list_free(sa->nic,
    1494                 :          0 :                                                   &fw_rsrc->aset_list_id);
    1495         [ #  # ]:          0 :                 if (rc == 0) {
    1496                 :          0 :                         sfc_dbg(sa, "disabled action_set_list=%p with ASL_ID=0x%08x",
    1497                 :            :                                 action_set_list, fw_rsrc->aset_list_id.id);
    1498                 :            :                 } else {
    1499                 :          0 :                         sfc_err(sa, "failed to disable action_set_list=%p with ASL_ID=0x%08x: %s",
    1500                 :            :                                 action_set_list, fw_rsrc->aset_list_id.id,
    1501                 :            :                                 strerror(rc));
    1502                 :            :                 }
    1503                 :          0 :                 fw_rsrc->aset_list_id.id = EFX_MAE_RSRC_ID_INVALID;
    1504                 :            : 
    1505         [ #  # ]:          0 :                 for (i = 0; i < action_set_list->nb_action_sets; ++i) {
    1506                 :          0 :                         sfc_mae_action_set_disable(sa,
    1507                 :          0 :                                         action_set_list->action_sets[i]);
    1508                 :            :                 }
    1509                 :            :         }
    1510                 :            : 
    1511                 :          0 :         --(fw_rsrc->refcnt);
    1512                 :            : }
    1513                 :            : 
    1514                 :            : struct sfc_mae_action_rule_ctx {
    1515                 :            :         struct sfc_mae_outer_rule       *outer_rule;
    1516                 :            :         /*
    1517                 :            :          * When action_set_list != NULL, action_set is NULL, and vice versa.
    1518                 :            :          */
    1519                 :            :         struct sfc_mae_action_set       *action_set;
    1520                 :            :         struct sfc_mae_action_set_list  *action_set_list;
    1521                 :            :         efx_mae_match_spec_t            *match_spec;
    1522                 :            :         uint32_t                        ct_mark;
    1523                 :            : };
    1524                 :            : 
    1525                 :            : static int
    1526                 :          0 : sfc_mae_action_rule_attach(struct sfc_adapter *sa,
    1527                 :            :                            struct sfc_mae_action_rule_ctx *ctx,
    1528                 :            :                            struct sfc_mae_action_rule **rulep,
    1529                 :            :                            struct rte_flow_error *error)
    1530                 :            : {
    1531                 :          0 :         uint32_t new_ct_mark = ctx->ct_mark;
    1532                 :            :         struct sfc_mae_action_rule *rule;
    1533                 :            :         int rc;
    1534                 :            : 
    1535                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1536                 :            : 
    1537                 :            :         SFC_ASSERT(ctx->ct_mark <= 1);
    1538                 :            : 
    1539                 :            :         /*
    1540                 :            :          * It is assumed that the caller of this helper has already properly
    1541                 :            :          * tailored ctx->match_spec to match on OR_ID / 0xffffffff (when
    1542                 :            :          * ctx->outer_rule refers to a currently active outer rule) or
    1543                 :            :          * on 0xffffffff / 0xffffffff, so that specs compare correctly.
    1544                 :            :          */
    1545         [ #  # ]:          0 :         TAILQ_FOREACH(rule, &sa->mae.action_rules, entries) {
    1546         [ #  # ]:          0 :                 if (rule->ct_mark == new_ct_mark)
    1547                 :          0 :                         ++new_ct_mark;
    1548                 :            : 
    1549         [ #  # ]:          0 :                 if (rule->outer_rule != ctx->outer_rule ||
    1550         [ #  # ]:          0 :                     rule->action_set != ctx->action_set ||
    1551         [ #  # ]:          0 :                     rule->action_set_list != ctx->action_set_list ||
    1552         [ #  # ]:          0 :                     !!rule->ct_mark != !!ctx->ct_mark)
    1553                 :          0 :                         continue;
    1554                 :            : 
    1555         [ #  # ]:          0 :                 if (ctx->ct_mark != 0) {
    1556                 :          0 :                         rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
    1557                 :            :                                                             rule->ct_mark);
    1558         [ #  # ]:          0 :                         if (rc != 0) {
    1559                 :          0 :                                 return rte_flow_error_set(error, EFAULT,
    1560                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1561                 :            :                                         NULL, "AR: failed to set CT mark for comparison");
    1562                 :            :                         }
    1563                 :            :                 }
    1564                 :            : 
    1565         [ #  # ]:          0 :                 if (efx_mae_match_specs_equal(rule->match_spec,
    1566                 :          0 :                                               ctx->match_spec)) {
    1567                 :          0 :                         sfc_dbg(sa, "attaching to action_rule=%p", rule);
    1568                 :          0 :                         ++(rule->refcnt);
    1569                 :          0 :                         *rulep = rule;
    1570                 :          0 :                         return 0;
    1571                 :            :                 }
    1572                 :            :         }
    1573                 :            : 
    1574         [ #  # ]:          0 :         if (ctx->ct_mark != 0) {
    1575         [ #  # ]:          0 :                 if (new_ct_mark == UINT32_MAX) {
    1576                 :          0 :                         return rte_flow_error_set(error, ERANGE,
    1577                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1578                 :            :                                         NULL, "AR: failed to allocate CT mark");
    1579                 :            :                 }
    1580                 :            : 
    1581                 :          0 :                 rc = efx_mae_match_spec_ct_mark_set(ctx->match_spec,
    1582                 :            :                                                     new_ct_mark);
    1583         [ #  # ]:          0 :                 if (rc != 0) {
    1584                 :          0 :                         return rte_flow_error_set(error, EFAULT,
    1585                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    1586                 :            :                                         NULL, "AR: failed to set CT mark");
    1587                 :            :                 }
    1588                 :            : 
    1589                 :          0 :                 ctx->ct_mark = new_ct_mark;
    1590                 :            :         }
    1591                 :            : 
    1592                 :            :         /*
    1593                 :            :          * No need to set RTE error, as this
    1594                 :            :          * code should be handled gracefully.
    1595                 :            :          */
    1596                 :            :         return -ENOENT;
    1597                 :            : }
    1598                 :            : 
    1599                 :            : static int
    1600                 :          0 : sfc_mae_action_rule_add(struct sfc_adapter *sa,
    1601                 :            :                         const struct sfc_mae_action_rule_ctx *ctx,
    1602                 :            :                         struct sfc_mae_action_rule **rulep)
    1603                 :            : {
    1604                 :            :         struct sfc_mae_action_rule *rule;
    1605                 :            :         struct sfc_mae *mae = &sa->mae;
    1606                 :            : 
    1607                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1608                 :            : 
    1609                 :          0 :         rule = rte_zmalloc("sfc_mae_action_rule", sizeof(*rule), 0);
    1610         [ #  # ]:          0 :         if (rule == NULL)
    1611                 :            :                 return ENOMEM;
    1612                 :            : 
    1613                 :          0 :         rule->refcnt = 1;
    1614                 :            : 
    1615                 :            :         /*
    1616                 :            :          * It is assumed that the caller invoked sfc_mae_action_rule_attach()
    1617                 :            :          * and got (-ENOENT) before getting here. That ensures a unique CT
    1618                 :            :          * mark value or, if no CT is involved at all, simply zero.
    1619                 :            :          *
    1620                 :            :          * It is also assumed that match on the mark (if non-zero)
    1621                 :            :          * is already set in the action rule match specification.
    1622                 :            :          */
    1623                 :          0 :         rule->ct_mark = ctx->ct_mark;
    1624                 :            : 
    1625                 :          0 :         rule->outer_rule = ctx->outer_rule;
    1626                 :          0 :         rule->action_set = ctx->action_set;
    1627                 :          0 :         rule->action_set_list = ctx->action_set_list;
    1628                 :          0 :         rule->match_spec = ctx->match_spec;
    1629                 :            : 
    1630                 :          0 :         rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
    1631                 :            : 
    1632                 :          0 :         TAILQ_INSERT_TAIL(&mae->action_rules, rule, entries);
    1633                 :            : 
    1634                 :          0 :         *rulep = rule;
    1635                 :            : 
    1636                 :          0 :         sfc_dbg(sa, "added action_rule=%p", rule);
    1637                 :            : 
    1638                 :          0 :         return 0;
    1639                 :            : }
    1640                 :            : 
    1641                 :            : static void
    1642                 :          0 : sfc_mae_action_rule_del(struct sfc_adapter *sa,
    1643                 :            :                         struct sfc_mae_action_rule *rule)
    1644                 :            : {
    1645                 :            :         struct sfc_mae *mae = &sa->mae;
    1646         [ #  # ]:          0 :         if (rule == NULL)
    1647                 :            :                 return;
    1648                 :            : 
    1649                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1650                 :            :         SFC_ASSERT(rule->refcnt != 0);
    1651                 :            : 
    1652                 :          0 :         --(rule->refcnt);
    1653                 :            : 
    1654         [ #  # ]:          0 :         if (rule->refcnt != 0)
    1655                 :            :                 return;
    1656                 :            : 
    1657         [ #  # ]:          0 :         if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
    1658                 :            :             rule->fw_rsrc.refcnt != 0) {
    1659                 :          0 :                 sfc_err(sa, "deleting action_rule=%p abandons its FW resource: AR_ID=0x%08x, refcnt=%u",
    1660                 :            :                         rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
    1661                 :            :         }
    1662                 :            : 
    1663                 :          0 :         efx_mae_match_spec_fini(sa->nic, rule->match_spec);
    1664                 :          0 :         sfc_mae_action_set_list_del(sa, rule->action_set_list);
    1665                 :          0 :         sfc_mae_action_set_del(sa, rule->action_set);
    1666                 :          0 :         sfc_mae_outer_rule_del(sa, rule->outer_rule);
    1667                 :            : 
    1668         [ #  # ]:          0 :         TAILQ_REMOVE(&mae->action_rules, rule, entries);
    1669                 :          0 :         sfc_dbg(sa, "deleted action_rule=%p", rule);
    1670                 :          0 :         rte_free(rule);
    1671                 :            : }
    1672                 :            : 
    1673                 :            : static int
    1674                 :          0 : sfc_mae_action_rule_enable(struct sfc_adapter *sa,
    1675                 :            :                            struct sfc_mae_action_rule *rule)
    1676                 :            : {
    1677                 :            :         const efx_mae_aset_list_id_t *asl_idp = NULL;
    1678                 :            :         const efx_mae_aset_id_t *as_idp = NULL;
    1679                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1680                 :            :         int rc;
    1681                 :            : 
    1682                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1683                 :            : 
    1684                 :            :         fw_rsrc = &rule->fw_rsrc;
    1685                 :            : 
    1686         [ #  # ]:          0 :         if (fw_rsrc->refcnt != 0)
    1687                 :          0 :                 goto success;
    1688                 :            : 
    1689                 :          0 :         rc = sfc_mae_outer_rule_enable(sa, rule->outer_rule, rule->match_spec);
    1690         [ #  # ]:          0 :         if (rc != 0)
    1691                 :          0 :                 goto fail_outer_rule_enable;
    1692                 :            : 
    1693                 :          0 :         rc = sfc_mae_action_set_enable(sa, rule->action_set);
    1694         [ #  # ]:          0 :         if (rc != 0)
    1695                 :          0 :                 goto fail_action_set_enable;
    1696                 :            : 
    1697                 :          0 :         rc = sfc_mae_action_set_list_enable(sa, rule->action_set_list);
    1698         [ #  # ]:          0 :         if (rc != 0)
    1699                 :          0 :                 goto fail_action_set_list_enable;
    1700                 :            : 
    1701         [ #  # ]:          0 :         if (rule->action_set_list != NULL)
    1702                 :          0 :                 asl_idp = &rule->action_set_list->fw_rsrc.aset_list_id;
    1703                 :            : 
    1704         [ #  # ]:          0 :         if (rule->action_set != NULL)
    1705                 :          0 :                 as_idp = &rule->action_set->fw_rsrc.aset_id;
    1706                 :            : 
    1707                 :          0 :         rc = efx_mae_action_rule_insert(sa->nic, rule->match_spec, asl_idp,
    1708                 :            :                                         as_idp, &fw_rsrc->rule_id);
    1709         [ #  # ]:          0 :         if (rc != 0) {
    1710                 :          0 :                 sfc_err(sa, "failed to enable action_rule=%p: %s",
    1711                 :            :                         rule, strerror(rc));
    1712                 :          0 :                 goto fail_action_rule_insert;
    1713                 :            :         }
    1714                 :            : 
    1715                 :          0 : success:
    1716         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 0) {
    1717                 :          0 :                 sfc_dbg(sa, "enabled action_rule=%p: AR_ID=0x%08x",
    1718                 :            :                         rule, fw_rsrc->rule_id.id);
    1719                 :            :         }
    1720                 :            : 
    1721                 :          0 :         ++(fw_rsrc->refcnt);
    1722                 :            : 
    1723                 :          0 :         return 0;
    1724                 :            : 
    1725                 :            : fail_action_rule_insert:
    1726                 :          0 :         sfc_mae_action_set_list_disable(sa, rule->action_set_list);
    1727                 :            : 
    1728                 :          0 : fail_action_set_list_enable:
    1729                 :          0 :         sfc_mae_action_set_disable(sa, rule->action_set);
    1730                 :            : 
    1731                 :          0 : fail_action_set_enable:
    1732                 :          0 :         sfc_mae_outer_rule_disable(sa, rule->outer_rule, rule->match_spec);
    1733                 :            : 
    1734                 :            : fail_outer_rule_enable:
    1735                 :            :         return rc;
    1736                 :            : }
    1737                 :            : static void
    1738                 :          0 : sfc_mae_action_rule_disable(struct sfc_adapter *sa,
    1739                 :            :                             struct sfc_mae_action_rule *rule)
    1740                 :            : {
    1741                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    1742                 :            :         int rc;
    1743                 :            : 
    1744                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    1745                 :            : 
    1746                 :            :         fw_rsrc = &rule->fw_rsrc;
    1747                 :            : 
    1748         [ #  # ]:          0 :         if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
    1749         [ #  # ]:          0 :             fw_rsrc->refcnt == 0) {
    1750                 :          0 :                 sfc_err(sa, "failed to disable action_rule=%p: already disabled; AR_ID=0x%08x, refcnt=%u",
    1751                 :            :                         rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
    1752                 :          0 :                 return;
    1753                 :            :         }
    1754                 :            : 
    1755         [ #  # ]:          0 :         if (fw_rsrc->refcnt == 1) {
    1756                 :          0 :                 rc = efx_mae_action_rule_remove(sa->nic, &fw_rsrc->rule_id);
    1757         [ #  # ]:          0 :                 if (rc == 0) {
    1758                 :          0 :                         sfc_dbg(sa, "disabled action_rule=%p with AR_ID=0x%08x",
    1759                 :            :                                 rule, fw_rsrc->rule_id.id);
    1760                 :            :                 } else {
    1761                 :          0 :                         sfc_err(sa, "failed to disable action_rule=%p with AR_ID=0x%08x: %s",
    1762                 :            :                                 rule, fw_rsrc->rule_id.id, strerror(rc));
    1763                 :            :                 }
    1764                 :            : 
    1765                 :          0 :                 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
    1766                 :            : 
    1767                 :          0 :                 sfc_mae_action_set_list_disable(sa, rule->action_set_list);
    1768                 :            : 
    1769                 :          0 :                 sfc_mae_action_set_disable(sa, rule->action_set);
    1770                 :            : 
    1771                 :          0 :                 sfc_mae_outer_rule_disable(sa, rule->outer_rule,
    1772                 :            :                                            rule->match_spec);
    1773                 :            :         }
    1774                 :            : 
    1775                 :          0 :         --(fw_rsrc->refcnt);
    1776                 :            : }
    1777                 :            : 
    1778                 :            : void
    1779                 :          0 : sfc_mae_flow_cleanup(struct sfc_adapter *sa,
    1780                 :            :                      struct rte_flow *flow)
    1781                 :            : {
    1782                 :            :         struct sfc_flow_spec_mae *spec_mae;
    1783                 :            : 
    1784         [ #  # ]:          0 :         if (flow == NULL)
    1785                 :            :                 return;
    1786                 :            : 
    1787                 :            :         spec_mae = &flow->spec.mae;
    1788                 :            : 
    1789         [ #  # ]:          0 :         if (spec_mae->ft_ctx != NULL) {
    1790         [ #  # ]:          0 :                 if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
    1791                 :          0 :                         spec_mae->ft_ctx->tunnel_rule_is_set = B_FALSE;
    1792                 :            : 
    1793                 :            :                 SFC_ASSERT(spec_mae->ft_ctx->refcnt != 0);
    1794                 :          0 :                 --(spec_mae->ft_ctx->refcnt);
    1795                 :            :         }
    1796                 :            : 
    1797                 :          0 :         sfc_mae_action_rule_del(sa, spec_mae->action_rule);
    1798                 :            : 
    1799                 :          0 :         sfc_mae_counter_del(sa, spec_mae->ct_counter);
    1800                 :            : }
    1801                 :            : 
    1802                 :            : static int
    1803                 :          0 : sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
    1804                 :            : {
    1805                 :            :         struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
    1806                 :          0 :         const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
    1807                 :          0 :         const efx_mae_field_id_t field_ids[] = {
    1808                 :            :                 EFX_MAE_FIELD_VLAN0_PROTO_BE,
    1809                 :            :                 EFX_MAE_FIELD_VLAN1_PROTO_BE,
    1810                 :            :         };
    1811                 :            :         const struct sfc_mae_ethertype *et;
    1812                 :            :         unsigned int i;
    1813                 :            :         int rc;
    1814                 :            : 
    1815                 :            :         /*
    1816                 :            :          * In accordance with RTE flow API convention, the innermost L2
    1817                 :            :          * item's "type" ("inner_type") is a L3 EtherType. If there is
    1818                 :            :          * no L3 item, it's 0x0000/0x0000.
    1819                 :            :          */
    1820                 :          0 :         et = &pdata->ethertypes[pdata->nb_vlan_tags];
    1821                 :          0 :         rc = efx_mae_match_spec_field_set(ctx->match_spec,
    1822                 :            :                                           fremap[EFX_MAE_FIELD_ETHER_TYPE_BE],
    1823                 :            :                                           sizeof(et->value),
    1824                 :          0 :                                           (const uint8_t *)&et->value,
    1825                 :            :                                           sizeof(et->mask),
    1826                 :          0 :                                           (const uint8_t *)&et->mask);
    1827         [ #  # ]:          0 :         if (rc != 0)
    1828                 :            :                 return rc;
    1829                 :            : 
    1830                 :            :         /*
    1831                 :            :          * sfc_mae_rule_parse_item_vlan() has already made sure
    1832                 :            :          * that pdata->nb_vlan_tags does not exceed this figure.
    1833                 :            :          */
    1834                 :            :         RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
    1835                 :            : 
    1836         [ #  # ]:          0 :         for (i = 0; i < pdata->nb_vlan_tags; ++i) {
    1837                 :            :                 et = &pdata->ethertypes[i];
    1838                 :            : 
    1839                 :          0 :                 rc = efx_mae_match_spec_field_set(ctx->match_spec,
    1840                 :          0 :                                                   fremap[field_ids[i]],
    1841                 :            :                                                   sizeof(et->value),
    1842                 :          0 :                                                   (const uint8_t *)&et->value,
    1843                 :            :                                                   sizeof(et->mask),
    1844                 :          0 :                                                   (const uint8_t *)&et->mask);
    1845         [ #  # ]:          0 :                 if (rc != 0)
    1846                 :          0 :                         return rc;
    1847                 :            :         }
    1848                 :            : 
    1849                 :            :         return 0;
    1850                 :            : }
    1851                 :            : 
    1852                 :            : static int
    1853                 :          0 : sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
    1854                 :            :                                   struct rte_flow_error *error)
    1855                 :            : {
    1856                 :          0 :         const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
    1857                 :            :         struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
    1858                 :          0 :         struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
    1859                 :          0 :         const rte_be16_t supported_tpids[] = {
    1860                 :            :                 /* VLAN standard TPID (always the first element) */
    1861                 :            :                 RTE_BE16(RTE_ETHER_TYPE_VLAN),
    1862                 :            : 
    1863                 :            :                 /* Double-tagging TPIDs */
    1864                 :            :                 RTE_BE16(RTE_ETHER_TYPE_QINQ),
    1865                 :            :                 RTE_BE16(RTE_ETHER_TYPE_QINQ1),
    1866                 :            :                 RTE_BE16(RTE_ETHER_TYPE_QINQ2),
    1867                 :            :                 RTE_BE16(RTE_ETHER_TYPE_QINQ3),
    1868                 :            :         };
    1869                 :          0 :         bool enforce_tag_presence[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {0};
    1870                 :            :         unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
    1871                 :            :         unsigned int ethertype_idx;
    1872                 :            :         const uint8_t *valuep;
    1873                 :            :         const uint8_t *maskp;
    1874                 :            :         int rc;
    1875                 :            : 
    1876         [ #  # ]:          0 :         if (pdata->innermost_ethertype_restriction.mask != 0 &&
    1877         [ #  # ]:          0 :             pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
    1878                 :            :                 /*
    1879                 :            :                  * If a single item VLAN is followed by a L3 item, value
    1880                 :            :                  * of "type" in item ETH can't be a double-tagging TPID.
    1881                 :            :                  */
    1882                 :            :                 nb_supported_tpids = 1;
    1883                 :            :         }
    1884                 :            : 
    1885                 :            :         /*
    1886                 :            :          * sfc_mae_rule_parse_item_vlan() has already made sure
    1887                 :            :          * that pdata->nb_vlan_tags does not exceed this figure.
    1888                 :            :          */
    1889                 :            :         RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
    1890                 :            : 
    1891                 :            :         for (ethertype_idx = 0;
    1892         [ #  # ]:          0 :              ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) {
    1893                 :          0 :                 rte_be16_t tpid_v = ethertypes[ethertype_idx].value;
    1894                 :          0 :                 rte_be16_t tpid_m = ethertypes[ethertype_idx].mask;
    1895                 :            :                 unsigned int tpid_idx;
    1896                 :            : 
    1897                 :            :                 /*
    1898                 :            :                  * This loop can have only two iterations. On the second one,
    1899                 :            :                  * drop outer tag presence enforcement bit because the inner
    1900                 :            :                  * tag presence automatically assumes that for the outer tag.
    1901                 :            :                  */
    1902                 :          0 :                 enforce_tag_presence[0] = B_FALSE;
    1903                 :            : 
    1904         [ #  # ]:          0 :                 if (tpid_m == RTE_BE16(0)) {
    1905         [ #  # ]:          0 :                         if (pdata->tci_masks[ethertype_idx] == RTE_BE16(0))
    1906                 :          0 :                                 enforce_tag_presence[ethertype_idx] = B_TRUE;
    1907                 :            : 
    1908                 :            :                         /* No match on this field, and no value check. */
    1909                 :            :                         nb_supported_tpids = 1;
    1910                 :          0 :                         continue;
    1911                 :            :                 }
    1912                 :            : 
    1913                 :            :                 /* Exact match is supported only. */
    1914         [ #  # ]:          0 :                 if (tpid_m != RTE_BE16(0xffff)) {
    1915         [ #  # ]:          0 :                         sfc_err(ctx->sa, "TPID mask must be 0x0 or 0xffff; got 0x%04x",
    1916                 :            :                                 rte_be_to_cpu_16(tpid_m));
    1917                 :            :                         rc = EINVAL;
    1918                 :          0 :                         goto fail;
    1919                 :            :                 }
    1920                 :            : 
    1921                 :          0 :                 for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1;
    1922         [ #  # ]:          0 :                      tpid_idx < nb_supported_tpids; ++tpid_idx) {
    1923         [ #  # ]:          0 :                         if (tpid_v == supported_tpids[tpid_idx])
    1924                 :            :                                 break;
    1925                 :            :                 }
    1926                 :            : 
    1927         [ #  # ]:          0 :                 if (tpid_idx == nb_supported_tpids) {
    1928         [ #  # ]:          0 :                         sfc_err(ctx->sa, "TPID 0x%04x is unsupported",
    1929                 :            :                                 rte_be_to_cpu_16(tpid_v));
    1930                 :            :                         rc = EINVAL;
    1931                 :          0 :                         goto fail;
    1932                 :            :                 }
    1933                 :            : 
    1934                 :            :                 nb_supported_tpids = 1;
    1935                 :            :         }
    1936                 :            : 
    1937         [ #  # ]:          0 :         if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) {
    1938                 :          0 :                 struct sfc_mae_ethertype *et = &ethertypes[ethertype_idx];
    1939                 :            :                 rte_be16_t enforced_et;
    1940                 :            : 
    1941                 :          0 :                 enforced_et = pdata->innermost_ethertype_restriction.value;
    1942                 :            : 
    1943         [ #  # ]:          0 :                 if (et->mask == 0) {
    1944                 :          0 :                         et->mask = RTE_BE16(0xffff);
    1945                 :          0 :                         et->value = enforced_et;
    1946         [ #  # ]:          0 :                 } else if (et->mask != RTE_BE16(0xffff) ||
    1947         [ #  # ]:          0 :                            et->value != enforced_et) {
    1948   [ #  #  #  #  :          0 :                         sfc_err(ctx->sa, "L3 EtherType must be 0x0/0x0 or 0x%04x/0xffff; got 0x%04x/0x%04x",
                   #  # ]
    1949                 :            :                                 rte_be_to_cpu_16(enforced_et),
    1950                 :            :                                 rte_be_to_cpu_16(et->value),
    1951                 :            :                                 rte_be_to_cpu_16(et->mask));
    1952                 :            :                         rc = EINVAL;
    1953                 :          0 :                         goto fail;
    1954                 :            :                 }
    1955                 :            :         }
    1956                 :            : 
    1957                 :            :         /*
    1958                 :            :          * Now, when the number of VLAN tags is known, set fields
    1959                 :            :          * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first
    1960                 :            :          * one is either a valid L3 EtherType (or 0x0000/0x0000),
    1961                 :            :          * and the last two are valid TPIDs (or 0x0000/0x0000).
    1962                 :            :          */
    1963                 :          0 :         rc = sfc_mae_set_ethertypes(ctx);
    1964         [ #  # ]:          0 :         if (rc != 0)
    1965                 :          0 :                 goto fail;
    1966                 :            : 
    1967         [ #  # ]:          0 :         if (pdata->l3_next_proto_restriction_mask == 0xff) {
    1968         [ #  # ]:          0 :                 if (pdata->l3_next_proto_mask == 0) {
    1969                 :          0 :                         pdata->l3_next_proto_mask = 0xff;
    1970                 :          0 :                         pdata->l3_next_proto_value =
    1971                 :          0 :                                 pdata->l3_next_proto_restriction_value;
    1972         [ #  # ]:          0 :                 } else if (pdata->l3_next_proto_mask != 0xff ||
    1973                 :          0 :                            pdata->l3_next_proto_value !=
    1974         [ #  # ]:          0 :                            pdata->l3_next_proto_restriction_value) {
    1975                 :          0 :                         sfc_err(ctx->sa, "L3 next protocol must be 0x0/0x0 or 0x%02x/0xff; got 0x%02x/0x%02x",
    1976                 :            :                                 pdata->l3_next_proto_restriction_value,
    1977                 :            :                                 pdata->l3_next_proto_value,
    1978                 :            :                                 pdata->l3_next_proto_mask);
    1979                 :            :                         rc = EINVAL;
    1980                 :          0 :                         goto fail;
    1981                 :            :                 }
    1982                 :            :         }
    1983                 :            : 
    1984   [ #  #  #  # ]:          0 :         if (enforce_tag_presence[0] || pdata->has_ovlan_mask) {
    1985                 :          0 :                 rc = efx_mae_match_spec_bit_set(ctx->match_spec,
    1986                 :            :                                                 fremap[EFX_MAE_FIELD_HAS_OVLAN],
    1987         [ #  # ]:          0 :                                                 enforce_tag_presence[0] ||
    1988         [ #  # ]:          0 :                                                 pdata->has_ovlan_value);
    1989         [ #  # ]:          0 :                 if (rc != 0)
    1990                 :          0 :                         goto fail;
    1991                 :            :         }
    1992                 :            : 
    1993   [ #  #  #  # ]:          0 :         if (enforce_tag_presence[1] || pdata->has_ivlan_mask) {
    1994                 :          0 :                 rc = efx_mae_match_spec_bit_set(ctx->match_spec,
    1995                 :            :                                                 fremap[EFX_MAE_FIELD_HAS_IVLAN],
    1996         [ #  # ]:          0 :                                                 enforce_tag_presence[1] ||
    1997         [ #  # ]:          0 :                                                 pdata->has_ivlan_value);
    1998         [ #  # ]:          0 :                 if (rc != 0)
    1999                 :          0 :                         goto fail;
    2000                 :            :         }
    2001                 :            : 
    2002                 :          0 :         valuep = (const uint8_t *)&pdata->l3_next_proto_value;
    2003                 :          0 :         maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
    2004                 :          0 :         rc = efx_mae_match_spec_field_set(ctx->match_spec,
    2005                 :            :                                           fremap[EFX_MAE_FIELD_IP_PROTO],
    2006                 :            :                                           sizeof(pdata->l3_next_proto_value),
    2007                 :            :                                           valuep,
    2008                 :            :                                           sizeof(pdata->l3_next_proto_mask),
    2009                 :            :                                           maskp);
    2010         [ #  # ]:          0 :         if (rc != 0)
    2011                 :          0 :                 goto fail;
    2012                 :            : 
    2013         [ #  # ]:          0 :         if (pdata->l3_frag_ofst_mask != 0) {
    2014                 :            :                 const rte_be16_t hdr_mask = RTE_BE16(RTE_IPV4_HDR_OFFSET_MASK);
    2015                 :            :                 rte_be16_t value;
    2016                 :            :                 rte_be16_t last;
    2017                 :            :                 boolean_t first_frag;
    2018                 :            :                 boolean_t is_ip_frag;
    2019                 :            :                 boolean_t any_frag;
    2020                 :            : 
    2021         [ #  # ]:          0 :                 if (pdata->l3_frag_ofst_mask & RTE_BE16(RTE_IPV4_HDR_DF_FLAG)) {
    2022                 :          0 :                         sfc_err(ctx->sa, "Don't fragment flag is not supported.");
    2023                 :            :                         rc = ENOTSUP;
    2024                 :          0 :                         goto fail;
    2025                 :            :                 }
    2026                 :            : 
    2027         [ #  # ]:          0 :                 if ((pdata->l3_frag_ofst_mask & hdr_mask) != hdr_mask) {
    2028                 :          0 :                         sfc_err(ctx->sa, "Invalid value for fragment offset mask.");
    2029                 :            :                         rc = EINVAL;
    2030                 :          0 :                         goto fail;
    2031                 :            :                 }
    2032                 :            : 
    2033                 :          0 :                 value = pdata->l3_frag_ofst_mask & pdata->l3_frag_ofst_value;
    2034                 :          0 :                 last = pdata->l3_frag_ofst_mask & pdata->l3_frag_ofst_last;
    2035                 :            : 
    2036                 :            :                 /*
    2037                 :            :                  *  value:  last:       matches:
    2038                 :            :                  *  0       0           Non-fragmented packet
    2039                 :            :                  *  1       0x1fff      Non-first fragment
    2040                 :            :                  *  1       0x1fff+MF   Any fragment
    2041                 :            :                  *  MF      0           First fragment
    2042                 :            :                  */
    2043         [ #  # ]:          0 :                 if (last == 0 &&
    2044         [ #  # ]:          0 :                     (pdata->l3_frag_ofst_value & hdr_mask) != 0) {
    2045                 :          0 :                         sfc_err(ctx->sa,
    2046                 :            :                                 "Exact matching is prohibited for non-zero offsets, but ranges are allowed.");
    2047                 :            :                         rc = EINVAL;
    2048                 :          0 :                         goto fail;
    2049                 :            :                 }
    2050                 :            : 
    2051         [ #  # ]:          0 :                 if (value == 0 && last == 0) {
    2052                 :            :                         is_ip_frag = false;
    2053                 :            :                         any_frag = true;
    2054   [ #  #  #  # ]:          0 :                 } else if (value == RTE_BE16(1) && (last & hdr_mask) == hdr_mask) {
    2055         [ #  # ]:          0 :                         if (last & RTE_BE16(RTE_IPV4_HDR_MF_FLAG)) {
    2056                 :            :                                 is_ip_frag = true;
    2057                 :            :                                 any_frag = true;
    2058                 :            :                         } else {
    2059                 :            :                                 is_ip_frag = true;
    2060                 :            :                                 any_frag = false;
    2061                 :            :                                 first_frag = false;
    2062                 :            :                         }
    2063         [ #  # ]:          0 :                 } else if (value == RTE_BE16(RTE_IPV4_HDR_MF_FLAG) && last == 0) {
    2064                 :            :                         is_ip_frag = true;
    2065                 :            :                         any_frag = false;
    2066                 :            :                         first_frag = true;
    2067                 :            :                 } else {
    2068                 :          0 :                         sfc_err(ctx->sa, "Invalid value for fragment offset.");
    2069                 :            :                         rc = EINVAL;
    2070                 :          0 :                         goto fail;
    2071                 :            :                 }
    2072                 :            : 
    2073                 :          0 :                 rc = efx_mae_match_spec_bit_set(ctx->match_spec,
    2074                 :            :                                                 fremap[EFX_MAE_FIELD_IS_IP_FRAG], is_ip_frag);
    2075         [ #  # ]:          0 :                 if (rc != 0)
    2076                 :          0 :                         goto fail;
    2077                 :            : 
    2078         [ #  # ]:          0 :                 if (!any_frag) {
    2079                 :          0 :                         rc = efx_mae_match_spec_bit_set(ctx->match_spec,
    2080                 :            :                                                         fremap[EFX_MAE_FIELD_IP_FIRST_FRAG],
    2081                 :            :                                                         first_frag);
    2082         [ #  # ]:          0 :                         if (rc != 0)
    2083                 :          0 :                                 goto fail;
    2084                 :            :                 }
    2085                 :            :         }
    2086                 :            : 
    2087                 :            :         return 0;
    2088                 :            : 
    2089                 :          0 : fail:
    2090                 :          0 :         return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    2091                 :            :                                   "Failed to process pattern data");
    2092                 :            : }
    2093                 :            : 
    2094                 :            : static int
    2095                 :          0 : sfc_mae_rule_parse_item_mark(const struct rte_flow_item *item,
    2096                 :            :                              struct sfc_flow_parse_ctx *ctx,
    2097                 :            :                              struct rte_flow_error *error)
    2098                 :            : {
    2099                 :          0 :         const struct rte_flow_item_mark *spec = item->spec;
    2100                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2101                 :          0 :         struct sfc_ft_ctx *ft_ctx = ctx_mae->ft_ctx;
    2102                 :            : 
    2103         [ #  # ]:          0 :         if (spec == NULL) {
    2104                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2105                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2106                 :            :                                 "NULL spec in item MARK");
    2107                 :            :         }
    2108                 :            : 
    2109                 :            :         /*
    2110                 :            :          * This item is used in tunnel offload support only.
    2111                 :            :          * It must go before any network header items. This
    2112                 :            :          * way, sfc_mae_rule_preparse_item_mark() must have
    2113                 :            :          * already parsed it. Only one item MARK is allowed.
    2114                 :            :          */
    2115         [ #  # ]:          0 :         if (ctx_mae->ft_rule_type != SFC_FT_RULE_SWITCH ||
    2116         [ #  # ]:          0 :             spec->id != (uint32_t)SFC_FT_CTX_ID_TO_FLOW_MARK(ft_ctx->id)) {
    2117                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2118                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM,
    2119                 :            :                                           item, "invalid item MARK");
    2120                 :            :         }
    2121                 :            : 
    2122                 :            :         return 0;
    2123                 :            : }
    2124                 :            : 
    2125                 :            : static int
    2126                 :          0 : sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
    2127                 :            :                                 struct sfc_flow_parse_ctx *ctx,
    2128                 :            :                                 struct rte_flow_error *error)
    2129                 :            : {
    2130                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2131                 :          0 :         const struct rte_flow_item_port_id supp_mask = {
    2132                 :            :                 .id = 0xffffffff,
    2133                 :            :         };
    2134                 :            :         const void *def_mask = &rte_flow_item_port_id_mask;
    2135                 :          0 :         const struct rte_flow_item_port_id *spec = NULL;
    2136                 :          0 :         const struct rte_flow_item_port_id *mask = NULL;
    2137                 :            :         efx_mport_sel_t mport_sel;
    2138                 :            :         unsigned int type_mask;
    2139                 :            :         int rc;
    2140                 :            : 
    2141         [ #  # ]:          0 :         if (ctx_mae->match_mport_set) {
    2142                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2143                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2144                 :            :                                 "Can't handle multiple traffic source items");
    2145                 :            :         }
    2146                 :            : 
    2147                 :          0 :         rc = sfc_flow_parse_init(item,
    2148                 :            :                                  (const void **)&spec, (const void **)&mask,
    2149                 :            :                                  (const void *)&supp_mask, def_mask,
    2150                 :            :                                  sizeof(struct rte_flow_item_port_id), error);
    2151         [ #  # ]:          0 :         if (rc != 0)
    2152                 :            :                 return rc;
    2153                 :            : 
    2154         [ #  # ]:          0 :         if (mask->id != supp_mask.id) {
    2155                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2156                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2157                 :            :                                 "Bad mask in the PORT_ID pattern item");
    2158                 :            :         }
    2159                 :            : 
    2160                 :            :         /* If "spec" is not set, could be any port ID */
    2161         [ #  # ]:          0 :         if (spec == NULL)
    2162                 :            :                 return 0;
    2163                 :            : 
    2164         [ #  # ]:          0 :         if (spec->id > UINT16_MAX) {
    2165                 :          0 :                 return rte_flow_error_set(error, EOVERFLOW,
    2166                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2167                 :            :                                           "The port ID is too large");
    2168                 :            :         }
    2169                 :            : 
    2170                 :            :         type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
    2171                 :            : 
    2172                 :          0 :         rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
    2173                 :            :                                              spec->id, type_mask, &mport_sel);
    2174         [ #  # ]:          0 :         if (rc != 0) {
    2175                 :          0 :                 return rte_flow_error_set(error, rc,
    2176                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2177                 :            :                                 "Can't get m-port for the given ethdev");
    2178                 :            :         }
    2179                 :            : 
    2180                 :          0 :         rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
    2181                 :            :                                           &mport_sel, NULL);
    2182         [ #  # ]:          0 :         if (rc != 0) {
    2183                 :          0 :                 return rte_flow_error_set(error, rc,
    2184                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2185                 :            :                                 "Failed to set MPORT for the port ID");
    2186                 :            :         }
    2187                 :            : 
    2188                 :          0 :         ctx_mae->match_mport_set = B_TRUE;
    2189                 :            : 
    2190                 :          0 :         return 0;
    2191                 :            : }
    2192                 :            : 
    2193                 :            : static int
    2194                 :          0 : sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
    2195                 :            :                                      struct sfc_flow_parse_ctx *ctx,
    2196                 :            :                                      struct rte_flow_error *error)
    2197                 :            : {
    2198                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2199                 :          0 :         const struct rte_flow_item_ethdev supp_mask = {
    2200                 :            :                 .port_id = 0xffff,
    2201                 :            :         };
    2202                 :            :         const void *def_mask = &rte_flow_item_ethdev_mask;
    2203                 :          0 :         const struct rte_flow_item_ethdev *spec = NULL;
    2204                 :          0 :         const struct rte_flow_item_ethdev *mask = NULL;
    2205                 :            :         efx_mport_sel_t mport_sel;
    2206                 :            :         unsigned int type_mask;
    2207                 :            :         int rc;
    2208                 :            : 
    2209         [ #  # ]:          0 :         if (ctx_mae->match_mport_set) {
    2210                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2211                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2212                 :            :                                 "Can't handle multiple traffic source items");
    2213                 :            :         }
    2214                 :            : 
    2215                 :          0 :         rc = sfc_flow_parse_init(item,
    2216                 :            :                                  (const void **)&spec, (const void **)&mask,
    2217                 :            :                                  (const void *)&supp_mask, def_mask,
    2218                 :            :                                  sizeof(struct rte_flow_item_ethdev), error);
    2219         [ #  # ]:          0 :         if (rc != 0)
    2220                 :            :                 return rc;
    2221                 :            : 
    2222         [ #  # ]:          0 :         if (mask->port_id != supp_mask.port_id) {
    2223                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2224                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2225                 :            :                                 "Bad mask in the ethdev-based pattern item");
    2226                 :            :         }
    2227                 :            : 
    2228                 :            :         /* If "spec" is not set, could be any port ID */
    2229         [ #  # ]:          0 :         if (spec == NULL)
    2230                 :            :                 return 0;
    2231                 :            : 
    2232      [ #  #  # ]:          0 :         switch (item->type) {
    2233                 :          0 :         case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
    2234                 :            :                 type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
    2235                 :            : 
    2236                 :          0 :                 rc = sfc_mae_switch_get_ethdev_mport(
    2237                 :          0 :                                 ctx_mae->sa->mae.switch_domain_id,
    2238                 :          0 :                                 spec->port_id, type_mask, &mport_sel);
    2239         [ #  # ]:          0 :                 if (rc != 0) {
    2240                 :          0 :                         return rte_flow_error_set(error, rc,
    2241                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2242                 :            :                                         "Can't get m-port for the given ethdev");
    2243                 :            :                 }
    2244                 :            :                 break;
    2245                 :          0 :         case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
    2246                 :          0 :                 rc = sfc_mae_switch_get_entity_mport(
    2247                 :          0 :                                 ctx_mae->sa->mae.switch_domain_id,
    2248                 :          0 :                                 spec->port_id, &mport_sel);
    2249         [ #  # ]:          0 :                 if (rc != 0) {
    2250                 :          0 :                         return rte_flow_error_set(error, rc,
    2251                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2252                 :            :                                         "Can't get m-port for the given ethdev");
    2253                 :            :                 }
    2254                 :            :                 break;
    2255                 :          0 :         default:
    2256                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2257                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2258                 :            :                                 "Unsupported ethdev-based flow item");
    2259                 :            :         }
    2260                 :            : 
    2261                 :          0 :         rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
    2262                 :            :                                           &mport_sel, NULL);
    2263         [ #  # ]:          0 :         if (rc != 0) {
    2264                 :          0 :                 return rte_flow_error_set(error, rc,
    2265                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2266                 :            :                                 "Failed to set MPORT for the port ID");
    2267                 :            :         }
    2268                 :            : 
    2269                 :          0 :         ctx_mae->match_mport_set = B_TRUE;
    2270                 :            : 
    2271                 :          0 :         return 0;
    2272                 :            : }
    2273                 :            : 
    2274                 :            : /*
    2275                 :            :  * Having this field ID in a field locator means that this
    2276                 :            :  * locator cannot be used to actually set the field at the
    2277                 :            :  * time when the corresponding item gets encountered. Such
    2278                 :            :  * fields get stashed in the parsing context instead. This
    2279                 :            :  * is required to resolve dependencies between the stashed
    2280                 :            :  * fields. See sfc_mae_rule_process_pattern_data().
    2281                 :            :  */
    2282                 :            : #define SFC_MAE_FIELD_HANDLING_DEFERRED EFX_MAE_FIELD_NIDS
    2283                 :            : 
    2284                 :            : struct sfc_mae_field_locator {
    2285                 :            :         efx_mae_field_id_t              field_id;
    2286                 :            :         size_t                          size;
    2287                 :            :         /* Field offset in the corresponding rte_flow_item_ struct */
    2288                 :            :         size_t                          ofst;
    2289                 :            : 
    2290                 :            :         uint8_t                         ct_key_field;
    2291                 :            : };
    2292                 :            : 
    2293                 :            : static void
    2294                 :          0 : sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
    2295                 :            :                              unsigned int nb_field_locators, void *mask_ptr,
    2296                 :            :                              size_t mask_size)
    2297                 :            : {
    2298                 :            :         unsigned int i;
    2299                 :            : 
    2300                 :            :         memset(mask_ptr, 0, mask_size);
    2301                 :            : 
    2302         [ #  # ]:          0 :         for (i = 0; i < nb_field_locators; ++i) {
    2303                 :          0 :                 const struct sfc_mae_field_locator *fl = &field_locators[i];
    2304                 :            : 
    2305                 :            :                 SFC_ASSERT(fl->ofst + fl->size <= mask_size);
    2306                 :          0 :                 memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size);
    2307                 :            :         }
    2308                 :          0 : }
    2309                 :            : 
    2310                 :            : static int
    2311                 :          0 : sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
    2312                 :            :                    unsigned int nb_field_locators, const uint8_t *spec,
    2313                 :            :                    const uint8_t *mask, struct sfc_mae_parse_ctx *ctx,
    2314                 :            :                    struct rte_flow_error *error)
    2315                 :            : {
    2316                 :          0 :         const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
    2317                 :            :         unsigned int i;
    2318                 :            :         int rc = 0;
    2319                 :            : 
    2320         [ #  # ]:          0 :         for (i = 0; i < nb_field_locators; ++i) {
    2321                 :          0 :                 const struct sfc_mae_field_locator *fl = &field_locators[i];
    2322                 :            : 
    2323         [ #  # ]:          0 :                 if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED)
    2324                 :          0 :                         continue;
    2325                 :            : 
    2326                 :          0 :                 rc = efx_mae_match_spec_field_set(ctx->match_spec,
    2327                 :          0 :                                                   fremap[fl->field_id],
    2328                 :            :                                                   fl->size, spec + fl->ofst,
    2329                 :          0 :                                                   fl->size, mask + fl->ofst);
    2330         [ #  # ]:          0 :                 if (rc != 0)
    2331                 :            :                         break;
    2332                 :            :         }
    2333                 :            : 
    2334         [ #  # ]:          0 :         if (rc != 0) {
    2335                 :          0 :                 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
    2336                 :            :                                 NULL, "Failed to process item fields");
    2337                 :            :         }
    2338                 :            : 
    2339                 :          0 :         return rc;
    2340                 :            : }
    2341                 :            : 
    2342                 :            : static const struct sfc_mae_field_locator flocs_eth[] = {
    2343                 :            :         {
    2344                 :            :                 /*
    2345                 :            :                  * This locator is used only for building supported fields mask.
    2346                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2347                 :            :                  */
    2348                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2349                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, hdr.ether_type),
    2350                 :            :                 offsetof(struct rte_flow_item_eth, hdr.ether_type),
    2351                 :            :         },
    2352                 :            :         {
    2353                 :            :                 EFX_MAE_FIELD_ETH_DADDR_BE,
    2354                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, hdr.dst_addr),
    2355                 :            :                 offsetof(struct rte_flow_item_eth, hdr.dst_addr),
    2356                 :            :         },
    2357                 :            :         {
    2358                 :            :                 EFX_MAE_FIELD_ETH_SADDR_BE,
    2359                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, hdr.src_addr),
    2360                 :            :                 offsetof(struct rte_flow_item_eth, hdr.src_addr),
    2361                 :            :         },
    2362                 :            : };
    2363                 :            : 
    2364                 :            : static int
    2365                 :          0 : sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
    2366                 :            :                             struct sfc_flow_parse_ctx *ctx,
    2367                 :            :                             struct rte_flow_error *error)
    2368                 :            : {
    2369                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2370                 :            :         struct rte_flow_item_eth override_mask;
    2371                 :            :         struct rte_flow_item_eth supp_mask;
    2372                 :          0 :         const uint8_t *spec = NULL;
    2373                 :          0 :         const uint8_t *mask = NULL;
    2374                 :            :         int rc;
    2375                 :            : 
    2376                 :          0 :         sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
    2377                 :            :                                      &supp_mask, sizeof(supp_mask));
    2378                 :          0 :         supp_mask.has_vlan = 1;
    2379                 :            : 
    2380                 :          0 :         rc = sfc_flow_parse_init(item,
    2381                 :            :                                  (const void **)&spec, (const void **)&mask,
    2382                 :            :                                  (const void *)&supp_mask,
    2383                 :            :                                  &rte_flow_item_eth_mask,
    2384                 :            :                                  sizeof(struct rte_flow_item_eth), error);
    2385         [ #  # ]:          0 :         if (rc != 0)
    2386                 :            :                 return rc;
    2387                 :            : 
    2388   [ #  #  #  # ]:          0 :         if (ctx_mae->ft_rule_type == SFC_FT_RULE_TUNNEL && mask != NULL) {
    2389                 :            :                 /*
    2390                 :            :                  * The HW/FW hasn't got support for match on MAC addresses in
    2391                 :            :                  * outer rules yet (this will change). Match on VLAN presence
    2392                 :            :                  * isn't supported either. Ignore these match criteria.
    2393                 :            :                  */
    2394                 :            :                 memcpy(&override_mask, mask, sizeof(override_mask));
    2395                 :            :                 memset(&override_mask.hdr.dst_addr, 0,
    2396                 :            :                        sizeof(override_mask.hdr.dst_addr));
    2397                 :            :                 memset(&override_mask.hdr.src_addr, 0,
    2398                 :            :                        sizeof(override_mask.hdr.src_addr));
    2399                 :          0 :                 override_mask.has_vlan = 0;
    2400                 :            : 
    2401                 :          0 :                 mask = (const uint8_t *)&override_mask;
    2402                 :            :         }
    2403                 :            : 
    2404         [ #  # ]:          0 :         if (spec != NULL) {
    2405                 :            :                 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2406                 :            :                 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
    2407                 :            :                 const struct rte_flow_item_eth *item_spec;
    2408                 :            :                 const struct rte_flow_item_eth *item_mask;
    2409                 :            : 
    2410                 :            :                 item_spec = (const struct rte_flow_item_eth *)spec;
    2411                 :          0 :                 item_mask = (const struct rte_flow_item_eth *)mask;
    2412                 :            : 
    2413                 :            :                 /*
    2414                 :            :                  * Remember various match criteria in the parsing context.
    2415                 :            :                  * sfc_mae_rule_process_pattern_data() will consider them
    2416                 :            :                  * altogether when the rest of the items have been parsed.
    2417                 :            :                  */
    2418                 :          0 :                 ethertypes[0].value = item_spec->hdr.ether_type;
    2419                 :          0 :                 ethertypes[0].mask = item_mask->hdr.ether_type;
    2420         [ #  # ]:          0 :                 if (item_mask->has_vlan) {
    2421                 :          0 :                         pdata->has_ovlan_mask = B_TRUE;
    2422         [ #  # ]:          0 :                         if (item_spec->has_vlan)
    2423                 :          0 :                                 pdata->has_ovlan_value = B_TRUE;
    2424                 :            :                 }
    2425                 :            :         } else {
    2426                 :            :                 /*
    2427                 :            :                  * The specification is empty. The overall pattern
    2428                 :            :                  * validity will be enforced at the end of parsing.
    2429                 :            :                  * See sfc_mae_rule_process_pattern_data().
    2430                 :            :                  */
    2431                 :            :                 return 0;
    2432                 :            :         }
    2433                 :            : 
    2434                 :          0 :         return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
    2435                 :            :                                   ctx_mae, error);
    2436                 :            : }
    2437                 :            : 
    2438                 :            : static const struct sfc_mae_field_locator flocs_vlan[] = {
    2439                 :            :         /* Outermost tag */
    2440                 :            :         {
    2441                 :            :                 EFX_MAE_FIELD_VLAN0_TCI_BE,
    2442                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, hdr.vlan_tci),
    2443                 :            :                 offsetof(struct rte_flow_item_vlan, hdr.vlan_tci),
    2444                 :            :         },
    2445                 :            :         {
    2446                 :            :                 /*
    2447                 :            :                  * This locator is used only for building supported fields mask.
    2448                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2449                 :            :                  */
    2450                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2451                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, hdr.eth_proto),
    2452                 :            :                 offsetof(struct rte_flow_item_vlan, hdr.eth_proto),
    2453                 :            :         },
    2454                 :            : 
    2455                 :            :         /* Innermost tag */
    2456                 :            :         {
    2457                 :            :                 EFX_MAE_FIELD_VLAN1_TCI_BE,
    2458                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, hdr.vlan_tci),
    2459                 :            :                 offsetof(struct rte_flow_item_vlan, hdr.vlan_tci),
    2460                 :            :         },
    2461                 :            :         {
    2462                 :            :                 /*
    2463                 :            :                  * This locator is used only for building supported fields mask.
    2464                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2465                 :            :                  */
    2466                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2467                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, hdr.eth_proto),
    2468                 :            :                 offsetof(struct rte_flow_item_vlan, hdr.eth_proto),
    2469                 :            :         },
    2470                 :            : };
    2471                 :            : 
    2472                 :            : static int
    2473                 :          0 : sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
    2474                 :            :                              struct sfc_flow_parse_ctx *ctx,
    2475                 :            :                              struct rte_flow_error *error)
    2476                 :            : {
    2477                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2478                 :            :         struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2479                 :          0 :         boolean_t *has_vlan_mp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
    2480                 :          0 :                 &pdata->has_ovlan_mask,
    2481                 :          0 :                 &pdata->has_ivlan_mask,
    2482                 :            :         };
    2483                 :          0 :         boolean_t *has_vlan_vp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
    2484                 :          0 :                 &pdata->has_ovlan_value,
    2485                 :          0 :                 &pdata->has_ivlan_value,
    2486                 :            :         };
    2487                 :            :         boolean_t *cur_tag_presence_bit_mp;
    2488                 :            :         boolean_t *cur_tag_presence_bit_vp;
    2489                 :            :         const struct sfc_mae_field_locator *flocs;
    2490                 :            :         struct rte_flow_item_vlan supp_mask;
    2491                 :          0 :         const uint8_t *spec = NULL;
    2492                 :          0 :         const uint8_t *mask = NULL;
    2493                 :            :         unsigned int nb_flocs;
    2494                 :            :         int rc;
    2495                 :            : 
    2496                 :            :         RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
    2497                 :            : 
    2498         [ #  # ]:          0 :         if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
    2499                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    2500                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2501                 :            :                                 "Can't match that many VLAN tags");
    2502                 :            :         }
    2503                 :            : 
    2504                 :          0 :         cur_tag_presence_bit_mp = has_vlan_mp_by_nb_tags[pdata->nb_vlan_tags];
    2505                 :          0 :         cur_tag_presence_bit_vp = has_vlan_vp_by_nb_tags[pdata->nb_vlan_tags];
    2506                 :            : 
    2507         [ #  # ]:          0 :         if (*cur_tag_presence_bit_mp == B_TRUE &&
    2508         [ #  # ]:          0 :             *cur_tag_presence_bit_vp == B_FALSE) {
    2509                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2510                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    2511                 :            :                                 "The previous item enforces no (more) VLAN, "
    2512                 :            :                                 "so the current item (VLAN) must not exist");
    2513                 :            :         }
    2514                 :            : 
    2515                 :            :         nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS;
    2516                 :          0 :         flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs;
    2517                 :            : 
    2518                 :          0 :         sfc_mae_item_build_supp_mask(flocs, nb_flocs,
    2519                 :            :                                      &supp_mask, sizeof(supp_mask));
    2520                 :            :         /*
    2521                 :            :          * This only means that the field is supported by the driver and libefx.
    2522                 :            :          * Support on NIC level will be checked when all items have been parsed.
    2523                 :            :          */
    2524                 :          0 :         supp_mask.has_more_vlan = 1;
    2525                 :            : 
    2526                 :          0 :         rc = sfc_flow_parse_init(item,
    2527                 :            :                                  (const void **)&spec, (const void **)&mask,
    2528                 :            :                                  (const void *)&supp_mask,
    2529                 :            :                                  &rte_flow_item_vlan_mask,
    2530                 :            :                                  sizeof(struct rte_flow_item_vlan), error);
    2531         [ #  # ]:          0 :         if (rc != 0)
    2532                 :            :                 return rc;
    2533                 :            : 
    2534         [ #  # ]:          0 :         if (spec != NULL) {
    2535                 :          0 :                 struct sfc_mae_ethertype *et = pdata->ethertypes;
    2536                 :            :                 const struct rte_flow_item_vlan *item_spec;
    2537                 :            :                 const struct rte_flow_item_vlan *item_mask;
    2538                 :            : 
    2539                 :            :                 item_spec = (const struct rte_flow_item_vlan *)spec;
    2540                 :          0 :                 item_mask = (const struct rte_flow_item_vlan *)mask;
    2541                 :            : 
    2542                 :            :                 /*
    2543                 :            :                  * Remember various match criteria in the parsing context.
    2544                 :            :                  * sfc_mae_rule_process_pattern_data() will consider them
    2545                 :            :                  * altogether when the rest of the items have been parsed.
    2546                 :            :                  */
    2547                 :          0 :                 et[pdata->nb_vlan_tags + 1].value = item_spec->hdr.eth_proto;
    2548                 :          0 :                 et[pdata->nb_vlan_tags + 1].mask = item_mask->hdr.eth_proto;
    2549                 :          0 :                 pdata->tci_masks[pdata->nb_vlan_tags] = item_mask->hdr.vlan_tci;
    2550         [ #  # ]:          0 :                 if (item_mask->has_more_vlan) {
    2551         [ #  # ]:          0 :                         if (pdata->nb_vlan_tags ==
    2552                 :            :                             SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
    2553                 :          0 :                                 return rte_flow_error_set(error, ENOTSUP,
    2554                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    2555                 :            :                                         "Can't use 'has_more_vlan' in "
    2556                 :            :                                         "the second item VLAN");
    2557                 :            :                         }
    2558                 :          0 :                         pdata->has_ivlan_mask = B_TRUE;
    2559         [ #  # ]:          0 :                         if (item_spec->has_more_vlan)
    2560                 :          0 :                                 pdata->has_ivlan_value = B_TRUE;
    2561                 :            :                 }
    2562                 :            : 
    2563                 :            :                 /* Convert TCI to MAE representation right now. */
    2564                 :          0 :                 rc = sfc_mae_parse_item(flocs, nb_flocs, spec, mask,
    2565                 :            :                                         ctx_mae, error);
    2566         [ #  # ]:          0 :                 if (rc != 0)
    2567                 :            :                         return rc;
    2568                 :            :         }
    2569                 :            : 
    2570                 :          0 :         ++(pdata->nb_vlan_tags);
    2571                 :            : 
    2572                 :          0 :         return 0;
    2573                 :            : }
    2574                 :            : 
    2575                 :            : static const struct sfc_mae_field_locator flocs_ipv4[] = {
    2576                 :            :         {
    2577                 :            :                 EFX_MAE_FIELD_SRC_IP4_BE,
    2578                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
    2579                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.src_addr),
    2580                 :            :         },
    2581                 :            :         {
    2582                 :            :                 EFX_MAE_FIELD_DST_IP4_BE,
    2583                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
    2584                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.dst_addr),
    2585                 :            :         },
    2586                 :            :         {
    2587                 :            :                 /*
    2588                 :            :                  * This locator is used only for building supported fields mask.
    2589                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2590                 :            :                  */
    2591                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2592                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id),
    2593                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id),
    2594                 :            :         },
    2595                 :            :         {
    2596                 :            :                 /*
    2597                 :            :                  * This locator is used only for building supported fields mask.
    2598                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2599                 :            :                  */
    2600                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2601                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.fragment_offset),
    2602                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.fragment_offset),
    2603                 :            :         },
    2604                 :            :         {
    2605                 :            :                 EFX_MAE_FIELD_IP_TOS,
    2606                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4,
    2607                 :            :                                  hdr.type_of_service),
    2608                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.type_of_service),
    2609                 :            :         },
    2610                 :            :         {
    2611                 :            :                 EFX_MAE_FIELD_IP_TTL,
    2612                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live),
    2613                 :            :                 offsetof(struct rte_flow_item_ipv4, hdr.time_to_live),
    2614                 :            :         },
    2615                 :            : };
    2616                 :            : 
    2617                 :            : static int
    2618                 :          0 : sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
    2619                 :            :                              struct sfc_flow_parse_ctx *ctx,
    2620                 :            :                              struct rte_flow_error *error)
    2621                 :            : {
    2622                 :            :         rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    2623                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2624                 :            :         struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2625                 :            :         struct rte_flow_item_ipv4 supp_mask;
    2626                 :            :         struct rte_flow_item item_dup;
    2627                 :          0 :         const uint8_t *spec = NULL;
    2628                 :          0 :         const uint8_t *mask = NULL;
    2629                 :            :         const uint8_t *last = NULL;
    2630                 :            :         int rc;
    2631                 :            : 
    2632                 :          0 :         item_dup.spec = item->spec;
    2633                 :          0 :         item_dup.mask = item->mask;
    2634                 :          0 :         item_dup.last = item->last;
    2635                 :          0 :         item_dup.type = item->type;
    2636                 :            : 
    2637                 :          0 :         sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4),
    2638                 :            :                                      &supp_mask, sizeof(supp_mask));
    2639                 :            : 
    2640                 :            :         /* We don't support IPv4 fragmentation in the outer frames. */
    2641         [ #  # ]:          0 :         if (ctx_mae->match_spec != ctx_mae->match_spec_action)
    2642                 :          0 :                 supp_mask.hdr.fragment_offset = 0;
    2643                 :            : 
    2644         [ #  # ]:          0 :         if (item->last != NULL) {
    2645                 :            :                 last = item->last;
    2646                 :          0 :                 item_dup.last = NULL;
    2647                 :            :         }
    2648                 :            : 
    2649                 :          0 :         rc = sfc_flow_parse_init(&item_dup,
    2650                 :            :                                  (const void **)&spec, (const void **)&mask,
    2651                 :            :                                  (const void *)&supp_mask,
    2652                 :            :                                  &rte_flow_item_ipv4_mask,
    2653                 :            :                                  sizeof(struct rte_flow_item_ipv4), error);
    2654         [ #  # ]:          0 :         if (rc != 0)
    2655                 :            :                 return rc;
    2656                 :            : 
    2657                 :          0 :         pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be;
    2658                 :          0 :         pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
    2659                 :            : 
    2660         [ #  # ]:          0 :         if (spec != NULL) {
    2661                 :            :                 const struct rte_flow_item_ipv4 *item_spec;
    2662                 :            :                 const struct rte_flow_item_ipv4 *item_mask;
    2663                 :            :                 const struct rte_flow_item_ipv4 *item_last;
    2664                 :            : 
    2665                 :            :                 item_spec = (const struct rte_flow_item_ipv4 *)spec;
    2666                 :          0 :                 item_mask = (const struct rte_flow_item_ipv4 *)mask;
    2667         [ #  # ]:          0 :                 if (last != NULL)
    2668                 :            :                         item_last = (const struct rte_flow_item_ipv4 *)last;
    2669                 :            : 
    2670                 :          0 :                 pdata->l3_next_proto_value = item_spec->hdr.next_proto_id;
    2671                 :          0 :                 pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id;
    2672                 :          0 :                 pdata->l3_frag_ofst_mask = item_mask->hdr.fragment_offset;
    2673                 :          0 :                 pdata->l3_frag_ofst_value = item_spec->hdr.fragment_offset;
    2674         [ #  # ]:          0 :                 if (last != NULL)
    2675                 :          0 :                         pdata->l3_frag_ofst_last = item_last->hdr.fragment_offset;
    2676                 :            :         } else {
    2677                 :            :                 return 0;
    2678                 :            :         }
    2679                 :            : 
    2680                 :          0 :         return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask,
    2681                 :            :                                   ctx_mae, error);
    2682                 :            : }
    2683                 :            : 
    2684                 :            : static const struct sfc_mae_field_locator flocs_ipv6[] = {
    2685                 :            :         {
    2686                 :            :                 EFX_MAE_FIELD_SRC_IP6_BE,
    2687                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
    2688                 :            :                 offsetof(struct rte_flow_item_ipv6, hdr.src_addr),
    2689                 :            :         },
    2690                 :            :         {
    2691                 :            :                 EFX_MAE_FIELD_DST_IP6_BE,
    2692                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
    2693                 :            :                 offsetof(struct rte_flow_item_ipv6, hdr.dst_addr),
    2694                 :            :         },
    2695                 :            :         {
    2696                 :            :                 /*
    2697                 :            :                  * This locator is used only for building supported fields mask.
    2698                 :            :                  * The field is handled by sfc_mae_rule_process_pattern_data().
    2699                 :            :                  */
    2700                 :            :                 SFC_MAE_FIELD_HANDLING_DEFERRED,
    2701                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto),
    2702                 :            :                 offsetof(struct rte_flow_item_ipv6, hdr.proto),
    2703                 :            :         },
    2704                 :            :         {
    2705                 :            :                 EFX_MAE_FIELD_IP_TTL,
    2706                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits),
    2707                 :            :                 offsetof(struct rte_flow_item_ipv6, hdr.hop_limits),
    2708                 :            :         },
    2709                 :            : };
    2710                 :            : 
    2711                 :            : static int
    2712                 :          0 : sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
    2713                 :            :                              struct sfc_flow_parse_ctx *ctx,
    2714                 :            :                              struct rte_flow_error *error)
    2715                 :            : {
    2716                 :            :         rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    2717                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2718                 :          0 :         const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap;
    2719                 :            :         struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2720                 :            :         struct rte_flow_item_ipv6 supp_mask;
    2721                 :          0 :         const uint8_t *spec = NULL;
    2722                 :          0 :         const uint8_t *mask = NULL;
    2723                 :            :         rte_be32_t vtc_flow_be;
    2724                 :            :         uint32_t vtc_flow;
    2725                 :            :         uint8_t tc_value;
    2726                 :            :         uint8_t tc_mask;
    2727                 :            :         int rc;
    2728                 :            : 
    2729                 :          0 :         sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6),
    2730                 :            :                                      &supp_mask, sizeof(supp_mask));
    2731                 :            : 
    2732                 :          0 :         vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK);
    2733                 :            :         memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be));
    2734                 :            : 
    2735                 :          0 :         rc = sfc_flow_parse_init(item,
    2736                 :            :                                  (const void **)&spec, (const void **)&mask,
    2737                 :            :                                  (const void *)&supp_mask,
    2738                 :            :                                  &rte_flow_item_ipv6_mask,
    2739                 :            :                                  sizeof(struct rte_flow_item_ipv6), error);
    2740         [ #  # ]:          0 :         if (rc != 0)
    2741                 :            :                 return rc;
    2742                 :            : 
    2743                 :          0 :         pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be;
    2744                 :          0 :         pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
    2745                 :            : 
    2746         [ #  # ]:          0 :         if (spec != NULL) {
    2747                 :            :                 const struct rte_flow_item_ipv6 *item_spec;
    2748                 :            :                 const struct rte_flow_item_ipv6 *item_mask;
    2749                 :            : 
    2750                 :            :                 item_spec = (const struct rte_flow_item_ipv6 *)spec;
    2751                 :          0 :                 item_mask = (const struct rte_flow_item_ipv6 *)mask;
    2752                 :            : 
    2753                 :          0 :                 pdata->l3_next_proto_value = item_spec->hdr.proto;
    2754                 :          0 :                 pdata->l3_next_proto_mask = item_mask->hdr.proto;
    2755                 :            :         } else {
    2756                 :            :                 return 0;
    2757                 :            :         }
    2758                 :            : 
    2759                 :          0 :         rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
    2760                 :            :                                 ctx_mae, error);
    2761         [ #  # ]:          0 :         if (rc != 0)
    2762                 :            :                 return rc;
    2763                 :            : 
    2764                 :          0 :         memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be));
    2765         [ #  # ]:          0 :         vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
    2766                 :          0 :         tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
    2767                 :            : 
    2768                 :          0 :         memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be));
    2769         [ #  # ]:          0 :         vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
    2770                 :          0 :         tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
    2771                 :            : 
    2772                 :          0 :         rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
    2773                 :            :                                           fremap[EFX_MAE_FIELD_IP_TOS],
    2774                 :            :                                           sizeof(tc_value), &tc_value,
    2775                 :            :                                           sizeof(tc_mask), &tc_mask);
    2776         [ #  # ]:          0 :         if (rc != 0) {
    2777                 :          0 :                 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
    2778                 :            :                                 NULL, "Failed to process item fields");
    2779                 :            :         }
    2780                 :            : 
    2781                 :            :         return 0;
    2782                 :            : }
    2783                 :            : 
    2784                 :            : static const struct sfc_mae_field_locator flocs_tcp[] = {
    2785                 :            :         {
    2786                 :            :                 EFX_MAE_FIELD_L4_SPORT_BE,
    2787                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port),
    2788                 :            :                 offsetof(struct rte_flow_item_tcp, hdr.src_port),
    2789                 :            :         },
    2790                 :            :         {
    2791                 :            :                 EFX_MAE_FIELD_L4_DPORT_BE,
    2792                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port),
    2793                 :            :                 offsetof(struct rte_flow_item_tcp, hdr.dst_port),
    2794                 :            :         },
    2795                 :            :         {
    2796                 :            :                 EFX_MAE_FIELD_TCP_FLAGS_BE,
    2797                 :            :                 /*
    2798                 :            :                  * The values have been picked intentionally since the
    2799                 :            :                  * target MAE field is oversize (16 bit). This mapping
    2800                 :            :                  * relies on the fact that the MAE field is big-endian.
    2801                 :            :                  */
    2802                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) +
    2803                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags),
    2804                 :            :                 offsetof(struct rte_flow_item_tcp, hdr.data_off),
    2805                 :            :         },
    2806                 :            : };
    2807                 :            : 
    2808                 :            : static int
    2809                 :          0 : sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
    2810                 :            :                             struct sfc_flow_parse_ctx *ctx,
    2811                 :            :                             struct rte_flow_error *error)
    2812                 :            : {
    2813                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2814                 :            :         struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2815                 :            :         struct rte_flow_item_tcp supp_mask;
    2816                 :          0 :         const uint8_t *spec = NULL;
    2817                 :          0 :         const uint8_t *mask = NULL;
    2818                 :            :         int rc;
    2819                 :            : 
    2820                 :            :         /*
    2821                 :            :          * When encountered among outermost items, item TCP is invalid.
    2822                 :            :          * Check which match specification is being constructed now.
    2823                 :            :          */
    2824         [ #  # ]:          0 :         if (ctx_mae->match_spec != ctx_mae->match_spec_action) {
    2825                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    2826                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, item,
    2827                 :            :                                           "TCP in outer frame is invalid");
    2828                 :            :         }
    2829                 :            : 
    2830                 :          0 :         sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp),
    2831                 :            :                                      &supp_mask, sizeof(supp_mask));
    2832                 :            : 
    2833                 :          0 :         rc = sfc_flow_parse_init(item,
    2834                 :            :                                  (const void **)&spec, (const void **)&mask,
    2835                 :            :                                  (const void *)&supp_mask,
    2836                 :            :                                  &rte_flow_item_tcp_mask,
    2837                 :            :                                  sizeof(struct rte_flow_item_tcp), error);
    2838         [ #  # ]:          0 :         if (rc != 0)
    2839                 :            :                 return rc;
    2840                 :            : 
    2841                 :          0 :         pdata->l3_next_proto_restriction_value = IPPROTO_TCP;
    2842                 :          0 :         pdata->l3_next_proto_restriction_mask = 0xff;
    2843                 :            : 
    2844         [ #  # ]:          0 :         if (spec == NULL)
    2845                 :            :                 return 0;
    2846                 :            : 
    2847                 :          0 :         return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask,
    2848                 :            :                                   ctx_mae, error);
    2849                 :            : }
    2850                 :            : 
    2851                 :            : static const struct sfc_mae_field_locator flocs_udp[] = {
    2852                 :            :         {
    2853                 :            :                 EFX_MAE_FIELD_L4_SPORT_BE,
    2854                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port),
    2855                 :            :                 offsetof(struct rte_flow_item_udp, hdr.src_port),
    2856                 :            :         },
    2857                 :            :         {
    2858                 :            :                 EFX_MAE_FIELD_L4_DPORT_BE,
    2859                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port),
    2860                 :            :                 offsetof(struct rte_flow_item_udp, hdr.dst_port),
    2861                 :            :         },
    2862                 :            : };
    2863                 :            : 
    2864                 :            : static int
    2865                 :          0 : sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item,
    2866                 :            :                             struct sfc_flow_parse_ctx *ctx,
    2867                 :            :                             struct rte_flow_error *error)
    2868                 :            : {
    2869                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2870                 :            :         struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
    2871                 :            :         struct rte_flow_item_udp supp_mask;
    2872                 :          0 :         const uint8_t *spec = NULL;
    2873                 :          0 :         const uint8_t *mask = NULL;
    2874                 :            :         int rc;
    2875                 :            : 
    2876                 :          0 :         sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp),
    2877                 :            :                                      &supp_mask, sizeof(supp_mask));
    2878                 :            : 
    2879                 :          0 :         rc = sfc_flow_parse_init(item,
    2880                 :            :                                  (const void **)&spec, (const void **)&mask,
    2881                 :            :                                  (const void *)&supp_mask,
    2882                 :            :                                  &rte_flow_item_udp_mask,
    2883                 :            :                                  sizeof(struct rte_flow_item_udp), error);
    2884         [ #  # ]:          0 :         if (rc != 0)
    2885                 :            :                 return rc;
    2886                 :            : 
    2887                 :          0 :         pdata->l3_next_proto_restriction_value = IPPROTO_UDP;
    2888                 :          0 :         pdata->l3_next_proto_restriction_mask = 0xff;
    2889                 :            : 
    2890         [ #  # ]:          0 :         if (spec == NULL)
    2891                 :            :                 return 0;
    2892                 :            : 
    2893                 :          0 :         return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask,
    2894                 :            :                                   ctx_mae, error);
    2895                 :            : }
    2896                 :            : 
    2897                 :            : static const struct sfc_mae_field_locator flocs_tunnel[] = {
    2898                 :            :         {
    2899                 :            :                 /*
    2900                 :            :                  * The size and offset values are relevant
    2901                 :            :                  * for Geneve and NVGRE, too.
    2902                 :            :                  */
    2903                 :            :                 .size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, hdr.vni),
    2904                 :            :                 .ofst = offsetof(struct rte_flow_item_vxlan, hdr.vni),
    2905                 :            :         },
    2906                 :            : };
    2907                 :            : 
    2908                 :            : /*
    2909                 :            :  * An auxiliary registry which allows using non-encap. field IDs
    2910                 :            :  * directly when building a match specification of type ACTION.
    2911                 :            :  *
    2912                 :            :  * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel().
    2913                 :            :  */
    2914                 :            : static const efx_mae_field_id_t field_ids_no_remap[] = {
    2915                 :            : #define FIELD_ID_NO_REMAP(_field) \
    2916                 :            :         [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field
    2917                 :            : 
    2918                 :            :         FIELD_ID_NO_REMAP(ETHER_TYPE_BE),
    2919                 :            :         FIELD_ID_NO_REMAP(ETH_SADDR_BE),
    2920                 :            :         FIELD_ID_NO_REMAP(ETH_DADDR_BE),
    2921                 :            :         FIELD_ID_NO_REMAP(VLAN0_TCI_BE),
    2922                 :            :         FIELD_ID_NO_REMAP(VLAN0_PROTO_BE),
    2923                 :            :         FIELD_ID_NO_REMAP(VLAN1_TCI_BE),
    2924                 :            :         FIELD_ID_NO_REMAP(VLAN1_PROTO_BE),
    2925                 :            :         FIELD_ID_NO_REMAP(SRC_IP4_BE),
    2926                 :            :         FIELD_ID_NO_REMAP(DST_IP4_BE),
    2927                 :            :         FIELD_ID_NO_REMAP(IP_PROTO),
    2928                 :            :         FIELD_ID_NO_REMAP(IP_TOS),
    2929                 :            :         FIELD_ID_NO_REMAP(IP_TTL),
    2930                 :            :         FIELD_ID_NO_REMAP(SRC_IP6_BE),
    2931                 :            :         FIELD_ID_NO_REMAP(DST_IP6_BE),
    2932                 :            :         FIELD_ID_NO_REMAP(L4_SPORT_BE),
    2933                 :            :         FIELD_ID_NO_REMAP(L4_DPORT_BE),
    2934                 :            :         FIELD_ID_NO_REMAP(TCP_FLAGS_BE),
    2935                 :            :         FIELD_ID_NO_REMAP(HAS_OVLAN),
    2936                 :            :         FIELD_ID_NO_REMAP(HAS_IVLAN),
    2937                 :            :         FIELD_ID_NO_REMAP(IS_IP_FRAG),
    2938                 :            :         FIELD_ID_NO_REMAP(IP_FIRST_FRAG),
    2939                 :            : 
    2940                 :            : #undef FIELD_ID_NO_REMAP
    2941                 :            : };
    2942                 :            : 
    2943                 :            : /*
    2944                 :            :  * An auxiliary registry which allows using "ENC" field IDs
    2945                 :            :  * when building a match specification of type OUTER.
    2946                 :            :  *
    2947                 :            :  * See sfc_mae_rule_encap_parse_init().
    2948                 :            :  */
    2949                 :            : static const efx_mae_field_id_t field_ids_remap_to_encap[] = {
    2950                 :            : #define FIELD_ID_REMAP_TO_ENCAP(_field) \
    2951                 :            :         [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field
    2952                 :            : 
    2953                 :            :         FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE),
    2954                 :            :         FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE),
    2955                 :            :         FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE),
    2956                 :            :         FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE),
    2957                 :            :         FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE),
    2958                 :            :         FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE),
    2959                 :            :         FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE),
    2960                 :            :         FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE),
    2961                 :            :         FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE),
    2962                 :            :         FIELD_ID_REMAP_TO_ENCAP(IP_PROTO),
    2963                 :            :         FIELD_ID_REMAP_TO_ENCAP(IP_TOS),
    2964                 :            :         FIELD_ID_REMAP_TO_ENCAP(IP_TTL),
    2965                 :            :         FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE),
    2966                 :            :         FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE),
    2967                 :            :         FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE),
    2968                 :            :         FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE),
    2969                 :            :         FIELD_ID_REMAP_TO_ENCAP(HAS_OVLAN),
    2970                 :            :         FIELD_ID_REMAP_TO_ENCAP(HAS_IVLAN),
    2971                 :            : 
    2972                 :            : #undef FIELD_ID_REMAP_TO_ENCAP
    2973                 :            : };
    2974                 :            : 
    2975                 :            : static int
    2976                 :          0 : sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item,
    2977                 :            :                                struct sfc_flow_parse_ctx *ctx,
    2978                 :            :                                struct rte_flow_error *error)
    2979                 :            : {
    2980                 :          0 :         struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
    2981                 :          0 :         uint8_t vnet_id_v[sizeof(uint32_t)] = {0};
    2982                 :          0 :         uint8_t vnet_id_m[sizeof(uint32_t)] = {0};
    2983                 :            :         const struct rte_flow_item_vxlan *vxp;
    2984                 :            :         uint8_t supp_mask[sizeof(uint64_t)];
    2985                 :          0 :         const uint8_t *spec = NULL;
    2986                 :          0 :         const uint8_t *mask = NULL;
    2987                 :            :         int rc;
    2988                 :            : 
    2989         [ #  # ]:          0 :         if (ctx_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
    2990                 :            :                 /*
    2991                 :            :                  * As a workaround, pattern processing has started from
    2992                 :            :                  * this (tunnel) item. No pattern data to process yet.
    2993                 :            :                  */
    2994                 :            :         } else {
    2995                 :            :                 /*
    2996                 :            :                  * We're about to start processing inner frame items.
    2997                 :            :                  * Process pattern data that has been deferred so far
    2998                 :            :                  * and reset pattern data storage.
    2999                 :            :                  */
    3000                 :          0 :                 rc = sfc_mae_rule_process_pattern_data(ctx_mae, error);
    3001         [ #  # ]:          0 :                 if (rc != 0)
    3002                 :            :                         return rc;
    3003                 :            :         }
    3004                 :            : 
    3005                 :          0 :         memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data));
    3006                 :            : 
    3007                 :          0 :         sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel),
    3008                 :            :                                      &supp_mask, sizeof(supp_mask));
    3009                 :            : 
    3010                 :            :         /*
    3011                 :            :          * This tunnel item was preliminarily detected by
    3012                 :            :          * sfc_mae_rule_encap_parse_init(). Default mask
    3013                 :            :          * was also picked by that helper. Use it here.
    3014                 :            :          */
    3015                 :          0 :         rc = sfc_flow_parse_init(item,
    3016                 :            :                                  (const void **)&spec, (const void **)&mask,
    3017                 :            :                                  (const void *)&supp_mask,
    3018                 :            :                                  ctx_mae->tunnel_def_mask,
    3019                 :          0 :                                  ctx_mae->tunnel_def_mask_size,  error);
    3020         [ #  # ]:          0 :         if (rc != 0)
    3021                 :            :                 return rc;
    3022                 :            : 
    3023                 :            :         /*
    3024                 :            :          * This item and later ones comprise a
    3025                 :            :          * match specification of type ACTION.
    3026                 :            :          */
    3027                 :          0 :         ctx_mae->match_spec = ctx_mae->match_spec_action;
    3028                 :            : 
    3029                 :            :         /* This item and later ones use non-encap. EFX MAE field IDs. */
    3030                 :          0 :         ctx_mae->field_ids_remap = field_ids_no_remap;
    3031                 :            : 
    3032         [ #  # ]:          0 :         if (spec == NULL)
    3033                 :            :                 return 0;
    3034                 :            : 
    3035                 :            :         /*
    3036                 :            :          * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one.
    3037                 :            :          * Copy 24-bit VNI, which is BE, at offset 1 in it.
    3038                 :            :          * The extra byte is 0 both in the mask and in the value.
    3039                 :            :          */
    3040                 :            :         vxp = (const struct rte_flow_item_vxlan *)spec;
    3041                 :          0 :         memcpy(vnet_id_v + 1, &vxp->hdr.vni, sizeof(vxp->hdr.vni));
    3042                 :            : 
    3043                 :          0 :         vxp = (const struct rte_flow_item_vxlan *)mask;
    3044                 :          0 :         memcpy(vnet_id_m + 1, &vxp->hdr.vni, sizeof(vxp->hdr.vni));
    3045                 :            : 
    3046                 :          0 :         rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
    3047                 :            :                                           EFX_MAE_FIELD_ENC_VNET_ID_BE,
    3048                 :            :                                           sizeof(vnet_id_v), vnet_id_v,
    3049                 :            :                                           sizeof(vnet_id_m), vnet_id_m);
    3050         [ #  # ]:          0 :         if (rc != 0) {
    3051                 :          0 :                 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
    3052                 :            :                                         item, "Failed to set VXLAN VNI");
    3053                 :            :         }
    3054                 :            : 
    3055                 :            :         return rc;
    3056                 :            : }
    3057                 :            : 
    3058                 :            : static const struct sfc_flow_item sfc_flow_items[] = {
    3059                 :            :         {
    3060                 :            :                 .type = RTE_FLOW_ITEM_TYPE_MARK,
    3061                 :            :                 .name = "MARK",
    3062                 :            :                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
    3063                 :            :                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
    3064                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3065                 :            :                 .parse = sfc_mae_rule_parse_item_mark,
    3066                 :            :         },
    3067                 :            :         {
    3068                 :            :                 .type = RTE_FLOW_ITEM_TYPE_PORT_ID,
    3069                 :            :                 .name = "PORT_ID",
    3070                 :            :                 /*
    3071                 :            :                  * In terms of RTE flow, this item is a META one,
    3072                 :            :                  * and its position in the pattern is don't care.
    3073                 :            :                  */
    3074                 :            :                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
    3075                 :            :                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
    3076                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3077                 :            :                 .parse = sfc_mae_rule_parse_item_port_id,
    3078                 :            :         },
    3079                 :            :         {
    3080                 :            :                 .type = RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR,
    3081                 :            :                 .name = "PORT_REPRESENTOR",
    3082                 :            :                 /*
    3083                 :            :                  * In terms of RTE flow, this item is a META one,
    3084                 :            :                  * and its position in the pattern is don't care.
    3085                 :            :                  */
    3086                 :            :                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
    3087                 :            :                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
    3088                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3089                 :            :                 .parse = sfc_mae_rule_parse_item_ethdev_based,
    3090                 :            :         },
    3091                 :            :         {
    3092                 :            :                 .type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
    3093                 :            :                 .name = "REPRESENTED_PORT",
    3094                 :            :                 /*
    3095                 :            :                  * In terms of RTE flow, this item is a META one,
    3096                 :            :                  * and its position in the pattern is don't care.
    3097                 :            :                  */
    3098                 :            :                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
    3099                 :            :                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
    3100                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3101                 :            :                 .parse = sfc_mae_rule_parse_item_ethdev_based,
    3102                 :            :         },
    3103                 :            :         {
    3104                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
    3105                 :            :                 .name = "ETH",
    3106                 :            :                 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
    3107                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    3108                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3109                 :            :                 .parse = sfc_mae_rule_parse_item_eth,
    3110                 :            :         },
    3111                 :            :         {
    3112                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
    3113                 :            :                 .name = "VLAN",
    3114                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    3115                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    3116                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3117                 :            :                 .parse = sfc_mae_rule_parse_item_vlan,
    3118                 :            :         },
    3119                 :            :         {
    3120                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
    3121                 :            :                 .name = "IPV4",
    3122                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    3123                 :            :                 .layer = SFC_FLOW_ITEM_L3,
    3124                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3125                 :            :                 .parse = sfc_mae_rule_parse_item_ipv4,
    3126                 :            :         },
    3127                 :            :         {
    3128                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
    3129                 :            :                 .name = "IPV6",
    3130                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    3131                 :            :                 .layer = SFC_FLOW_ITEM_L3,
    3132                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3133                 :            :                 .parse = sfc_mae_rule_parse_item_ipv6,
    3134                 :            :         },
    3135                 :            :         {
    3136                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
    3137                 :            :                 .name = "TCP",
    3138                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    3139                 :            :                 .layer = SFC_FLOW_ITEM_L4,
    3140                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3141                 :            :                 .parse = sfc_mae_rule_parse_item_tcp,
    3142                 :            :         },
    3143                 :            :         {
    3144                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
    3145                 :            :                 .name = "UDP",
    3146                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    3147                 :            :                 .layer = SFC_FLOW_ITEM_L4,
    3148                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3149                 :            :                 .parse = sfc_mae_rule_parse_item_udp,
    3150                 :            :         },
    3151                 :            :         {
    3152                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
    3153                 :            :                 .name = "VXLAN",
    3154                 :            :                 .prev_layer = SFC_FLOW_ITEM_L4,
    3155                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    3156                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3157                 :            :                 .parse = sfc_mae_rule_parse_item_tunnel,
    3158                 :            :         },
    3159                 :            :         {
    3160                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
    3161                 :            :                 .name = "GENEVE",
    3162                 :            :                 .prev_layer = SFC_FLOW_ITEM_L4,
    3163                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    3164                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3165                 :            :                 .parse = sfc_mae_rule_parse_item_tunnel,
    3166                 :            :         },
    3167                 :            :         {
    3168                 :            :                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
    3169                 :            :                 .name = "NVGRE",
    3170                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    3171                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    3172                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
    3173                 :            :                 .parse = sfc_mae_rule_parse_item_tunnel,
    3174                 :            :         },
    3175                 :            : };
    3176                 :            : 
    3177                 :            : #define SFC_MAE_CT_KEY_ET 0x01 /* EtherType */
    3178                 :            : #define SFC_MAE_CT_KEY_DA 0x02 /* IPv4/IPv6 destination address */
    3179                 :            : #define SFC_MAE_CT_KEY_SA 0x04 /* IPv4/IPv6 source address */
    3180                 :            : #define SFC_MAE_CT_KEY_L4 0x08 /* IPv4/IPv6 L4 protocol ID */
    3181                 :            : #define SFC_MAE_CT_KEY_DP 0x10 /* L4 destination port */
    3182                 :            : #define SFC_MAE_CT_KEY_SP 0x20 /* L4 source port */
    3183                 :            : 
    3184                 :            : #define SFC_MAE_CT_KEY_FIELD_SIZE_MAX   sizeof(sfc_mae_conntrack_key_t)
    3185                 :            : 
    3186                 :            : static const struct sfc_mae_field_locator flocs_ct[] = {
    3187                 :            :         {
    3188                 :            :                 EFX_MAE_FIELD_ETHER_TYPE_BE,
    3189                 :            :                 RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ether_type_le),
    3190                 :            :                 offsetof(sfc_mae_conntrack_key_t, ether_type_le),
    3191                 :            :                 SFC_MAE_CT_KEY_ET,
    3192                 :            :         },
    3193                 :            :         {
    3194                 :            :                 EFX_MAE_FIELD_DST_IP4_BE,
    3195                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
    3196                 :            :                 offsetof(sfc_mae_conntrack_key_t, dst_addr_le) +
    3197                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr) -
    3198                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
    3199                 :            :                 SFC_MAE_CT_KEY_DA,
    3200                 :            :         },
    3201                 :            :         {
    3202                 :            :                 EFX_MAE_FIELD_SRC_IP4_BE,
    3203                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
    3204                 :            :                 offsetof(sfc_mae_conntrack_key_t, src_addr_le) +
    3205                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr) -
    3206                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
    3207                 :            :                 SFC_MAE_CT_KEY_SA,
    3208                 :            :         },
    3209                 :            :         {
    3210                 :            :                 EFX_MAE_FIELD_DST_IP6_BE,
    3211                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
    3212                 :            :                 offsetof(sfc_mae_conntrack_key_t, dst_addr_le),
    3213                 :            :                 SFC_MAE_CT_KEY_DA,
    3214                 :            :         },
    3215                 :            :         {
    3216                 :            :                 EFX_MAE_FIELD_SRC_IP6_BE,
    3217                 :            :                 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
    3218                 :            :                 offsetof(sfc_mae_conntrack_key_t, src_addr_le),
    3219                 :            :                 SFC_MAE_CT_KEY_SA,
    3220                 :            :         },
    3221                 :            :         {
    3222                 :            :                 EFX_MAE_FIELD_IP_PROTO,
    3223                 :            :                 RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, ip_proto),
    3224                 :            :                 offsetof(sfc_mae_conntrack_key_t, ip_proto),
    3225                 :            :                 SFC_MAE_CT_KEY_L4,
    3226                 :            :         },
    3227                 :            :         {
    3228                 :            :                 EFX_MAE_FIELD_L4_DPORT_BE,
    3229                 :            :                 RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, dst_port_le),
    3230                 :            :                 offsetof(sfc_mae_conntrack_key_t, dst_port_le),
    3231                 :            :                 SFC_MAE_CT_KEY_DP,
    3232                 :            :         },
    3233                 :            :         {
    3234                 :            :                 EFX_MAE_FIELD_L4_SPORT_BE,
    3235                 :            :                 RTE_SIZEOF_FIELD(sfc_mae_conntrack_key_t, src_port_le),
    3236                 :            :                 offsetof(sfc_mae_conntrack_key_t, src_port_le),
    3237                 :            :                 SFC_MAE_CT_KEY_SP,
    3238                 :            :         },
    3239                 :            : };
    3240                 :            : 
    3241                 :            : static int
    3242                 :          0 : sfc_mae_rule_process_ct(struct sfc_adapter *sa, struct sfc_mae_parse_ctx *pctx,
    3243                 :            :                         struct sfc_mae_action_rule_ctx *action_rule_ctx,
    3244                 :            :                         struct sfc_flow_spec_mae *spec,
    3245                 :            :                         struct rte_flow_error *error)
    3246                 :            : {
    3247                 :            :         efx_mae_match_spec_t *match_spec_tmp;
    3248                 :            :         uint8_t ct_key_missing_fields =
    3249                 :            :                 SFC_MAE_CT_KEY_ET | SFC_MAE_CT_KEY_DA | SFC_MAE_CT_KEY_SA |
    3250                 :            :                 SFC_MAE_CT_KEY_L4 | SFC_MAE_CT_KEY_DP | SFC_MAE_CT_KEY_SP;
    3251                 :            :         unsigned int i;
    3252                 :            :         int rc;
    3253                 :            : 
    3254         [ #  # ]:          0 :         if (pctx->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    3255                 :            :                 /*
    3256                 :            :                  * TUNNEL rules have no network match fields that belong
    3257                 :            :                  * in an action rule match specification, so nothing can
    3258                 :            :                  * be possibly utilised for conntrack assistance offload.
    3259                 :            :                  */
    3260                 :            :                 return 0;
    3261                 :            :         }
    3262                 :            : 
    3263         [ #  # ]:          0 :         if (!sfc_mae_conntrack_is_supported(sa))
    3264                 :            :                 return 0;
    3265                 :            : 
    3266                 :          0 :         rc = efx_mae_match_spec_clone(sa->nic, pctx->match_spec_action,
    3267                 :            :                                       &match_spec_tmp);
    3268         [ #  # ]:          0 :         if (rc != 0) {
    3269                 :          0 :                 return rte_flow_error_set(error, rc,
    3270                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3271                 :            :                                 "AR: failed to clone the match specification");
    3272                 :            :         }
    3273                 :            : 
    3274         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(flocs_ct); ++i) {
    3275                 :            :                 const struct sfc_mae_field_locator *fl = &flocs_ct[i];
    3276                 :            :                 uint8_t mask_full[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
    3277                 :            :                 uint8_t mask_zero[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
    3278                 :            :                 uint8_t value[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
    3279                 :            :                 uint8_t mask[SFC_MAE_CT_KEY_FIELD_SIZE_MAX];
    3280                 :          0 :                 uint8_t *ct_key = (uint8_t *)&spec->ct_key;
    3281                 :          0 :                 efx_mae_field_id_t fid = fl->field_id;
    3282                 :            :                 unsigned int j;
    3283                 :            : 
    3284                 :          0 :                 rc = efx_mae_match_spec_field_get(match_spec_tmp, fid,
    3285                 :            :                                                   fl->size, value,
    3286                 :          0 :                                                   fl->size, mask);
    3287         [ #  # ]:          0 :                 if (rc != 0) {
    3288                 :          0 :                         return rte_flow_error_set(error, rc,
    3289                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3290                 :            :                                         "AR: failed to extract match field");
    3291                 :            :                 }
    3292                 :            : 
    3293                 :            :                 memset(mask_full, 0xff, fl->size);
    3294                 :            : 
    3295         [ #  # ]:          0 :                 if (memcmp(mask, mask_full, fl->size) != 0)
    3296                 :          0 :                         continue;
    3297                 :            : 
    3298                 :            :                 memset(mask_zero, 0, fl->size);
    3299                 :            : 
    3300                 :          0 :                 rc = efx_mae_match_spec_field_set(match_spec_tmp, fid,
    3301                 :            :                                                   fl->size, mask_zero,
    3302                 :            :                                                   fl->size, mask_zero);
    3303         [ #  # ]:          0 :                 if (rc != 0) {
    3304                 :          0 :                         return rte_flow_error_set(error, rc,
    3305                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3306                 :            :                                         "AR: failed to erase match field");
    3307                 :            :                 }
    3308                 :            : 
    3309         [ #  # ]:          0 :                 for (j = 0; j < fl->size; ++j) {
    3310                 :          0 :                         uint8_t *byte_dst = ct_key + fl->ofst + fl->size - 1 - j;
    3311                 :          0 :                         const uint8_t *byte_src = value + j;
    3312                 :            : 
    3313                 :          0 :                         *byte_dst = *byte_src;
    3314                 :            :                 }
    3315                 :            : 
    3316                 :          0 :                 ct_key_missing_fields &= ~(fl->ct_key_field);
    3317                 :            :         }
    3318                 :            : 
    3319         [ #  # ]:          0 :         if (ct_key_missing_fields != 0) {
    3320                 :          0 :                 efx_mae_match_spec_fini(sa->nic, match_spec_tmp);
    3321                 :          0 :                 return 0;
    3322                 :            :         }
    3323                 :            : 
    3324                 :          0 :         efx_mae_match_spec_fini(sa->nic, pctx->match_spec_action);
    3325                 :          0 :         pctx->match_spec_action = match_spec_tmp;
    3326                 :            : 
    3327         [ #  # ]:          0 :         if (pctx->ft_rule_type == SFC_FT_RULE_SWITCH) {
    3328                 :            :                 /*
    3329                 :            :                  * A SWITCH rule re-uses the corresponding TUNNEL rule's
    3330                 :            :                  * outer rule, where conntrack request should have been
    3331                 :            :                  * configured already, so skip outer rule processing.
    3332                 :            :                  */
    3333                 :          0 :                 goto skip_outer_rule;
    3334                 :            :         }
    3335                 :            : 
    3336         [ #  # ]:          0 :         if (pctx->match_spec_outer == NULL) {
    3337                 :            :                 const struct sfc_mae_pattern_data *pdata = &pctx->pattern_data;
    3338                 :            :                 const struct sfc_mae_ethertype *et;
    3339                 :            :                 struct sfc_mae *mae = &sa->mae;
    3340                 :            : 
    3341                 :          0 :                 rc = efx_mae_match_spec_init(sa->nic,
    3342                 :            :                                              EFX_MAE_RULE_OUTER,
    3343                 :          0 :                                              mae->nb_outer_rule_prios_max - 1,
    3344                 :            :                                              &pctx->match_spec_outer);
    3345         [ #  # ]:          0 :                 if (rc != 0) {
    3346                 :          0 :                         return rte_flow_error_set(error, rc,
    3347                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3348                 :            :                                 "OR: failed to initialise the match specification");
    3349                 :            :                 }
    3350                 :            : 
    3351                 :            :                 /* Match on EtherType appears to be compulsory in outer rules */
    3352                 :            : 
    3353                 :          0 :                 et = &pdata->ethertypes[pdata->nb_vlan_tags];
    3354                 :            : 
    3355                 :          0 :                 rc = efx_mae_match_spec_field_set(pctx->match_spec_outer,
    3356                 :            :                                 EFX_MAE_FIELD_ENC_ETHER_TYPE_BE,
    3357                 :          0 :                                 sizeof(et->value), (const uint8_t *)&et->value,
    3358                 :          0 :                                 sizeof(et->mask), (const uint8_t *)&et->mask);
    3359         [ #  # ]:          0 :                 if (rc != 0) {
    3360                 :          0 :                         return rte_flow_error_set(error, rc,
    3361                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3362                 :            :                                         "OR: failed to set match on EtherType");
    3363                 :            :                 }
    3364                 :            :         }
    3365                 :            : 
    3366                 :          0 :         rc = efx_mae_outer_rule_do_ct_set(pctx->match_spec_outer);
    3367         [ #  # ]:          0 :         if (rc != 0) {
    3368                 :          0 :                 return rte_flow_error_set(error, rc,
    3369                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3370                 :            :                                 "OR: failed to request CT lookup");
    3371                 :            :         }
    3372                 :            : 
    3373                 :          0 : skip_outer_rule:
    3374                 :            :         /* Initial/dummy CT mark value */
    3375                 :          0 :         action_rule_ctx->ct_mark = 1;
    3376                 :            : 
    3377                 :          0 :         return 0;
    3378                 :            : }
    3379                 :            : 
    3380                 :            : #undef SFC_MAE_CT_KEY_ET
    3381                 :            : #undef SFC_MAE_CT_KEY_DA
    3382                 :            : #undef SFC_MAE_CT_KEY_SA
    3383                 :            : #undef SFC_MAE_CT_KEY_L4
    3384                 :            : #undef SFC_MAE_CT_KEY_DP
    3385                 :            : #undef SFC_MAE_CT_KEY_SP
    3386                 :            : 
    3387                 :            : static int
    3388                 :          0 : sfc_mae_rule_process_outer(struct sfc_adapter *sa,
    3389                 :            :                            struct sfc_mae_parse_ctx *ctx,
    3390                 :            :                            struct sfc_mae_outer_rule **rulep,
    3391                 :            :                            struct rte_flow_error *error)
    3392                 :            : {
    3393                 :          0 :         efx_mae_rule_id_t or_id = { .id = EFX_MAE_RSRC_ID_INVALID };
    3394                 :            :         int rc;
    3395                 :            : 
    3396         [ #  # ]:          0 :         if (ctx->internal) {
    3397                 :            :                 /*
    3398                 :            :                  * A driver-internal flow may not comprise an outer rule,
    3399                 :            :                  * but it must not match on invalid outer rule ID since
    3400                 :            :                  * it must catch all missed packets, including those
    3401                 :            :                  * that hit an outer rule of another flow entry but
    3402                 :            :                  * do not hit a higher-priority action rule later.
    3403                 :            :                  * So do not set match on outer rule ID here.
    3404                 :            :                  */
    3405                 :            :                 SFC_ASSERT(ctx->match_spec_outer == NULL);
    3406                 :          0 :                 *rulep = NULL;
    3407                 :          0 :                 return 0;
    3408                 :            :         }
    3409                 :            : 
    3410         [ #  # ]:          0 :         if (ctx->match_spec_outer == NULL) {
    3411                 :          0 :                 *rulep = NULL;
    3412                 :          0 :                 goto no_or_id;
    3413                 :            :         }
    3414                 :            : 
    3415         [ #  # ]:          0 :         if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
    3416                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3417                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3418                 :            :                                           "Inconsistent pattern (outer)");
    3419                 :            :         }
    3420                 :            : 
    3421                 :          0 :         *rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer,
    3422                 :            :                                            ctx->encap_type);
    3423         [ #  # ]:          0 :         if (*rulep != NULL) {
    3424                 :          0 :                 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
    3425                 :            :         } else {
    3426                 :          0 :                 rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer,
    3427                 :            :                                             ctx->encap_type, rulep);
    3428         [ #  # ]:          0 :                 if (rc != 0) {
    3429                 :          0 :                         return rte_flow_error_set(error, rc,
    3430                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3431                 :            :                                         "Failed to process the pattern");
    3432                 :            :                 }
    3433                 :            :         }
    3434                 :            : 
    3435                 :            :         /* The spec has now been tracked by the outer rule entry. */
    3436                 :          0 :         ctx->match_spec_outer = NULL;
    3437                 :            : 
    3438                 :          0 :         or_id.id = (*rulep)->fw_rsrc.rule_id.id;
    3439                 :            : 
    3440                 :          0 : no_or_id:
    3441         [ #  # ]:          0 :         switch (ctx->ft_rule_type) {
    3442                 :            :         case SFC_FT_RULE_NONE:
    3443                 :            :                 break;
    3444                 :            :         case SFC_FT_RULE_TUNNEL:
    3445                 :            :                 /*
    3446                 :            :                  * Workaround. TUNNEL flows are not supposed to involve
    3447                 :            :                  * MAE action rules, but, due to the currently limited
    3448                 :            :                  * HW/FW implementation, action rules are still needed.
    3449                 :            :                  * See sfc_mae_rule_parse_pattern().
    3450                 :            :                  */
    3451                 :            :                 break;
    3452                 :          0 :         case SFC_FT_RULE_SWITCH:
    3453                 :            :                 /*
    3454                 :            :                  * Match on recirculation ID rather than
    3455                 :            :                  * on the outer rule allocation handle.
    3456                 :            :                  */
    3457                 :          0 :                 rc = efx_mae_match_spec_recirc_id_set(ctx->match_spec_action,
    3458                 :          0 :                                 SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id));
    3459         [ #  # ]:          0 :                 if (rc != 0) {
    3460                 :          0 :                         return rte_flow_error_set(error, rc,
    3461                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3462                 :            :                                         "FT: SWITCH: AR: failed to request match on RECIRC_ID");
    3463                 :            :                 }
    3464                 :            :                 return 0;
    3465                 :          0 :         default:
    3466                 :            :                 SFC_ASSERT(B_FALSE);
    3467                 :            :         }
    3468                 :            : 
    3469                 :            :         /*
    3470                 :            :          * In MAE, lookup sequence comprises outer parse, outer rule lookup,
    3471                 :            :          * inner parse (when some outer rule is hit) and action rule lookup.
    3472                 :            :          * If the currently processed flow does not come with an outer rule,
    3473                 :            :          * its action rule must be available only for packets which miss in
    3474                 :            :          * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
    3475                 :            :          * in the action rule specification; this ensures correct behaviour.
    3476                 :            :          *
    3477                 :            :          * If, however, this flow does have an outer rule, OR_ID match must
    3478                 :            :          * be set to the currently known value for that outer rule. It will
    3479                 :            :          * be either 0xffffffff or some valid ID, depending on whether this
    3480                 :            :          * outer rule is currently active (adapter state is STARTED) or not.
    3481                 :            :          */
    3482                 :          0 :         rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
    3483                 :            :                                                   &or_id);
    3484         [ #  # ]:          0 :         if (rc != 0) {
    3485                 :          0 :                 sfc_mae_outer_rule_del(sa, *rulep);
    3486                 :          0 :                 *rulep = NULL;
    3487                 :            : 
    3488                 :          0 :                 return rte_flow_error_set(error, rc,
    3489                 :            :                                           RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3490                 :            :                                           "Failed to process the pattern");
    3491                 :            :         }
    3492                 :            : 
    3493                 :            :         return 0;
    3494                 :            : }
    3495                 :            : 
    3496                 :            : static int
    3497                 :          0 : sfc_mae_rule_preparse_item_mark(const struct rte_flow_item_mark *spec,
    3498                 :            :                                 struct sfc_mae_parse_ctx *ctx)
    3499                 :            : {
    3500                 :            :         struct sfc_ft_ctx *ft_ctx;
    3501                 :            :         uint32_t user_mark;
    3502                 :            : 
    3503         [ #  # ]:          0 :         if (spec == NULL) {
    3504                 :          0 :                 sfc_err(ctx->sa, "FT: SWITCH: NULL spec in item MARK");
    3505                 :          0 :                 return EINVAL;
    3506                 :            :         }
    3507                 :            : 
    3508                 :          0 :         ft_ctx = sfc_ft_ctx_pick(ctx->sa, spec->id);
    3509         [ #  # ]:          0 :         if (ft_ctx == NULL) {
    3510                 :          0 :                 sfc_err(ctx->sa, "FT: SWITCH: invalid context");
    3511                 :          0 :                 return EINVAL;
    3512                 :            :         }
    3513                 :            : 
    3514         [ #  # ]:          0 :         if (ft_ctx->refcnt == 0) {
    3515                 :          0 :                 sfc_err(ctx->sa, "FT: SWITCH: inactive context (ID=%u)",
    3516                 :            :                         ft_ctx->id);
    3517                 :          0 :                 return ENOENT;
    3518                 :            :         }
    3519                 :            : 
    3520                 :          0 :         user_mark = SFC_FT_FLOW_MARK_TO_USER_MARK(spec->id);
    3521         [ #  # ]:          0 :         if (user_mark != 0) {
    3522                 :          0 :                 sfc_err(ctx->sa, "FT: SWITCH: invalid item MARK");
    3523                 :          0 :                 return EINVAL;
    3524                 :            :         }
    3525                 :            : 
    3526                 :          0 :         sfc_dbg(ctx->sa, "FT: SWITCH: detected");
    3527                 :            : 
    3528                 :          0 :         ctx->ft_rule_type = SFC_FT_RULE_SWITCH;
    3529                 :          0 :         ctx->ft_ctx = ft_ctx;
    3530                 :            : 
    3531                 :          0 :         return 0;
    3532                 :            : }
    3533                 :            : 
    3534                 :            : static int
    3535                 :          0 : sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
    3536                 :            :                               struct sfc_mae_parse_ctx *ctx,
    3537                 :            :                               struct rte_flow_error *error)
    3538                 :            : {
    3539                 :          0 :         const struct rte_flow_item *pattern = ctx->pattern;
    3540                 :            :         struct sfc_mae *mae = &sa->mae;
    3541                 :            :         bool request_ct = false;
    3542                 :            :         uint8_t recirc_id = 0;
    3543                 :            :         int rc;
    3544                 :            : 
    3545         [ #  # ]:          0 :         if (pattern == NULL) {
    3546                 :          0 :                 rte_flow_error_set(error, EINVAL,
    3547                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
    3548                 :            :                                    "NULL pattern");
    3549                 :          0 :                 return -rte_errno;
    3550                 :            :         }
    3551                 :            : 
    3552                 :            :         for (;;) {
    3553   [ #  #  #  #  :          0 :                 switch (pattern->type) {
                   #  # ]
    3554                 :          0 :                 case RTE_FLOW_ITEM_TYPE_MARK:
    3555                 :          0 :                         rc = sfc_mae_rule_preparse_item_mark(pattern->spec,
    3556                 :            :                                                              ctx);
    3557         [ #  # ]:          0 :                         if (rc != 0) {
    3558                 :          0 :                                 return rte_flow_error_set(error, rc,
    3559                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3560                 :            :                                                   pattern, "FT: SWITCH: invalid item MARK");
    3561                 :            :                         }
    3562                 :          0 :                         ++pattern;
    3563                 :          0 :                         continue;
    3564                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    3565                 :          0 :                         ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
    3566                 :          0 :                         ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask;
    3567                 :          0 :                         ctx->tunnel_def_mask_size =
    3568                 :            :                                 sizeof(rte_flow_item_vxlan_mask);
    3569                 :          0 :                         break;
    3570                 :          0 :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    3571                 :          0 :                         ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
    3572                 :          0 :                         ctx->tunnel_def_mask = &rte_flow_item_geneve_mask;
    3573                 :          0 :                         ctx->tunnel_def_mask_size =
    3574                 :            :                                 sizeof(rte_flow_item_geneve_mask);
    3575                 :          0 :                         break;
    3576                 :          0 :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    3577                 :          0 :                         ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
    3578                 :          0 :                         ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask;
    3579                 :          0 :                         ctx->tunnel_def_mask_size =
    3580                 :            :                                 sizeof(rte_flow_item_nvgre_mask);
    3581                 :          0 :                         break;
    3582                 :            :                 case RTE_FLOW_ITEM_TYPE_END:
    3583                 :            :                         break;
    3584                 :          0 :                 default:
    3585                 :          0 :                         ++pattern;
    3586                 :          0 :                         continue;
    3587                 :            :                 };
    3588                 :            : 
    3589                 :            :                 break;
    3590                 :            :         }
    3591                 :            : 
    3592   [ #  #  #  # ]:          0 :         switch (ctx->ft_rule_type) {
    3593                 :          0 :         case SFC_FT_RULE_NONE:
    3594         [ #  # ]:          0 :                 if (pattern->type == RTE_FLOW_ITEM_TYPE_END)
    3595                 :            :                         return 0;
    3596                 :            :                 break;
    3597                 :          0 :         case SFC_FT_RULE_TUNNEL:
    3598         [ #  # ]:          0 :                 if (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
    3599                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3600                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3601                 :            :                                                   pattern, "FT: TUNNEL: invalid item");
    3602                 :            :                 }
    3603                 :          0 :                 ctx->encap_type = ctx->ft_ctx->encap_type;
    3604                 :          0 :                 break;
    3605                 :          0 :         case SFC_FT_RULE_SWITCH:
    3606         [ #  # ]:          0 :                 if (pattern->type == RTE_FLOW_ITEM_TYPE_END) {
    3607                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3608                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3609                 :            :                                                   NULL, "FT: SWITCH: missing tunnel item");
    3610         [ #  # ]:          0 :                 } else if (ctx->encap_type != ctx->ft_ctx->encap_type) {
    3611                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    3612                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
    3613                 :            :                                                   pattern, "FT: SWITCH: tunnel type mismatch");
    3614                 :            :                 }
    3615                 :            : 
    3616                 :            :                 /*
    3617                 :            :                  * The HW/FW hasn't got support for the use of "ENC" fields in
    3618                 :            :                  * action rules (except the VNET_ID one) yet. As a workaround,
    3619                 :            :                  * start parsing the pattern from the tunnel item.
    3620                 :            :                  */
    3621                 :          0 :                 ctx->pattern = pattern;
    3622                 :          0 :                 break;
    3623                 :            :         default:
    3624                 :            :                 SFC_ASSERT(B_FALSE);
    3625                 :            :                 break;
    3626                 :            :         }
    3627                 :            : 
    3628         [ #  # ]:          0 :         if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) {
    3629                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    3630                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3631                 :            :                                           "OR: unsupported tunnel type");
    3632                 :            :         }
    3633                 :            : 
    3634   [ #  #  #  # ]:          0 :         switch (ctx->ft_rule_type) {
    3635                 :          0 :         case SFC_FT_RULE_TUNNEL:
    3636                 :          0 :                 recirc_id = SFC_FT_CTX_ID_TO_CTX_MARK(ctx->ft_ctx->id);
    3637                 :            : 
    3638         [ #  # ]:          0 :                 if (sfc_mae_conntrack_is_supported(sa)) {
    3639                 :            :                         /*
    3640                 :            :                          * Request lookup in conntrack table since SWITCH rules
    3641                 :            :                          * are eligible to utilise this type of assistance.
    3642                 :            :                          */
    3643                 :            :                         request_ct = true;
    3644                 :            :                 }
    3645                 :            :                 /* FALLTHROUGH */
    3646                 :            :         case SFC_FT_RULE_NONE:
    3647         [ #  # ]:          0 :                 if (ctx->priority >= mae->nb_outer_rule_prios_max) {
    3648                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    3649                 :            :                                         RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    3650                 :            :                                         NULL, "OR: unsupported priority level");
    3651                 :            :                 }
    3652                 :            : 
    3653                 :          0 :                 rc = efx_mae_match_spec_init(sa->nic,
    3654                 :            :                                              EFX_MAE_RULE_OUTER, ctx->priority,
    3655                 :            :                                              &ctx->match_spec_outer);
    3656         [ #  # ]:          0 :                 if (rc != 0) {
    3657                 :          0 :                         return rte_flow_error_set(error, rc,
    3658                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3659                 :            :                                 "OR: failed to initialise the match specification");
    3660                 :            :                 }
    3661                 :            : 
    3662                 :            :                 /*
    3663                 :            :                  * Outermost items comprise a match
    3664                 :            :                  * specification of type OUTER.
    3665                 :            :                  */
    3666                 :          0 :                 ctx->match_spec = ctx->match_spec_outer;
    3667                 :            : 
    3668                 :            :                 /* Outermost items use "ENC" EFX MAE field IDs. */
    3669                 :          0 :                 ctx->field_ids_remap = field_ids_remap_to_encap;
    3670                 :            : 
    3671                 :          0 :                 rc = efx_mae_outer_rule_recirc_id_set(ctx->match_spec,
    3672                 :            :                                                       recirc_id);
    3673         [ #  # ]:          0 :                 if (rc != 0) {
    3674                 :          0 :                         return rte_flow_error_set(error, rc,
    3675                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3676                 :            :                                         "OR: failed to initialise RECIRC_ID");
    3677                 :            :                 }
    3678                 :            : 
    3679         [ #  # ]:          0 :                 if (!request_ct)
    3680                 :            :                         break;
    3681                 :            : 
    3682                 :          0 :                 rc = efx_mae_outer_rule_do_ct_set(ctx->match_spec_outer);
    3683         [ #  # ]:          0 :                 if (rc != 0) {
    3684                 :          0 :                         return rte_flow_error_set(error, rc,
    3685                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3686                 :            :                                         "OR: failed to request CT lookup");
    3687                 :            :                 }
    3688                 :            :                 break;
    3689                 :          0 :         case SFC_FT_RULE_SWITCH:
    3690                 :            :                 /* Outermost items -> "ENC" match fields in the action rule. */
    3691                 :          0 :                 ctx->field_ids_remap = field_ids_remap_to_encap;
    3692                 :          0 :                 ctx->match_spec = ctx->match_spec_action;
    3693                 :            : 
    3694                 :            :                 /* No own outer rule; match on TUNNEL OR's RECIRC_ID is used. */
    3695                 :          0 :                 ctx->encap_type = EFX_TUNNEL_PROTOCOL_NONE;
    3696                 :          0 :                 break;
    3697                 :            :         default:
    3698                 :            :                 SFC_ASSERT(B_FALSE);
    3699                 :            :                 break;
    3700                 :            :         }
    3701                 :            : 
    3702                 :            :         return 0;
    3703                 :            : }
    3704                 :            : 
    3705                 :            : static void
    3706                 :            : sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
    3707                 :            :                               struct sfc_mae_parse_ctx *ctx)
    3708                 :            : {
    3709                 :          0 :         if (ctx->match_spec_outer != NULL)
    3710                 :          0 :                 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
    3711                 :            : }
    3712                 :            : 
    3713                 :            : static int
    3714                 :          0 : sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
    3715                 :            :                            const struct rte_flow_item pattern[],
    3716                 :            :                            struct rte_flow *flow,
    3717                 :            :                            struct sfc_mae_action_rule_ctx *action_rule_ctx,
    3718                 :            :                            struct rte_flow_error *error)
    3719                 :            : {
    3720   [ #  #  #  # ]:          0 :         struct sfc_flow_spec_mae *spec = &flow->spec.mae;
    3721                 :            :         struct sfc_mae_outer_rule **outer_rulep;
    3722                 :            :         struct sfc_mae_parse_ctx ctx_mae;
    3723                 :            :         unsigned int priority_shift = 0;
    3724                 :            :         struct sfc_flow_parse_ctx ctx;
    3725                 :            :         int rc;
    3726                 :            : 
    3727                 :            :         memset(&ctx_mae, 0, sizeof(ctx_mae));
    3728                 :          0 :         ctx_mae.ft_rule_type = spec->ft_rule_type;
    3729                 :          0 :         ctx_mae.internal = flow->internal;
    3730                 :          0 :         ctx_mae.priority = spec->priority;
    3731                 :          0 :         ctx_mae.ft_ctx = spec->ft_ctx;
    3732                 :          0 :         ctx_mae.sa = sa;
    3733                 :            : 
    3734                 :          0 :         outer_rulep = &action_rule_ctx->outer_rule;
    3735                 :            : 
    3736   [ #  #  #  # ]:          0 :         switch (ctx_mae.ft_rule_type) {
    3737                 :          0 :         case SFC_FT_RULE_TUNNEL:
    3738                 :            :                 /*
    3739                 :            :                  * By design, this flow should be represented solely by the
    3740                 :            :                  * outer rule. But the HW/FW hasn't got support for setting
    3741                 :            :                  * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
    3742                 :            :                  * does it support outer rule counters. As a workaround, an
    3743                 :            :                  * action rule of lower priority is used to do the job.
    3744                 :            :                  */
    3745                 :            :                 priority_shift = 1;
    3746                 :            : 
    3747                 :            :                 /* FALLTHROUGH */
    3748                 :          0 :         case SFC_FT_RULE_SWITCH:
    3749         [ #  # ]:          0 :                 if (ctx_mae.priority != 0) {
    3750                 :            :                         /*
    3751                 :            :                          * Because of the above workaround, deny the use
    3752                 :            :                          * of priorities to TUNNEL and SWITCH rules.
    3753                 :            :                          */
    3754                 :          0 :                         rc = rte_flow_error_set(error, ENOTSUP,
    3755                 :            :                                 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
    3756                 :            :                                 "FT: priorities are not supported");
    3757                 :          0 :                         goto fail_priority_check;
    3758                 :            :                 }
    3759                 :            : 
    3760                 :            :                 /* FALLTHROUGH */
    3761                 :            :         case SFC_FT_RULE_NONE:
    3762                 :          0 :                 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
    3763                 :            :                                              spec->priority + priority_shift,
    3764                 :            :                                              &ctx_mae.match_spec_action);
    3765         [ #  # ]:          0 :                 if (rc != 0) {
    3766                 :          0 :                         rc = rte_flow_error_set(error, rc,
    3767                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3768                 :            :                                 "AR: failed to initialise the match specification");
    3769                 :          0 :                         goto fail_init_match_spec_action;
    3770                 :            :                 }
    3771                 :            :                 break;
    3772                 :          0 :         default:
    3773                 :          0 :                 rc = rte_flow_error_set(error, EINVAL,
    3774                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    3775                 :            :                         "FT: unexpected rule type");
    3776                 :          0 :                 goto fail_unexpected_ft_rule_type;
    3777                 :            :         }
    3778                 :            : 
    3779                 :            :         /*
    3780                 :            :          * As a preliminary setting, assume that there is no encapsulation
    3781                 :            :          * in the pattern. That is, pattern items are about to comprise a
    3782                 :            :          * match specification of type ACTION and use non-encap. field IDs.
    3783                 :            :          *
    3784                 :            :          * sfc_mae_rule_encap_parse_init() below may override this.
    3785                 :            :          */
    3786                 :          0 :         ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE;
    3787                 :          0 :         ctx_mae.match_spec = ctx_mae.match_spec_action;
    3788                 :          0 :         ctx_mae.field_ids_remap = field_ids_no_remap;
    3789                 :          0 :         ctx_mae.pattern = pattern;
    3790                 :            : 
    3791                 :          0 :         ctx.type = SFC_FLOW_PARSE_CTX_MAE;
    3792                 :          0 :         ctx.mae = &ctx_mae;
    3793                 :            : 
    3794                 :          0 :         rc = sfc_mae_rule_encap_parse_init(sa, &ctx_mae, error);
    3795         [ #  # ]:          0 :         if (rc != 0)
    3796                 :          0 :                 goto fail_encap_parse_init;
    3797                 :            : 
    3798                 :            :         /*
    3799                 :            :          * sfc_mae_rule_encap_parse_init() may have detected tunnel offload
    3800                 :            :          * SWITCH rule. Remember its properties for later use.
    3801                 :            :          */
    3802                 :          0 :         spec->ft_rule_type = ctx_mae.ft_rule_type;
    3803                 :          0 :         spec->ft_ctx = ctx_mae.ft_ctx;
    3804                 :            : 
    3805                 :          0 :         rc = sfc_flow_parse_pattern(sa, sfc_flow_items, RTE_DIM(sfc_flow_items),
    3806                 :            :                                     ctx_mae.pattern, &ctx, error);
    3807         [ #  # ]:          0 :         if (rc != 0)
    3808                 :          0 :                 goto fail_parse_pattern;
    3809                 :            : 
    3810                 :          0 :         rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error);
    3811         [ #  # ]:          0 :         if (rc != 0)
    3812                 :          0 :                 goto fail_process_pattern_data;
    3813                 :            : 
    3814                 :          0 :         rc = sfc_mae_rule_process_ct(sa, &ctx_mae, action_rule_ctx,
    3815                 :            :                                      spec, error);
    3816         [ #  # ]:          0 :         if (rc != 0)
    3817                 :          0 :                 goto fail_process_ct;
    3818                 :            : 
    3819                 :          0 :         rc = sfc_mae_rule_process_outer(sa, &ctx_mae, outer_rulep, error);
    3820         [ #  # ]:          0 :         if (rc != 0)
    3821                 :          0 :                 goto fail_process_outer;
    3822                 :            : 
    3823   [ #  #  #  # ]:          0 :         if (ctx_mae.match_spec_action != NULL &&
    3824                 :          0 :             !efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
    3825                 :          0 :                 rc = rte_flow_error_set(error, ENOTSUP,
    3826                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, NULL,
    3827                 :            :                                         "Inconsistent pattern");
    3828                 :          0 :                 goto fail_validate_match_spec_action;
    3829                 :            :         }
    3830                 :            : 
    3831                 :          0 :         action_rule_ctx->match_spec = ctx_mae.match_spec_action;
    3832                 :            : 
    3833                 :          0 :         return 0;
    3834                 :            : 
    3835                 :            : fail_validate_match_spec_action:
    3836                 :          0 : fail_process_outer:
    3837                 :          0 : fail_process_ct:
    3838                 :          0 : fail_process_pattern_data:
    3839         [ #  # ]:          0 : fail_parse_pattern:
    3840                 :            :         sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
    3841                 :            : 
    3842                 :          0 : fail_encap_parse_init:
    3843         [ #  # ]:          0 :         if (ctx_mae.match_spec_action != NULL)
    3844                 :          0 :                 efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
    3845                 :            : 
    3846                 :          0 : fail_unexpected_ft_rule_type:
    3847                 :            : fail_init_match_spec_action:
    3848                 :            : fail_priority_check:
    3849                 :            :         return rc;
    3850                 :            : }
    3851                 :            : 
    3852                 :            : static int
    3853                 :          0 : sfc_mae_rule_parse_action_set_mac(struct sfc_adapter *sa,
    3854                 :            :                                   enum sfc_mae_mac_addr_type type,
    3855                 :            :                                   const struct rte_flow_action_set_mac *conf,
    3856                 :            :                                   struct sfc_mae_aset_ctx *ctx,
    3857                 :            :                                   struct rte_flow_error *error)
    3858                 :            : {
    3859                 :            :         struct sfc_mae_mac_addr **mac_addrp;
    3860                 :            :         int rc;
    3861                 :            : 
    3862         [ #  # ]:          0 :         if (conf == NULL) {
    3863                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    3864                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    3865                 :            :                                 "the MAC address entry definition is NULL");
    3866                 :            :         }
    3867                 :            : 
    3868      [ #  #  # ]:          0 :         switch (type) {
    3869                 :          0 :         case SFC_MAE_MAC_ADDR_DST:
    3870                 :          0 :                 rc = efx_mae_action_set_populate_set_dst_mac(ctx->spec);
    3871                 :          0 :                 mac_addrp = &ctx->dst_mac;
    3872                 :          0 :                 break;
    3873                 :          0 :         case SFC_MAE_MAC_ADDR_SRC:
    3874                 :          0 :                 rc = efx_mae_action_set_populate_set_src_mac(ctx->spec);
    3875                 :          0 :                 mac_addrp = &ctx->src_mac;
    3876                 :          0 :                 break;
    3877                 :            :         default:
    3878                 :            :                 rc = EINVAL;
    3879                 :            :                 break;
    3880                 :            :         }
    3881                 :            : 
    3882         [ #  # ]:          0 :         if (rc != 0)
    3883                 :          0 :                 goto error;
    3884                 :            : 
    3885                 :          0 :         *mac_addrp = sfc_mae_mac_addr_attach(sa, conf->mac_addr);
    3886         [ #  # ]:          0 :         if (*mac_addrp != NULL)
    3887                 :            :                 return 0;
    3888                 :            : 
    3889                 :          0 :         rc = sfc_mae_mac_addr_add(sa, conf->mac_addr, mac_addrp);
    3890         [ #  # ]:          0 :         if (rc != 0)
    3891                 :          0 :                 goto error;
    3892                 :            : 
    3893                 :            :         return 0;
    3894                 :            : 
    3895                 :          0 : error:
    3896                 :          0 :         return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
    3897                 :            :                                   NULL, "failed to request set MAC action");
    3898                 :            : }
    3899                 :            : 
    3900                 :            : /*
    3901                 :            :  * An action supported by MAE may correspond to a bundle of RTE flow actions,
    3902                 :            :  * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP.
    3903                 :            :  * That is, related RTE flow actions need to be tracked as parts of a whole
    3904                 :            :  * so that they can be combined into a single action and submitted to MAE
    3905                 :            :  * representation of a given rule's action set.
    3906                 :            :  *
    3907                 :            :  * Each RTE flow action provided by an application gets classified as
    3908                 :            :  * one belonging to some bundle type. If an action is not supposed to
    3909                 :            :  * belong to any bundle, or if this action is END, it is described as
    3910                 :            :  * one belonging to a dummy bundle of type EMPTY.
    3911                 :            :  *
    3912                 :            :  * A currently tracked bundle will be submitted if a repeating
    3913                 :            :  * action or an action of different bundle type follows.
    3914                 :            :  */
    3915                 :            : 
    3916                 :            : enum sfc_mae_actions_bundle_type {
    3917                 :            :         SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
    3918                 :            :         SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
    3919                 :            :         SFC_MAE_ACTIONS_BUNDLE_NAT_DST,
    3920                 :            :         SFC_MAE_ACTIONS_BUNDLE_NAT_SRC,
    3921                 :            : };
    3922                 :            : 
    3923                 :            : struct sfc_mae_actions_bundle {
    3924                 :            :         enum sfc_mae_actions_bundle_type        type;
    3925                 :            : 
    3926                 :            :         /* Indicates actions already tracked by the current bundle */
    3927                 :            :         uint64_t                                actions_mask;
    3928                 :            : 
    3929                 :            :         /* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */
    3930                 :            :         rte_be16_t                              vlan_push_tpid;
    3931                 :            :         rte_be16_t                              vlan_push_tci;
    3932                 :            : };
    3933                 :            : 
    3934                 :            : /*
    3935                 :            :  * Combine configuration of RTE flow actions tracked by the bundle into a
    3936                 :            :  * single action and submit the result to MAE action set specification.
    3937                 :            :  * Do nothing in the case of dummy action bundle.
    3938                 :            :  */
    3939                 :            : static int
    3940                 :          0 : sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
    3941                 :            :                               struct sfc_flow_spec_mae *flow_spec,
    3942                 :            :                               bool ct, efx_mae_actions_t *spec)
    3943                 :            : {
    3944                 :            :         int rc = 0;
    3945                 :            : 
    3946   [ #  #  #  # ]:          0 :         switch (bundle->type) {
    3947                 :            :         case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
    3948                 :            :                 break;
    3949                 :          0 :         case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH:
    3950                 :          0 :                 rc = efx_mae_action_set_populate_vlan_push(
    3951                 :          0 :                         spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
    3952                 :          0 :                 break;
    3953                 :          0 :         case SFC_MAE_ACTIONS_BUNDLE_NAT_DST:
    3954                 :          0 :                 flow_spec->ct_resp.nat.dir_is_dst = true;
    3955                 :            :                 /* FALLTHROUGH */
    3956                 :          0 :         case SFC_MAE_ACTIONS_BUNDLE_NAT_SRC:
    3957   [ #  #  #  # ]:          0 :                 if (ct && flow_spec->ct_resp.nat.ip_le != 0 &&
    3958         [ #  # ]:          0 :                     flow_spec->ct_resp.nat.port_le != 0)
    3959                 :          0 :                         rc = efx_mae_action_set_populate_nat(spec);
    3960                 :            :                 else
    3961                 :            :                         rc = EINVAL;
    3962                 :            :                 break;
    3963                 :            :         default:
    3964                 :            :                 SFC_ASSERT(B_FALSE);
    3965                 :            :                 break;
    3966                 :            :         }
    3967                 :            : 
    3968                 :          0 :         return rc;
    3969                 :            : }
    3970                 :            : 
    3971                 :            : /*
    3972                 :            :  * Given the type of the next RTE flow action in the line, decide
    3973                 :            :  * whether a new bundle is about to start, and, if this is the case,
    3974                 :            :  * submit and reset the current bundle.
    3975                 :            :  */
    3976                 :            : static int
    3977                 :          0 : sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
    3978                 :            :                             struct sfc_mae_actions_bundle *bundle,
    3979                 :            :                             struct sfc_flow_spec_mae *flow_spec,
    3980                 :            :                             efx_mae_actions_t *spec, bool ct,
    3981                 :            :                             struct rte_flow_error *error)
    3982                 :            : {
    3983                 :            :         enum sfc_mae_actions_bundle_type bundle_type_new;
    3984                 :            :         int rc;
    3985                 :            : 
    3986   [ #  #  #  # ]:          0 :         switch (action->type) {
    3987                 :            :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    3988                 :            :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    3989                 :            :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    3990                 :            :                 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
    3991                 :            :                 break;
    3992                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    3993                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    3994                 :            :                 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_DST;
    3995                 :          0 :                 break;
    3996                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    3997                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    3998                 :            :                 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_NAT_SRC;
    3999                 :          0 :                 break;
    4000                 :          0 :         default:
    4001                 :            :                 /*
    4002                 :            :                  * Self-sufficient actions, including END, are handled in this
    4003                 :            :                  * case. No checks for unsupported actions are needed here
    4004                 :            :                  * because parsing doesn't occur at this point.
    4005                 :            :                  */
    4006                 :            :                 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY;
    4007                 :          0 :                 break;
    4008                 :            :         }
    4009                 :            : 
    4010         [ #  # ]:          0 :         if (bundle_type_new != bundle->type ||
    4011         [ #  # ]:          0 :             (bundle->actions_mask & (1ULL << action->type)) != 0) {
    4012                 :          0 :                 rc = sfc_mae_actions_bundle_submit(bundle, flow_spec, ct, spec);
    4013         [ #  # ]:          0 :                 if (rc != 0)
    4014                 :          0 :                         goto fail_submit;
    4015                 :            : 
    4016                 :            :                 memset(bundle, 0, sizeof(*bundle));
    4017                 :            :         }
    4018                 :            : 
    4019                 :          0 :         bundle->type = bundle_type_new;
    4020                 :            : 
    4021                 :          0 :         return 0;
    4022                 :            : 
    4023                 :            : fail_submit:
    4024                 :          0 :         return rte_flow_error_set(error, rc,
    4025                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4026                 :            :                         "Failed to request the (group of) action(s)");
    4027                 :            : }
    4028                 :            : 
    4029                 :            : static void
    4030                 :            : sfc_mae_rule_parse_action_nat_addr(const struct rte_flow_action_set_ipv4 *conf,
    4031                 :            :                                    uint32_t *nat_addr_le)
    4032                 :            : {
    4033                 :          0 :         *nat_addr_le = rte_bswap32(conf->ipv4_addr);
    4034                 :          0 : }
    4035                 :            : 
    4036                 :            : static void
    4037                 :            : sfc_mae_rule_parse_action_nat_port(const struct rte_flow_action_set_tp *conf,
    4038                 :            :                                    uint16_t *nat_port_le)
    4039                 :            : {
    4040                 :          0 :         *nat_port_le = rte_bswap16(conf->port);
    4041                 :          0 : }
    4042                 :            : 
    4043                 :            : static void
    4044                 :            : sfc_mae_rule_parse_action_of_push_vlan(
    4045                 :            :                             const struct rte_flow_action_of_push_vlan *conf,
    4046                 :            :                             struct sfc_mae_actions_bundle *bundle)
    4047                 :            : {
    4048                 :          0 :         bundle->vlan_push_tpid = conf->ethertype;
    4049                 :          0 : }
    4050                 :            : 
    4051                 :            : static void
    4052                 :            : sfc_mae_rule_parse_action_of_set_vlan_vid(
    4053                 :            :                             const struct rte_flow_action_of_set_vlan_vid *conf,
    4054                 :            :                             struct sfc_mae_actions_bundle *bundle)
    4055                 :            : {
    4056                 :          0 :         bundle->vlan_push_tci |= (conf->vlan_vid &
    4057                 :            :                                   rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t)));
    4058                 :          0 : }
    4059                 :            : 
    4060                 :            : static void
    4061                 :            : sfc_mae_rule_parse_action_of_set_vlan_pcp(
    4062                 :            :                             const struct rte_flow_action_of_set_vlan_pcp *conf,
    4063                 :            :                             struct sfc_mae_actions_bundle *bundle)
    4064                 :            : {
    4065                 :          0 :         uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp &
    4066                 :          0 :                                            RTE_LEN2MASK(3, uint8_t)) << 13;
    4067                 :            : 
    4068                 :          0 :         bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
    4069                 :          0 : }
    4070                 :            : 
    4071                 :            : struct sfc_mae_parsed_item {
    4072                 :            :         const struct rte_flow_item      *item;
    4073                 :            :         size_t                          proto_header_ofst;
    4074                 :            :         size_t                          proto_header_size;
    4075                 :            : };
    4076                 :            : 
    4077                 :            : /*
    4078                 :            :  * For each 16-bit word of the given header, override
    4079                 :            :  * bits enforced by the corresponding 16-bit mask.
    4080                 :            :  */
    4081                 :            : static void
    4082                 :          0 : sfc_mae_header_force_item_masks(uint8_t *header_buf,
    4083                 :            :                                 const struct sfc_mae_parsed_item *parsed_items,
    4084                 :            :                                 unsigned int nb_parsed_items)
    4085                 :            : {
    4086                 :            :         unsigned int item_idx;
    4087                 :            : 
    4088         [ #  # ]:          0 :         for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) {
    4089                 :            :                 const struct sfc_mae_parsed_item *parsed_item;
    4090                 :            :                 const struct rte_flow_item *item;
    4091                 :            :                 size_t proto_header_size;
    4092                 :            :                 size_t ofst;
    4093                 :            : 
    4094                 :          0 :                 parsed_item = &parsed_items[item_idx];
    4095                 :          0 :                 proto_header_size = parsed_item->proto_header_size;
    4096                 :          0 :                 item = parsed_item->item;
    4097                 :            : 
    4098         [ #  # ]:          0 :                 for (ofst = 0; ofst < proto_header_size;
    4099                 :          0 :                      ofst += sizeof(rte_be16_t)) {
    4100                 :          0 :                         rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst);
    4101                 :            :                         const rte_be16_t *w_maskp;
    4102                 :            :                         const rte_be16_t *w_specp;
    4103                 :            : 
    4104                 :          0 :                         w_maskp = RTE_PTR_ADD(item->mask, ofst);
    4105                 :          0 :                         w_specp = RTE_PTR_ADD(item->spec, ofst);
    4106                 :            : 
    4107                 :          0 :                         *wp &= ~(*w_maskp);
    4108                 :          0 :                         *wp |= (*w_specp & *w_maskp);
    4109                 :            :                 }
    4110                 :            : 
    4111                 :          0 :                 header_buf += proto_header_size;
    4112                 :            :         }
    4113                 :          0 : }
    4114                 :            : 
    4115                 :            : #define SFC_IPV4_TTL_DEF        0x40
    4116                 :            : #define SFC_IPV6_VTC_FLOW_DEF   0x60000000
    4117                 :            : #define SFC_IPV6_HOP_LIMITS_DEF 0xff
    4118                 :            : #define SFC_VXLAN_FLAGS_DEF     0x08000000
    4119                 :            : 
    4120                 :            : static int
    4121                 :          0 : sfc_mae_rule_parse_action_vxlan_encap(
    4122                 :            :                             struct sfc_mae *mae,
    4123                 :            :                             const struct rte_flow_action_vxlan_encap *conf,
    4124                 :            :                             efx_mae_actions_t *spec,
    4125                 :            :                             struct rte_flow_error *error)
    4126                 :          0 : {
    4127                 :            :         struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
    4128                 :          0 :         struct rte_flow_item *pattern = conf->definition;
    4129                 :          0 :         uint8_t *buf = bounce_eh->buf;
    4130                 :            : 
    4131                 :            :         /* This array will keep track of non-VOID pattern items. */
    4132                 :            :         struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ +
    4133                 :            :                                                 2 /* VLAN tags */ +
    4134                 :            :                                                 1 /* IPv4 or IPv6 */ +
    4135                 :            :                                                 1 /* UDP */ +
    4136                 :            :                                                 1 /* VXLAN */];
    4137                 :            :         unsigned int nb_parsed_items = 0;
    4138                 :            : 
    4139                 :            :         size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type);
    4140                 :          0 :         uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr),
    4141                 :            :                                   sizeof(struct rte_ipv6_hdr))];
    4142                 :            :         struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf;
    4143                 :            :         struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf;
    4144                 :            :         struct rte_vxlan_hdr *vxlan = NULL;
    4145                 :            :         struct rte_udp_hdr *udp = NULL;
    4146                 :            :         unsigned int nb_vlan_tags = 0;
    4147                 :            :         size_t next_proto_ofst = 0;
    4148                 :            :         size_t ethertype_ofst = 0;
    4149                 :            :         uint64_t exp_items;
    4150                 :            :         int rc;
    4151                 :            : 
    4152         [ #  # ]:          0 :         if (pattern == NULL) {
    4153                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    4154                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4155                 :            :                                 "The encap. header definition is NULL");
    4156                 :            :         }
    4157                 :            : 
    4158                 :          0 :         bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN;
    4159                 :          0 :         bounce_eh->size = 0;
    4160                 :            : 
    4161                 :            :         /*
    4162                 :            :          * Process pattern items and remember non-VOID ones.
    4163                 :            :          * Defer applying masks until after the complete header
    4164                 :            :          * has been built from the pattern items.
    4165                 :            :          */
    4166                 :            :         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH);
    4167                 :            : 
    4168         [ #  # ]:          0 :         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) {
    4169                 :            :                 struct sfc_mae_parsed_item *parsed_item;
    4170                 :          0 :                 const uint64_t exp_items_extra_vlan[] = {
    4171                 :            :                         RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0
    4172                 :            :                 };
    4173                 :            :                 size_t proto_header_size;
    4174                 :            :                 rte_be16_t *ethertypep;
    4175                 :            :                 uint8_t *next_protop;
    4176                 :            :                 uint8_t *buf_cur;
    4177                 :            : 
    4178         [ #  # ]:          0 :                 if (pattern->spec == NULL) {
    4179                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4180                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4181                 :            :                                         "NULL item spec in the encap. header");
    4182                 :            :                 }
    4183                 :            : 
    4184         [ #  # ]:          0 :                 if (pattern->mask == NULL) {
    4185                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4186                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4187                 :            :                                         "NULL item mask in the encap. header");
    4188                 :            :                 }
    4189                 :            : 
    4190         [ #  # ]:          0 :                 if (pattern->last != NULL) {
    4191                 :            :                         /* This is not a match pattern, so disallow range. */
    4192                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4193                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4194                 :            :                                         "Range item in the encap. header");
    4195                 :            :                 }
    4196                 :            : 
    4197         [ #  # ]:          0 :                 if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) {
    4198                 :            :                         /* Handle VOID separately, for clarity. */
    4199                 :          0 :                         continue;
    4200                 :            :                 }
    4201                 :            : 
    4202         [ #  # ]:          0 :                 if ((exp_items & RTE_BIT64(pattern->type)) == 0) {
    4203                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    4204                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4205                 :            :                                         "Unexpected item in the encap. header");
    4206                 :            :                 }
    4207                 :            : 
    4208                 :            :                 parsed_item = &parsed_items[nb_parsed_items];
    4209                 :          0 :                 buf_cur = buf + bounce_eh->size;
    4210                 :            : 
    4211   [ #  #  #  #  :          0 :                 switch (pattern->type) {
                #  #  # ]
    4212                 :            :                 case RTE_FLOW_ITEM_TYPE_ETH:
    4213                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH,
    4214                 :            :                                                exp_items);
    4215                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth,
    4216                 :            :                                                   hdr) != 0);
    4217                 :            : 
    4218                 :            :                         proto_header_size = sizeof(struct rte_ether_hdr);
    4219                 :            : 
    4220                 :            :                         ethertype_ofst = eth_ethertype_ofst;
    4221                 :            : 
    4222                 :            :                         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) |
    4223                 :            :                                     RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
    4224                 :            :                                     RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
    4225                 :            :                         break;
    4226                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VLAN:
    4227                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN,
    4228                 :            :                                                exp_items);
    4229                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan,
    4230                 :            :                                                   hdr) != 0);
    4231                 :            : 
    4232                 :            :                         proto_header_size = sizeof(struct rte_vlan_hdr);
    4233                 :            : 
    4234                 :          0 :                         ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst);
    4235                 :          0 :                         *ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ);
    4236                 :            : 
    4237                 :          0 :                         ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
    4238                 :          0 :                         *ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN);
    4239                 :            : 
    4240                 :          0 :                         ethertype_ofst =
    4241                 :            :                             bounce_eh->size +
    4242                 :            :                             offsetof(struct rte_vlan_hdr, eth_proto);
    4243                 :            : 
    4244                 :            :                         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
    4245                 :            :                                     RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
    4246                 :          0 :                         exp_items |= exp_items_extra_vlan[nb_vlan_tags];
    4247                 :            : 
    4248                 :          0 :                         ++nb_vlan_tags;
    4249                 :          0 :                         break;
    4250                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    4251                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4,
    4252                 :            :                                                exp_items);
    4253                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4,
    4254                 :            :                                                   hdr) != 0);
    4255                 :            : 
    4256                 :            :                         proto_header_size = sizeof(struct rte_ipv4_hdr);
    4257                 :            : 
    4258                 :          0 :                         ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
    4259                 :          0 :                         *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4);
    4260                 :            : 
    4261                 :          0 :                         next_proto_ofst =
    4262                 :            :                             bounce_eh->size +
    4263                 :            :                             offsetof(struct rte_ipv4_hdr, next_proto_id);
    4264                 :            : 
    4265                 :            :                         ipv4 = (struct rte_ipv4_hdr *)buf_cur;
    4266                 :            : 
    4267                 :            :                         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
    4268                 :          0 :                         break;
    4269                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    4270                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6,
    4271                 :            :                                                exp_items);
    4272                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6,
    4273                 :            :                                                   hdr) != 0);
    4274                 :            : 
    4275                 :            :                         proto_header_size = sizeof(struct rte_ipv6_hdr);
    4276                 :            : 
    4277                 :          0 :                         ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
    4278                 :          0 :                         *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6);
    4279                 :            : 
    4280                 :          0 :                         next_proto_ofst = bounce_eh->size +
    4281                 :            :                                           offsetof(struct rte_ipv6_hdr, proto);
    4282                 :            : 
    4283                 :            :                         ipv6 = (struct rte_ipv6_hdr *)buf_cur;
    4284                 :            : 
    4285                 :            :                         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
    4286                 :          0 :                         break;
    4287                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    4288                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP,
    4289                 :            :                                                exp_items);
    4290                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp,
    4291                 :            :                                                   hdr) != 0);
    4292                 :            : 
    4293                 :            :                         proto_header_size = sizeof(struct rte_udp_hdr);
    4294                 :            : 
    4295                 :          0 :                         next_protop = RTE_PTR_ADD(buf, next_proto_ofst);
    4296                 :          0 :                         *next_protop = IPPROTO_UDP;
    4297                 :            : 
    4298                 :            :                         udp = (struct rte_udp_hdr *)buf_cur;
    4299                 :            : 
    4300                 :            :                         exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN);
    4301                 :          0 :                         break;
    4302                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    4303                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN,
    4304                 :            :                                                exp_items);
    4305                 :            :                         RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan,
    4306                 :            :                                                   hdr) != 0);
    4307                 :            : 
    4308                 :            :                         proto_header_size = sizeof(struct rte_vxlan_hdr);
    4309                 :            : 
    4310                 :            :                         vxlan = (struct rte_vxlan_hdr *)buf_cur;
    4311                 :            : 
    4312                 :          0 :                         udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
    4313                 :          0 :                         udp->dgram_len = RTE_BE16(sizeof(*udp) +
    4314                 :            :                                                   sizeof(*vxlan));
    4315                 :          0 :                         udp->dgram_cksum = 0;
    4316                 :            : 
    4317                 :            :                         exp_items = 0;
    4318                 :          0 :                         break;
    4319                 :          0 :                 default:
    4320                 :          0 :                         return rte_flow_error_set(error, ENOTSUP,
    4321                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4322                 :            :                                         "Unknown item in the encap. header");
    4323                 :            :                 }
    4324                 :            : 
    4325         [ #  # ]:          0 :                 if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) {
    4326                 :          0 :                         return rte_flow_error_set(error, E2BIG,
    4327                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4328                 :            :                                         "The encap. header is too big");
    4329                 :            :                 }
    4330                 :            : 
    4331                 :            :                 if ((proto_header_size & 1) != 0) {
    4332                 :            :                         return rte_flow_error_set(error, EINVAL,
    4333                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4334                 :            :                                         "Odd layer size in the encap. header");
    4335                 :            :                 }
    4336                 :            : 
    4337         [ #  # ]:          0 :                 rte_memcpy(buf_cur, pattern->spec, proto_header_size);
    4338                 :          0 :                 bounce_eh->size += proto_header_size;
    4339                 :            : 
    4340                 :          0 :                 parsed_item->item = pattern;
    4341                 :          0 :                 parsed_item->proto_header_size = proto_header_size;
    4342                 :          0 :                 ++nb_parsed_items;
    4343                 :            :         }
    4344                 :            : 
    4345         [ #  # ]:          0 :         if (exp_items != 0) {
    4346                 :            :                 /* Parsing item VXLAN would have reset exp_items to 0. */
    4347                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4348                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
    4349                 :            :                                         "No item VXLAN in the encap. header");
    4350                 :            :         }
    4351                 :            : 
    4352                 :            :         /* One of the pointers (ipv4, ipv6) refers to a dummy area. */
    4353                 :          0 :         ipv4->version_ihl = RTE_IPV4_VHL_DEF;
    4354                 :          0 :         ipv4->time_to_live = SFC_IPV4_TTL_DEF;
    4355                 :          0 :         ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) +
    4356                 :            :                                       sizeof(*vxlan));
    4357                 :            :         /* The HW cannot compute this checksum. */
    4358                 :          0 :         ipv4->hdr_checksum = 0;
    4359                 :          0 :         ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
    4360                 :            : 
    4361                 :          0 :         ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF);
    4362                 :          0 :         ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF;
    4363                 :          0 :         ipv6->payload_len = udp->dgram_len;
    4364                 :            : 
    4365                 :          0 :         vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF);
    4366                 :            : 
    4367                 :            :         /* Take care of the masks. */
    4368                 :          0 :         sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items);
    4369                 :            : 
    4370         [ #  # ]:          0 :         if (spec == NULL)
    4371                 :            :                 return 0;
    4372                 :            : 
    4373                 :          0 :         rc = efx_mae_action_set_populate_encap(spec);
    4374         [ #  # ]:          0 :         if (rc != 0) {
    4375                 :          0 :                 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
    4376                 :            :                                 NULL, "failed to request action ENCAP");
    4377                 :            :         }
    4378                 :            : 
    4379                 :            :         return rc;
    4380                 :            : }
    4381                 :            : 
    4382                 :            : static int
    4383                 :          0 : sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
    4384                 :            :                                const struct rte_flow_action_mark *conf,
    4385                 :            :                                const struct sfc_flow_spec_mae *spec_mae,
    4386                 :            :                                efx_mae_actions_t *spec)
    4387                 :            : {
    4388                 :            :         int rc;
    4389                 :            : 
    4390         [ #  # ]:          0 :         if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    4391                 :            :                 /* Workaround. See sfc_flow_parse_rte_to_mae() */
    4392         [ #  # ]:          0 :         } else if (conf->id > SFC_FT_USER_MARK_MASK) {
    4393                 :          0 :                 sfc_err(sa, "the mark value is too large");
    4394                 :          0 :                 return EINVAL;
    4395                 :            :         }
    4396                 :            : 
    4397                 :          0 :         rc = efx_mae_action_set_populate_mark(spec, conf->id);
    4398         [ #  # ]:          0 :         if (rc != 0)
    4399                 :          0 :                 sfc_err(sa, "failed to request action MARK: %s", strerror(rc));
    4400                 :            : 
    4401                 :            :         return rc;
    4402                 :            : }
    4403                 :            : 
    4404                 :            : static int
    4405                 :          0 : sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
    4406                 :            :                                 const struct rte_flow_action_count *conf,
    4407                 :            :                                 efx_counter_type_t mae_counter_type,
    4408                 :            :                                 struct sfc_mae_counter **counterp,
    4409                 :            :                                 efx_mae_actions_t *spec)
    4410                 :            : {
    4411                 :          0 :         struct sfc_mae_counter counter_tmp = {};
    4412                 :            :         int rc;
    4413                 :            : 
    4414         [ #  # ]:          0 :         if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
    4415                 :          0 :                 sfc_err(sa,
    4416                 :            :                         "counter queue is not configured for COUNT action");
    4417                 :            :                 rc = EINVAL;
    4418                 :          0 :                 goto fail_counter_queue_uninit;
    4419                 :            :         }
    4420                 :            : 
    4421         [ #  # ]:          0 :         if (sfc_get_service_lcore(SOCKET_ID_ANY) == RTE_MAX_LCORE) {
    4422                 :            :                 rc = EINVAL;
    4423                 :          0 :                 goto fail_no_service_core;
    4424                 :            :         }
    4425                 :            : 
    4426         [ #  # ]:          0 :         if (*counterp != NULL) {
    4427                 :          0 :                 sfc_err(sa, "cannot request more than 1 action COUNT per flow");
    4428                 :            :                 rc = EINVAL;
    4429                 :          0 :                 goto fail_more_than_one;
    4430                 :            :         }
    4431                 :            : 
    4432         [ #  # ]:          0 :         if (spec != NULL) {
    4433                 :          0 :                 rc = efx_mae_action_set_populate_count(spec);
    4434         [ #  # ]:          0 :                 if (rc != 0) {
    4435                 :          0 :                         sfc_err(sa,
    4436                 :            :                                 "failed to populate counters in MAE action set: %s",
    4437                 :            :                                 rte_strerror(rc));
    4438                 :          0 :                         goto fail_populate_count;
    4439                 :            :                 }
    4440                 :            :         }
    4441                 :            : 
    4442         [ #  # ]:          0 :         if (conf != NULL) {
    4443                 :          0 :                 counter_tmp.rte_id_valid = true;
    4444                 :          0 :                 counter_tmp.rte_id = conf->id;
    4445                 :            :         }
    4446                 :            : 
    4447                 :          0 :         counter_tmp.type = mae_counter_type;
    4448                 :            : 
    4449                 :          0 :         return sfc_mae_counter_add(sa, &counter_tmp, counterp);
    4450                 :            : 
    4451                 :            :         return 0;
    4452                 :            : 
    4453                 :            : fail_populate_count:
    4454                 :            : fail_more_than_one:
    4455                 :            : fail_no_service_core:
    4456                 :            : fail_counter_queue_uninit:
    4457                 :            : 
    4458                 :            :         return rc;
    4459                 :            : }
    4460                 :            : 
    4461                 :            : static int
    4462                 :          0 : sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa, bool replayable_only,
    4463                 :            :                                    const struct rte_flow_action_handle *handle,
    4464                 :            :                                    enum sfc_ft_rule_type ft_rule_type,
    4465                 :            :                                    struct sfc_mae_aset_ctx *ctx,
    4466                 :            :                                    struct rte_flow_error *error)
    4467                 :            : {
    4468                 :            :         struct rte_flow_action_handle *entry;
    4469                 :            :         int rc;
    4470                 :            : 
    4471         [ #  # ]:          0 :         TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
    4472         [ #  # ]:          0 :                 if (entry == handle) {
    4473                 :            :                         bool replayable = false;
    4474                 :            : 
    4475                 :          0 :                         sfc_dbg(sa, "attaching to indirect_action=%p", entry);
    4476                 :            : 
    4477         [ #  # ]:          0 :                         switch (entry->type) {
    4478                 :          0 :                         case RTE_FLOW_ACTION_TYPE_COUNT:
    4479                 :            :                                 replayable = true;
    4480                 :          0 :                                 break;
    4481                 :            :                         default:
    4482                 :            :                                 break;
    4483                 :            :                         }
    4484                 :            : 
    4485         [ #  # ]:          0 :                         if (replayable_only && !replayable) {
    4486                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    4487                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4488                 :            :                                   "the indirect action handle cannot be used");
    4489                 :            :                         }
    4490                 :            : 
    4491      [ #  #  # ]:          0 :                         switch (entry->type) {
    4492                 :          0 :                         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    4493         [ #  # ]:          0 :                                 if (ctx->encap_header != NULL) {
    4494                 :          0 :                                         return rte_flow_error_set(error, EINVAL,
    4495                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4496                 :            :                                           "cannot have multiple actions VXLAN_ENCAP in one flow");
    4497                 :            :                                 }
    4498                 :            : 
    4499                 :          0 :                                 rc = efx_mae_action_set_populate_encap(ctx->spec);
    4500         [ #  # ]:          0 :                                 if (rc != 0) {
    4501                 :          0 :                                         return rte_flow_error_set(error, rc,
    4502                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4503                 :            :                                          "failed to add ENCAP to MAE action set");
    4504                 :            :                                 }
    4505                 :            : 
    4506                 :          0 :                                 ctx->encap_header = entry->encap_header;
    4507                 :          0 :                                 ++(ctx->encap_header->refcnt);
    4508                 :          0 :                                 break;
    4509                 :          0 :                         case RTE_FLOW_ACTION_TYPE_COUNT:
    4510   [ #  #  #  # ]:          0 :                                 if (!replayable_only && ctx->counter != NULL) {
    4511                 :            :                                         /*
    4512                 :            :                                          * Signal the caller to "replay" the action
    4513                 :            :                                          * set context and re-invoke this function.
    4514                 :            :                                          */
    4515                 :            :                                         return EEXIST;
    4516                 :            :                                 }
    4517                 :            : 
    4518         [ #  # ]:          0 :                                 if (ft_rule_type != SFC_FT_RULE_SWITCH &&
    4519         [ #  # ]:          0 :                                     entry->counter->ft_switch_hit_counter != NULL) {
    4520                 :          0 :                                         return rte_flow_error_set(error, EBUSY,
    4521                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4522                 :            :                                           "cannot use requested indirect counter as it is in use by incompatible offload");
    4523                 :            :                                 }
    4524                 :            : 
    4525                 :            :                                 SFC_ASSERT(ctx->counter == NULL);
    4526                 :            : 
    4527                 :          0 :                                 rc = efx_mae_action_set_populate_count(ctx->spec);
    4528   [ #  #  #  # ]:          0 :                                 if (rc != 0 && !ctx->counter_implicit) {
    4529                 :          0 :                                         return rte_flow_error_set(error, rc,
    4530                 :            :                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4531                 :            :                                          "failed to add COUNT to MAE action set");
    4532                 :            :                                 }
    4533                 :            : 
    4534                 :          0 :                                 ctx->counter_implicit = false;
    4535                 :          0 :                                 ctx->counter = entry->counter;
    4536                 :          0 :                                 ++(ctx->counter->refcnt);
    4537                 :          0 :                                 break;
    4538                 :            :                         default:
    4539                 :            :                                 SFC_ASSERT(B_FALSE);
    4540                 :            :                                 break;
    4541                 :            :                         }
    4542                 :            : 
    4543                 :          0 :                         return 0;
    4544                 :            :                 }
    4545                 :            :         }
    4546                 :            : 
    4547                 :          0 :         return rte_flow_error_set(error, ENOENT,
    4548                 :            :                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    4549                 :            :                                   "indirect action handle not found");
    4550                 :            : }
    4551                 :            : 
    4552                 :            : static int
    4553                 :          0 : sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
    4554                 :            :                                 const struct rte_flow_action_vf *vf_conf,
    4555                 :            :                                 efx_mae_actions_t *spec)
    4556                 :            : {
    4557                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
    4558                 :            :         efx_mport_sel_t mport;
    4559                 :            :         uint32_t vf;
    4560                 :            :         int rc;
    4561                 :            : 
    4562         [ #  # ]:          0 :         if (vf_conf == NULL)
    4563                 :            :                 vf = EFX_PCI_VF_INVALID;
    4564         [ #  # ]:          0 :         else if (vf_conf->original != 0)
    4565                 :          0 :                 vf = encp->enc_vf;
    4566                 :            :         else
    4567                 :          0 :                 vf = vf_conf->id;
    4568                 :            : 
    4569                 :          0 :         rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport);
    4570         [ #  # ]:          0 :         if (rc != 0) {
    4571         [ #  # ]:          0 :                 sfc_err(sa, "failed to convert PF %u VF %d to m-port: %s",
    4572                 :            :                         encp->enc_pf, (vf != EFX_PCI_VF_INVALID) ? (int)vf : -1,
    4573                 :            :                         strerror(rc));
    4574                 :          0 :                 return rc;
    4575                 :            :         }
    4576                 :            : 
    4577                 :          0 :         rc = efx_mae_action_set_populate_deliver(spec, &mport);
    4578         [ #  # ]:          0 :         if (rc != 0) {
    4579                 :          0 :                 sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
    4580                 :            :                         mport.sel, strerror(rc));
    4581                 :            :         }
    4582                 :            : 
    4583                 :            :         return rc;
    4584                 :            : }
    4585                 :            : 
    4586                 :            : static int
    4587         [ #  # ]:          0 : sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
    4588                 :            :                                   const struct rte_flow_action_port_id *conf,
    4589                 :            :                                   efx_mae_actions_t *spec)
    4590                 :            : {
    4591                 :            :         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
    4592                 :            :         struct sfc_mae *mae = &sa->mae;
    4593                 :            :         unsigned int type_mask;
    4594                 :            :         efx_mport_sel_t mport;
    4595                 :            :         uint16_t port_id;
    4596                 :            :         int rc;
    4597                 :            : 
    4598         [ #  # ]:          0 :         if (conf->id > UINT16_MAX)
    4599                 :            :                 return EOVERFLOW;
    4600                 :            : 
    4601         [ #  # ]:          0 :         port_id = (conf->original != 0) ? sas->port_id : conf->id;
    4602                 :            : 
    4603                 :            :         type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
    4604                 :            : 
    4605                 :          0 :         rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
    4606                 :            :                                              port_id, type_mask, &mport);
    4607         [ #  # ]:          0 :         if (rc != 0) {
    4608                 :          0 :                 sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
    4609                 :            :                         port_id, strerror(rc));
    4610                 :          0 :                 return rc;
    4611                 :            :         }
    4612                 :            : 
    4613                 :          0 :         rc = efx_mae_action_set_populate_deliver(spec, &mport);
    4614         [ #  # ]:          0 :         if (rc != 0) {
    4615                 :          0 :                 sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
    4616                 :            :                         mport.sel, strerror(rc));
    4617                 :            :         }
    4618                 :            : 
    4619                 :            :         return rc;
    4620                 :            : }
    4621                 :            : 
    4622                 :            : static int
    4623                 :          0 : sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
    4624                 :            :                 const struct rte_flow_action_ethdev *conf,
    4625                 :            :                 unsigned int type_mask, efx_mae_actions_t *spec)
    4626                 :            : {
    4627                 :            :         struct sfc_mae *mae = &sa->mae;
    4628                 :            :         efx_mport_sel_t mport;
    4629                 :            :         int rc;
    4630                 :            : 
    4631                 :          0 :         rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
    4632                 :          0 :                                              conf->port_id, type_mask, &mport);
    4633         [ #  # ]:          0 :         if (rc != 0) {
    4634                 :          0 :                 sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
    4635                 :            :                         conf->port_id, strerror(rc));
    4636                 :          0 :                 return rc;
    4637                 :            :         }
    4638                 :            : 
    4639                 :          0 :         rc = efx_mae_action_set_populate_deliver(spec, &mport);
    4640         [ #  # ]:          0 :         if (rc != 0) {
    4641                 :          0 :                 sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
    4642                 :            :                         mport.sel, strerror(rc));
    4643                 :            :         }
    4644                 :            : 
    4645                 :            :         return rc;
    4646                 :            : }
    4647                 :            : 
    4648                 :            : static int
    4649                 :          0 : sfc_mae_rule_parse_action_represented_port(struct sfc_adapter *sa,
    4650                 :            :                 const struct rte_flow_action_ethdev *conf,
    4651                 :            :                 efx_mae_actions_t *spec)
    4652                 :            : {
    4653                 :            :         struct sfc_mae *mae = &sa->mae;
    4654                 :            :         efx_mport_sel_t mport;
    4655                 :            :         int rc;
    4656                 :            : 
    4657                 :          0 :         rc = sfc_mae_switch_get_entity_mport(mae->switch_domain_id,
    4658                 :          0 :                                              conf->port_id, &mport);
    4659         [ #  # ]:          0 :         if (rc != 0) {
    4660                 :          0 :                 sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
    4661                 :            :                         conf->port_id, strerror(rc));
    4662                 :          0 :                 return rc;
    4663                 :            :         }
    4664                 :            : 
    4665                 :          0 :         rc = efx_mae_action_set_populate_deliver(spec, &mport);
    4666         [ #  # ]:          0 :         if (rc != 0) {
    4667                 :          0 :                 sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
    4668                 :            :                         mport.sel, strerror(rc));
    4669                 :            :         }
    4670                 :            : 
    4671                 :            :         return rc;
    4672                 :            : }
    4673                 :            : 
    4674                 :            : static const char * const action_names[] = {
    4675                 :            :         [RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = "VXLAN_DECAP",
    4676                 :            :         [RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = "OF_POP_VLAN",
    4677                 :            :         [RTE_FLOW_ACTION_TYPE_SET_MAC_DST] = "SET_MAC_DST",
    4678                 :            :         [RTE_FLOW_ACTION_TYPE_SET_MAC_SRC] = "SET_MAC_SRC",
    4679                 :            :         [RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL] = "OF_DEC_NW_TTL",
    4680                 :            :         [RTE_FLOW_ACTION_TYPE_DEC_TTL] = "DEC_TTL",
    4681                 :            :         [RTE_FLOW_ACTION_TYPE_SET_IPV4_DST] = "SET_IPV4_DST",
    4682                 :            :         [RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC] = "SET_IPV4_SRC",
    4683                 :            :         [RTE_FLOW_ACTION_TYPE_SET_TP_DST] = "SET_TP_DST",
    4684                 :            :         [RTE_FLOW_ACTION_TYPE_SET_TP_SRC] = "SET_TP_SRC",
    4685                 :            :         [RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
    4686                 :            :         [RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
    4687                 :            :         [RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
    4688                 :            :         [RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
    4689                 :            :         [RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT",
    4690                 :            :         [RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT",
    4691                 :            :         [RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
    4692                 :            :         [RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
    4693                 :            :         [RTE_FLOW_ACTION_TYPE_PF] = "PF",
    4694                 :            :         [RTE_FLOW_ACTION_TYPE_VF] = "VF",
    4695                 :            :         [RTE_FLOW_ACTION_TYPE_PORT_ID] = "PORT_ID",
    4696                 :            :         [RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR] = "PORT_REPRESENTOR",
    4697                 :            :         [RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = "REPRESENTED_PORT",
    4698                 :            :         [RTE_FLOW_ACTION_TYPE_DROP] = "DROP",
    4699                 :            :         [RTE_FLOW_ACTION_TYPE_JUMP] = "JUMP",
    4700                 :            : };
    4701                 :            : 
    4702                 :            : static void sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh);
    4703                 :            : 
    4704                 :            : static int sfc_mae_process_encap_header(struct sfc_adapter *sa,
    4705                 :            :                                 const struct sfc_mae_bounce_eh *bounce_eh,
    4706                 :            :                                 struct sfc_mae_encap_header **encap_headerp);
    4707                 :            : 
    4708                 :            : static int
    4709                 :          0 : sfc_mae_aset_ctx_replay(struct sfc_adapter *sa, struct sfc_mae_aset_ctx **ctxp)
    4710                 :            : {
    4711                 :            :         const struct sfc_mae_aset_ctx *ctx_cur;
    4712                 :            :         struct sfc_mae_aset_ctx *ctx_new;
    4713                 :            :         struct sfc_mae *mae = &sa->mae;
    4714                 :            :         int rc;
    4715                 :            : 
    4716                 :            :         RTE_BUILD_BUG_ON(EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES == 0);
    4717                 :            : 
    4718                 :            :         /* Check the number of complete action set contexts. */
    4719         [ #  # ]:          0 :         if (mae->nb_bounce_asets >= (EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES - 1))
    4720                 :            :                 return ENOSPC;
    4721                 :            : 
    4722                 :          0 :         ctx_cur = &mae->bounce_aset_ctxs[mae->nb_bounce_asets];
    4723                 :            : 
    4724                 :          0 :         ++(mae->nb_bounce_asets);
    4725                 :            : 
    4726                 :          0 :         ctx_new = &mae->bounce_aset_ctxs[mae->nb_bounce_asets];
    4727                 :            : 
    4728                 :          0 :         *ctx_new = *ctx_cur;
    4729                 :          0 :         ctx_new->counter = NULL;
    4730                 :          0 :         ctx_new->fate_set = false;
    4731                 :            : 
    4732                 :            :         /*
    4733                 :            :          * This clones the action set specification and drops
    4734                 :            :          * actions COUNT and DELIVER from the clone so that
    4735                 :            :          * such can be added to it by later action parsing.
    4736                 :            :          */
    4737                 :          0 :         rc = efx_mae_action_set_replay(sa->nic, ctx_cur->spec, &ctx_new->spec);
    4738         [ #  # ]:          0 :         if (rc != 0)
    4739                 :            :                 return rc;
    4740                 :            : 
    4741                 :          0 :         *ctxp = ctx_new;
    4742                 :            : 
    4743                 :          0 :         return 0;
    4744                 :            : }
    4745                 :            : 
    4746                 :            : static int
    4747                 :          0 : sfc_mae_rule_parse_action_rc(struct sfc_adapter *sa,
    4748                 :            :                              struct sfc_mae_actions_bundle *bundle,
    4749                 :            :                              const struct rte_flow_action *action,
    4750                 :            :                              struct rte_flow_error *error,
    4751                 :            :                              int rc, bool custom_error)
    4752                 :            : {
    4753         [ #  # ]:          0 :         if (rc == 0) {
    4754                 :          0 :                 bundle->actions_mask |= (1ULL << action->type);
    4755         [ #  # ]:          0 :         } else if (!custom_error) {
    4756         [ #  # ]:          0 :                 if (action->type < RTE_DIM(action_names)) {
    4757                 :          0 :                         const char *action_name = action_names[action->type];
    4758                 :            : 
    4759         [ #  # ]:          0 :                         if (action_name != NULL) {
    4760                 :          0 :                                 sfc_err(sa, "action %s was rejected: %s",
    4761                 :            :                                         action_name, strerror(rc));
    4762                 :            :                         }
    4763                 :            :                 }
    4764                 :          0 :                 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
    4765                 :            :                                 NULL, "Failed to request the action");
    4766                 :            :         }
    4767                 :            : 
    4768                 :          0 :         return rc;
    4769                 :            : }
    4770                 :            : 
    4771                 :            : static int
    4772                 :          0 : sfc_mae_rule_parse_action_replayable(struct sfc_adapter *sa,
    4773                 :            :                                      const struct rte_flow *flow,
    4774                 :            :                                      struct sfc_mae_actions_bundle *bundle,
    4775                 :            :                                      const struct rte_flow_action *action,
    4776                 :            :                                      struct sfc_mae_aset_ctx *ctx,
    4777                 :            :                                      struct rte_flow_error *error)
    4778                 :            : {
    4779                 :            :         const struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
    4780                 :          0 :         efx_mae_actions_t *spec = ctx->spec;
    4781                 :            :         unsigned int switch_port_type_mask;
    4782                 :            :         bool custom_error = false;
    4783                 :            :         bool new_fate_set = false;
    4784                 :            :         bool need_replay = false;
    4785                 :            :         int rc;
    4786                 :            : 
    4787                 :            :         /*
    4788                 :            :          * Decide whether the current action set context is
    4789                 :            :          * complete. If yes, "replay" it = go to a new one.
    4790                 :            :          */
    4791      [ #  #  # ]:          0 :         switch (action->type) {
    4792                 :          0 :         case RTE_FLOW_ACTION_TYPE_INDIRECT:
    4793   [ #  #  #  # ]:          0 :                 if (ctx->fate_set || ctx->counter != NULL)
    4794                 :            :                         need_replay = true;
    4795                 :            :                 break;
    4796                 :          0 :         case RTE_FLOW_ACTION_TYPE_PF:
    4797                 :            :         case RTE_FLOW_ACTION_TYPE_VF:
    4798                 :            :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
    4799                 :            :         case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
    4800                 :            :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    4801                 :            :                 /* FALLTHROUGH */
    4802                 :            :         case RTE_FLOW_ACTION_TYPE_DROP:
    4803         [ #  # ]:          0 :                 if (ctx->fate_set)
    4804                 :            :                         need_replay = true;
    4805                 :            : 
    4806                 :            :                 new_fate_set = true;
    4807                 :            :                 break;
    4808                 :          0 :         default:
    4809                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    4810                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4811                 :            :                                 "Unsupported action");
    4812                 :            :         }
    4813                 :            : 
    4814                 :            :         if (need_replay) {
    4815         [ #  # ]:          0 :                 if (spec_mae->ft_rule_type != SFC_FT_RULE_NONE) {
    4816                 :          0 :                         return rte_flow_error_set(error, EINVAL,
    4817                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4818                 :            :                                 "no support for packet replay in tunnel offload");
    4819                 :            :                 }
    4820                 :            : 
    4821         [ #  # ]:          0 :                 if (!ctx->fate_set) {
    4822                 :            :                         /*
    4823                 :            :                          * With regard to replayable actions, the current action
    4824                 :            :                          * set is only needed to hold one of the counters.
    4825                 :            :                          * That is, it does not have a fate action, so
    4826                 :            :                          * add one to suppress undesired delivery.
    4827                 :            :                          */
    4828                 :          0 :                         rc = efx_mae_action_set_populate_drop(spec);
    4829         [ #  # ]:          0 :                         if (rc != 0) {
    4830                 :          0 :                                 return rte_flow_error_set(error, rc,
    4831                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4832                 :            :                                         "failed to auto-add action DROP");
    4833                 :            :                         }
    4834                 :            :                 }
    4835                 :            : 
    4836                 :          0 :                 rc = sfc_mae_aset_ctx_replay(sa, &ctx);
    4837         [ #  # ]:          0 :                 if (rc != 0) {
    4838                 :          0 :                         return rte_flow_error_set(error, rc,
    4839                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    4840                 :            :                                 "failed to replay the action set");
    4841                 :            :                 }
    4842                 :            : 
    4843                 :          0 :                 spec = ctx->spec;
    4844                 :            :         }
    4845                 :            : 
    4846                 :          0 :         ctx->fate_set = new_fate_set;
    4847                 :            : 
    4848   [ #  #  #  #  :          0 :         switch (action->type) {
             #  #  #  # ]
    4849                 :          0 :         case RTE_FLOW_ACTION_TYPE_INDIRECT:
    4850                 :          0 :                 rc = sfc_mae_rule_parse_action_indirect(sa, true, action->conf,
    4851                 :          0 :                                                         spec_mae->ft_rule_type,
    4852                 :            :                                                         ctx, error);
    4853                 :            :                 custom_error = true;
    4854                 :          0 :                 break;
    4855                 :          0 :         case RTE_FLOW_ACTION_TYPE_PF:
    4856                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF,
    4857                 :            :                                        bundle->actions_mask);
    4858                 :          0 :                 rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
    4859                 :          0 :                 break;
    4860                 :          0 :         case RTE_FLOW_ACTION_TYPE_VF:
    4861                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF,
    4862                 :            :                                        bundle->actions_mask);
    4863                 :          0 :                 rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
    4864                 :          0 :                 break;
    4865                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
    4866                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID,
    4867                 :            :                                        bundle->actions_mask);
    4868                 :          0 :                 rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec);
    4869                 :          0 :                 break;
    4870                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
    4871                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
    4872                 :            :                                        bundle->actions_mask);
    4873                 :            : 
    4874                 :            :                 switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
    4875                 :            : 
    4876         [ #  # ]:          0 :                 if (flow->internal) {
    4877                 :            :                         switch_port_type_mask |=
    4878                 :            :                                         1U << SFC_MAE_SWITCH_PORT_REPRESENTOR;
    4879                 :            :                 }
    4880                 :            : 
    4881                 :          0 :                 rc = sfc_mae_rule_parse_action_port_representor(sa,
    4882                 :          0 :                                 action->conf, switch_port_type_mask, spec);
    4883                 :          0 :                 break;
    4884                 :          0 :         case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
    4885                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
    4886                 :            :                                        bundle->actions_mask);
    4887                 :          0 :                 rc = sfc_mae_rule_parse_action_represented_port(sa,
    4888                 :          0 :                                 action->conf, spec);
    4889                 :          0 :                 break;
    4890                 :          0 :         case RTE_FLOW_ACTION_TYPE_DROP:
    4891                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
    4892                 :            :                                        bundle->actions_mask);
    4893                 :          0 :                 rc = efx_mae_action_set_populate_drop(spec);
    4894                 :          0 :                 break;
    4895                 :            :         default:
    4896                 :            :                 SFC_ASSERT(B_FALSE);
    4897                 :            :                 break;
    4898                 :            :         }
    4899                 :            : 
    4900                 :          0 :         return sfc_mae_rule_parse_action_rc(sa, bundle, action, error,
    4901                 :            :                                             rc, custom_error);
    4902                 :            : }
    4903                 :            : 
    4904                 :            : static int
    4905                 :          0 : sfc_mae_rule_parse_action(struct sfc_adapter *sa,
    4906                 :            :                           const struct rte_flow_action *action,
    4907                 :            :                           struct rte_flow *flow, bool ct,
    4908                 :            :                           struct sfc_mae_actions_bundle *bundle,
    4909                 :            :                           struct rte_flow_error *error)
    4910                 :            : {
    4911                 :          0 :         struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
    4912                 :          0 :         const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
    4913                 :            :         efx_counter_type_t mae_counter_type = EFX_COUNTER_TYPE_ACTION;
    4914                 :          0 :         const uint64_t rx_metadata = sa->negotiated_rx_metadata;
    4915                 :            :         struct sfc_mae_counter **counterp;
    4916                 :            :         bool non_replayable_found = true;
    4917                 :          0 :         struct sfc_mae *mae = &sa->mae;
    4918                 :            :         struct sfc_mae_aset_ctx *ctx;
    4919                 :            :         efx_mae_actions_t *spec_ptr;
    4920                 :            :         bool custom_error = B_FALSE;
    4921                 :            :         efx_mae_actions_t *spec;
    4922                 :            :         int rc = 0;
    4923                 :            : 
    4924                 :            :         /* Check the number of complete action set contexts. */
    4925         [ #  # ]:          0 :         if (mae->nb_bounce_asets > (EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES - 1)) {
    4926                 :          0 :                 return sfc_mae_rule_parse_action_rc(sa, bundle, action, error,
    4927                 :            :                                                     ENOSPC, custom_error);
    4928                 :            :         }
    4929                 :            : 
    4930                 :          0 :         ctx = &mae->bounce_aset_ctxs[mae->nb_bounce_asets];
    4931                 :          0 :         counterp = &ctx->counter;
    4932                 :          0 :         spec = ctx->spec;
    4933                 :            :         spec_ptr = spec;
    4934                 :            : 
    4935         [ #  # ]:          0 :         if (ct) {
    4936                 :            :                 mae_counter_type = EFX_COUNTER_TYPE_CONNTRACK;
    4937                 :          0 :                 counterp = &spec_mae->ct_counter;
    4938                 :            :                 spec_ptr = NULL;
    4939                 :            :         }
    4940                 :            : 
    4941   [ #  #  #  # ]:          0 :         if (mae->nb_bounce_asets != 0 || ctx->fate_set) {
    4942                 :            :                 /*
    4943                 :            :                  * When at least one delivery action has been encountered,
    4944                 :            :                  * non-replayable actions (packet edits, for instance)
    4945                 :            :                  * will be turned down.
    4946                 :            :                  */
    4947                 :          0 :                 return sfc_mae_rule_parse_action_replayable(sa, flow, bundle,
    4948                 :            :                                                             action, ctx, error);
    4949                 :            :         }
    4950                 :            : 
    4951   [ #  #  #  #  :          0 :         switch (action->type) {
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    4952                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
    4953                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
    4954                 :            :                                        bundle->actions_mask);
    4955         [ #  # ]:          0 :                 if (outer_rule == NULL ||
    4956         [ #  # ]:          0 :                     outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN)
    4957                 :            :                         rc = EINVAL;
    4958                 :            :                 else
    4959                 :          0 :                         rc = efx_mae_action_set_populate_decap(spec);
    4960                 :            :                 break;
    4961                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
    4962                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
    4963                 :            :                                        bundle->actions_mask);
    4964                 :          0 :                 rc = efx_mae_action_set_populate_vlan_pop(spec);
    4965                 :          0 :                 break;
    4966                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    4967                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_MAC_DST,
    4968                 :            :                                        bundle->actions_mask);
    4969                 :          0 :                 rc = sfc_mae_rule_parse_action_set_mac(sa, SFC_MAE_MAC_ADDR_DST,
    4970                 :          0 :                                                        action->conf, ctx,
    4971                 :            :                                                        error);
    4972                 :            :                 custom_error = B_TRUE;
    4973                 :          0 :                 break;
    4974                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
    4975                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_MAC_SRC,
    4976                 :            :                                        bundle->actions_mask);
    4977                 :          0 :                 rc = sfc_mae_rule_parse_action_set_mac(sa, SFC_MAE_MAC_ADDR_SRC,
    4978                 :          0 :                                                        action->conf, ctx,
    4979                 :            :                                                        error);
    4980                 :            :                 custom_error = B_TRUE;
    4981                 :          0 :                 break;
    4982                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL:
    4983                 :            :         case RTE_FLOW_ACTION_TYPE_DEC_TTL:
    4984                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL,
    4985                 :            :                                        bundle->actions_mask);
    4986                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DEC_TTL,
    4987                 :            :                                        bundle->actions_mask);
    4988                 :          0 :                 rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
    4989                 :          0 :                 break;
    4990                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
    4991                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
    4992                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_DST,
    4993                 :            :                                        bundle->actions_mask);
    4994                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC,
    4995                 :            :                                        bundle->actions_mask);
    4996         [ #  # ]:          0 :                 sfc_mae_rule_parse_action_nat_addr(action->conf,
    4997                 :            :                                         &spec_mae->ct_resp.nat.ip_le);
    4998                 :            :                 break;
    4999                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    5000                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
    5001                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_DST,
    5002                 :            :                                        bundle->actions_mask);
    5003                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_SET_TP_SRC,
    5004                 :            :                                        bundle->actions_mask);
    5005         [ #  # ]:          0 :                 sfc_mae_rule_parse_action_nat_port(action->conf,
    5006                 :            :                                                 &spec_mae->ct_resp.nat.port_le);
    5007                 :            :                 break;
    5008                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
    5009                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
    5010                 :            :                                        bundle->actions_mask);
    5011                 :          0 :                 sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle);
    5012                 :            :                 break;
    5013                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
    5014                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
    5015                 :            :                                        bundle->actions_mask);
    5016                 :          0 :                 sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle);
    5017                 :            :                 break;
    5018                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
    5019                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
    5020                 :            :                                        bundle->actions_mask);
    5021         [ #  # ]:          0 :                 sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
    5022                 :            :                 break;
    5023                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    5024                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,
    5025                 :            :                                        bundle->actions_mask);
    5026                 :            : 
    5027                 :            :                 /* Cleanup after previous encap. header bounce buffer usage. */
    5028                 :            :                 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
    5029                 :            : 
    5030                 :          0 :                 rc = sfc_mae_rule_parse_action_vxlan_encap(mae, action->conf,
    5031                 :            :                                                            spec, error);
    5032         [ #  # ]:          0 :                 if (rc == 0) {
    5033                 :          0 :                         rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh,
    5034                 :            :                                                           &ctx->encap_header);
    5035                 :            :                 } else {
    5036                 :            :                         custom_error = true;
    5037                 :            :                 }
    5038                 :            :                 break;
    5039                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    5040                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
    5041                 :            :                                        bundle->actions_mask);
    5042                 :          0 :                 rc = sfc_mae_rule_parse_action_count(sa, action->conf,
    5043                 :            :                                                      mae_counter_type,
    5044                 :            :                                                      counterp, spec_ptr);
    5045                 :          0 :                 break;
    5046                 :          0 :         case RTE_FLOW_ACTION_TYPE_INDIRECT:
    5047                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT,
    5048                 :            :                                        bundle->actions_mask);
    5049                 :          0 :                 rc = sfc_mae_rule_parse_action_indirect(sa, false, action->conf,
    5050                 :            :                                                         spec_mae->ft_rule_type,
    5051                 :            :                                                         ctx, error);
    5052         [ #  # ]:          0 :                 if (rc == EEXIST) {
    5053                 :            :                         /* Handle the action as a replayable one below. */
    5054                 :            :                         non_replayable_found = false;
    5055                 :            :                 }
    5056                 :            :                 custom_error = B_TRUE;
    5057                 :            :                 break;
    5058                 :          0 :         case RTE_FLOW_ACTION_TYPE_FLAG:
    5059                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
    5060                 :            :                                        bundle->actions_mask);
    5061         [ #  # ]:          0 :                 if ((rx_metadata & RTE_ETH_RX_METADATA_USER_FLAG) != 0) {
    5062                 :          0 :                         rc = efx_mae_action_set_populate_flag(spec);
    5063                 :            :                 } else {
    5064                 :          0 :                         rc = rte_flow_error_set(error, ENOTSUP,
    5065                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    5066                 :            :                                                 action,
    5067                 :            :                                                 "flag delivery has not been negotiated");
    5068                 :            :                         custom_error = B_TRUE;
    5069                 :            :                 }
    5070                 :            :                 break;
    5071                 :          0 :         case RTE_FLOW_ACTION_TYPE_MARK:
    5072                 :            :                 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
    5073                 :            :                                        bundle->actions_mask);
    5074         [ #  # ]:          0 :                 if ((rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0 ||
    5075         [ #  # ]:          0 :                     spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    5076                 :          0 :                         rc = sfc_mae_rule_parse_action_mark(sa, action->conf,
    5077                 :            :                                                             spec_mae, spec);
    5078                 :            :                 } else {
    5079                 :          0 :                         rc = rte_flow_error_set(error, ENOTSUP,
    5080                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION,
    5081                 :            :                                                 action,
    5082                 :            :                                                 "mark delivery has not been negotiated");
    5083                 :            :                         custom_error = B_TRUE;
    5084                 :            :                 }
    5085                 :            :                 break;
    5086                 :          0 :         case RTE_FLOW_ACTION_TYPE_JUMP:
    5087         [ #  # ]:          0 :                 if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    5088                 :            :                         /* Workaround. See sfc_flow_parse_rte_to_mae() */
    5089                 :            :                         break;
    5090                 :            :                 }
    5091                 :            :                 /* FALLTHROUGH */
    5092                 :            :         default:
    5093                 :            :                 non_replayable_found = false;
    5094                 :            :         }
    5095                 :            : 
    5096         [ #  # ]:          0 :         if (non_replayable_found) {
    5097                 :          0 :                 return sfc_mae_rule_parse_action_rc(sa, bundle, action, error,
    5098                 :            :                                                     rc, custom_error);
    5099                 :            :         }
    5100                 :            : 
    5101                 :          0 :         return sfc_mae_rule_parse_action_replayable(sa, flow, bundle,
    5102                 :            :                                                     action, ctx, error);
    5103                 :            : }
    5104                 :            : 
    5105                 :            : static void
    5106                 :            : sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh)
    5107                 :            : {
    5108                 :          0 :         bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE;
    5109                 :            : }
    5110                 :            : 
    5111                 :            : static int
    5112                 :          0 : sfc_mae_process_encap_header(struct sfc_adapter *sa,
    5113                 :            :                              const struct sfc_mae_bounce_eh *bounce_eh,
    5114                 :            :                              struct sfc_mae_encap_header **encap_headerp)
    5115                 :            : {
    5116         [ #  # ]:          0 :         if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) {
    5117                 :            :                 encap_headerp = NULL;
    5118                 :            :                 return 0;
    5119                 :            :         }
    5120                 :            : 
    5121                 :          0 :         *encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh);
    5122         [ #  # ]:          0 :         if (*encap_headerp != NULL)
    5123                 :            :                 return 0;
    5124                 :            : 
    5125                 :          0 :         return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
    5126                 :            : }
    5127                 :            : 
    5128                 :            : static int
    5129                 :          0 : sfc_mae_rule_process_replay(struct sfc_adapter *sa,
    5130                 :            :                             struct sfc_mae_action_rule_ctx *action_rule_ctx)
    5131                 :            : {
    5132                 :            :         struct sfc_mae_action_set *base_aset;
    5133                 :            :         struct sfc_mae_action_set **asetp;
    5134                 :            :         struct sfc_mae *mae = &sa->mae;
    5135                 :            :         struct sfc_mae_aset_ctx *ctx;
    5136                 :            :         unsigned int i;
    5137                 :            :         unsigned int j;
    5138                 :            :         int rc;
    5139                 :            : 
    5140         [ #  # ]:          0 :         if (mae->nb_bounce_asets == 1)
    5141                 :            :                 return 0;
    5142                 :            : 
    5143                 :          0 :         mae->bounce_aset_ptrs[0] = action_rule_ctx->action_set;
    5144                 :            :         base_aset = mae->bounce_aset_ptrs[0];
    5145                 :            : 
    5146         [ #  # ]:          0 :         for (i = 1; i < mae->nb_bounce_asets; ++i) {
    5147                 :          0 :                 asetp = &mae->bounce_aset_ptrs[i];
    5148                 :          0 :                 ctx = &mae->bounce_aset_ctxs[i];
    5149                 :            : 
    5150                 :          0 :                 *asetp = sfc_mae_action_set_attach(sa, ctx);
    5151         [ #  # ]:          0 :                 if (*asetp != NULL) {
    5152                 :          0 :                         efx_mae_action_set_spec_fini(sa->nic, ctx->spec);
    5153                 :          0 :                         sfc_mae_counter_del(sa, ctx->counter);
    5154                 :          0 :                         continue;
    5155                 :            :                 }
    5156                 :            : 
    5157                 :          0 :                 rc = sfc_mae_action_set_add(sa, ctx, asetp);
    5158         [ #  # ]:          0 :                 if (rc != 0)
    5159                 :          0 :                         goto fail_action_set_add;
    5160                 :            : 
    5161         [ #  # ]:          0 :                 if (base_aset->encap_header != NULL)
    5162                 :          0 :                         ++(base_aset->encap_header->refcnt);
    5163                 :            : 
    5164         [ #  # ]:          0 :                 if (base_aset->dst_mac_addr != NULL)
    5165                 :          0 :                         ++(base_aset->dst_mac_addr->refcnt);
    5166                 :            : 
    5167         [ #  # ]:          0 :                 if (base_aset->src_mac_addr != NULL)
    5168                 :          0 :                         ++(base_aset->src_mac_addr->refcnt);
    5169                 :            :         }
    5170                 :            : 
    5171                 :          0 :         action_rule_ctx->action_set_list = sfc_mae_action_set_list_attach(sa);
    5172         [ #  # ]:          0 :         if (action_rule_ctx->action_set_list != NULL) {
    5173         [ #  # ]:          0 :                 for (i = 0; i < mae->nb_bounce_asets; ++i)
    5174                 :          0 :                         sfc_mae_action_set_del(sa, mae->bounce_aset_ptrs[i]);
    5175                 :            :         } else {
    5176                 :          0 :                 rc = sfc_mae_action_set_list_add(sa,
    5177                 :            :                                         &action_rule_ctx->action_set_list);
    5178         [ #  # ]:          0 :                 if (rc != 0)
    5179                 :          0 :                         goto fail_action_set_list_add;
    5180                 :            :         }
    5181                 :            : 
    5182                 :          0 :         action_rule_ctx->action_set = NULL;
    5183                 :            : 
    5184                 :          0 :         return 0;
    5185                 :            : 
    5186                 :            : fail_action_set_list_add:
    5187                 :          0 : fail_action_set_add:
    5188         [ #  # ]:          0 :         for (j = i; j < mae->nb_bounce_asets; ++j) {
    5189                 :          0 :                 ctx = &mae->bounce_aset_ctxs[j];
    5190                 :          0 :                 efx_mae_action_set_spec_fini(sa->nic, ctx->spec);
    5191                 :          0 :                 sfc_mae_counter_del(sa, ctx->counter);
    5192                 :            :         }
    5193                 :            : 
    5194         [ #  # ]:          0 :         while (--i > 0)
    5195                 :          0 :                 sfc_mae_action_set_del(sa, mae->bounce_aset_ptrs[i]);
    5196                 :            : 
    5197                 :            :         return rc;
    5198                 :            : }
    5199                 :            : 
    5200                 :            : static int
    5201                 :          0 : sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
    5202                 :            :                            const struct rte_flow_action actions[],
    5203                 :            :                            struct rte_flow *flow,
    5204                 :            :                            struct sfc_mae_action_rule_ctx *action_rule_ctx,
    5205                 :            :                            struct rte_flow_error *error)
    5206                 :            : {
    5207                 :          0 :         struct sfc_flow_spec_mae *spec_mae = &flow->spec.mae;
    5208                 :          0 :         struct sfc_mae_actions_bundle bundle = {0};
    5209                 :          0 :         bool ct = (action_rule_ctx->ct_mark != 0);
    5210                 :            :         const struct rte_flow_action *action;
    5211                 :            :         struct sfc_mae_aset_ctx *last_ctx;
    5212                 :            :         struct sfc_mae *mae = &sa->mae;
    5213                 :            :         struct sfc_mae_aset_ctx *ctx;
    5214                 :            :         int rc;
    5215                 :            : 
    5216                 :          0 :         rte_errno = 0;
    5217                 :            : 
    5218         [ #  # ]:          0 :         if (actions == NULL) {
    5219                 :          0 :                 return rte_flow_error_set(error, EINVAL,
    5220                 :            :                                 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
    5221                 :            :                                 "NULL actions");
    5222                 :            :         }
    5223                 :            : 
    5224                 :            :         /*
    5225                 :            :          * Cleanup after action parsing of the previous flow.
    5226                 :            :          *
    5227                 :            :          * This particular variable always points at the
    5228                 :            :          * 1st (base) action set context, which can hold
    5229                 :            :          * both non-replayable and replayable actions.
    5230                 :            :          */
    5231                 :          0 :         ctx = &mae->bounce_aset_ctxs[0];
    5232                 :            :         memset(ctx, 0, sizeof(*ctx));
    5233                 :          0 :         mae->nb_bounce_asets = 0;
    5234                 :            : 
    5235                 :          0 :         rc = efx_mae_action_set_spec_init(sa->nic, &ctx->spec);
    5236         [ #  # ]:          0 :         if (rc != 0)
    5237                 :          0 :                 goto fail_action_set_spec_init;
    5238                 :            : 
    5239         [ #  # ]:          0 :         if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) {
    5240                 :            :                 bool have_inline_action_count = false;
    5241                 :            : 
    5242                 :            :                 /* TUNNEL rules don't decapsulate packets. SWITCH rules do. */
    5243                 :          0 :                 rc = efx_mae_action_set_populate_decap(ctx->spec);
    5244         [ #  # ]:          0 :                 if (rc != 0)
    5245                 :          0 :                         goto fail_enforce_ft_decap;
    5246                 :            : 
    5247                 :            :                 for (action = actions;
    5248         [ #  # ]:          0 :                      action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
    5249         [ #  # ]:          0 :                         if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) {
    5250                 :            :                                 have_inline_action_count = true;
    5251                 :            :                                 break;
    5252                 :            :                         }
    5253                 :            :                 }
    5254                 :            : 
    5255   [ #  #  #  # ]:          0 :                 if (!have_inline_action_count &&
    5256                 :          0 :                     sfc_mae_counter_stream_enabled(sa)) {
    5257                 :            :                         /*
    5258                 :            :                          * The user might have opted not to have a counter here,
    5259                 :            :                          * but the counter should be enabled implicitly because
    5260                 :            :                          * packets hitting this rule contribute to the tunnel's
    5261                 :            :                          * total number of hits. See sfc_mae_counter_get().
    5262                 :            :                          */
    5263                 :          0 :                         rc = efx_mae_action_set_populate_count(ctx->spec);
    5264         [ #  # ]:          0 :                         if (rc != 0)
    5265                 :          0 :                                 goto fail_enforce_ft_count;
    5266                 :            : 
    5267                 :            :                         /*
    5268                 :            :                          * An action of type COUNT may come inlined (see above)
    5269                 :            :                          * or via a shareable handle (enclosed by an action of
    5270                 :            :                          * type INDIRECT). The latter is expensive to resolve
    5271                 :            :                          * here. For now assume an implicit counter is needed.
    5272                 :            :                          *
    5273                 :            :                          * But if the flow does come with an indirect counter,
    5274                 :            :                          * sfc_mae_rule_parse_action_indirect() will test the
    5275                 :            :                          * flag to cope with its "populate" failure. It will
    5276                 :            :                          * reset the flag so that below code can skip
    5277                 :            :                          * creating a software object for the counter.
    5278                 :            :                          */
    5279                 :          0 :                         ctx->counter_implicit = true;
    5280                 :            :                 }
    5281                 :            :         }
    5282                 :            : 
    5283                 :            :         for (action = actions;
    5284         [ #  # ]:          0 :              action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
    5285         [ #  # ]:          0 :                 if (mae->nb_bounce_asets == 0) {
    5286                 :          0 :                         rc = sfc_mae_actions_bundle_sync(action, &bundle,
    5287                 :            :                                                          spec_mae, ctx->spec,
    5288                 :            :                                                          ct, error);
    5289         [ #  # ]:          0 :                         if (rc != 0)
    5290                 :          0 :                                 goto fail_rule_parse_action;
    5291                 :            :                 }
    5292                 :            : 
    5293                 :          0 :                 rc = sfc_mae_rule_parse_action(sa, action, flow, ct,
    5294                 :            :                                                &bundle, error);
    5295         [ #  # ]:          0 :                 if (rc != 0)
    5296                 :          0 :                         goto fail_rule_parse_action;
    5297                 :            :         }
    5298                 :            : 
    5299         [ #  # ]:          0 :         if (mae->nb_bounce_asets == 0) {
    5300                 :          0 :                 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec_mae,
    5301                 :            :                                                  ctx->spec, ct, error);
    5302         [ #  # ]:          0 :                 if (rc != 0)
    5303                 :          0 :                         goto fail_rule_parse_action;
    5304                 :            :         }
    5305                 :            : 
    5306      [ #  #  # ]:          0 :         switch (spec_mae->ft_rule_type) {
    5307                 :            :         case SFC_FT_RULE_NONE:
    5308                 :            :                 break;
    5309                 :          0 :         case SFC_FT_RULE_TUNNEL:
    5310                 :            :                 /* Workaround. See sfc_flow_parse_rte_to_mae() */
    5311                 :          0 :                 rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, ctx->spec);
    5312         [ #  # ]:          0 :                 if (rc != 0)
    5313                 :          0 :                         goto fail_workaround_tunnel_delivery;
    5314                 :            : 
    5315         [ #  # ]:          0 :                 if (ctx->counter != NULL)
    5316                 :          0 :                         (ctx->counter)->ft_ctx = spec_mae->ft_ctx;
    5317                 :            : 
    5318                 :          0 :                 ctx->fate_set = true;
    5319                 :          0 :                 break;
    5320                 :          0 :         case SFC_FT_RULE_SWITCH:
    5321                 :            :                 /*
    5322                 :            :                  * Packets that go to the rule's AR have FT mark set (from
    5323                 :            :                  * the TUNNEL rule OR's RECIRC_ID). Reset the mark to zero.
    5324                 :            :                  */
    5325                 :          0 :                 efx_mae_action_set_populate_mark_reset(ctx->spec);
    5326                 :            : 
    5327         [ #  # ]:          0 :                 if (ctx->counter_implicit) {
    5328                 :            :                         /*
    5329                 :            :                          * Turns out the rule indeed does not have a user
    5330                 :            :                          * counter, so add one. The action bit in the
    5331                 :            :                          * action set specification has already been
    5332                 :            :                          * populated by the above preparse logic.
    5333                 :            :                          */
    5334                 :          0 :                         rc = sfc_mae_counter_add(sa, NULL, &ctx->counter);
    5335         [ #  # ]:          0 :                         if (rc != 0)
    5336                 :          0 :                                 goto fail_add_implicit_counter;
    5337                 :            :                 }
    5338                 :            : 
    5339         [ #  # ]:          0 :                 if (ctx->counter != NULL) {
    5340                 :            :                         struct sfc_mae_counter *counter = ctx->counter;
    5341                 :            : 
    5342         [ #  # ]:          0 :                         if (counter->indirect &&
    5343         [ #  # ]:          0 :                             counter->refcnt > 1 /* indirect handle */ +
    5344                 :          0 :                                               1 /* 1st use */ &&
    5345                 :          0 :                             counter->ft_switch_hit_counter !=
    5346         [ #  # ]:          0 :                             &spec_mae->ft_ctx->switch_hit_counter) {
    5347                 :          0 :                                 rc = rte_flow_error_set(error, EBUSY,
    5348                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5349                 :            :                                         "requested indirect counter is in use by another tunnel context");
    5350                 :          0 :                                 goto fail_check_indirect_counter_ft_ctx;
    5351                 :            :                         }
    5352                 :            : 
    5353                 :          0 :                         counter->ft_switch_hit_counter =
    5354                 :          0 :                                 &spec_mae->ft_ctx->switch_hit_counter;
    5355         [ #  # ]:          0 :                 } else if (sfc_mae_counter_stream_enabled(sa)) {
    5356                 :            :                         SFC_ASSERT(ct);
    5357                 :            : 
    5358                 :          0 :                         spec_mae->ct_counter->ft_switch_hit_counter =
    5359                 :          0 :                                 &spec_mae->ft_ctx->switch_hit_counter;
    5360                 :            :                 }
    5361                 :            :                 break;
    5362                 :          0 :         default:
    5363                 :            :                 SFC_ASSERT(B_FALSE);
    5364                 :            :         }
    5365                 :            : 
    5366                 :            :         SFC_ASSERT(mae->nb_bounce_asets < EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES);
    5367                 :          0 :         last_ctx = &mae->bounce_aset_ctxs[mae->nb_bounce_asets];
    5368                 :          0 :         ++(mae->nb_bounce_asets);
    5369                 :            : 
    5370         [ #  # ]:          0 :         if (!last_ctx->fate_set) {
    5371                 :          0 :                 rc = rte_flow_error_set(error, EINVAL,
    5372                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5373                 :            :                                         "no fate action found");
    5374                 :          0 :                 goto fail_check_fate_action;
    5375                 :            :         }
    5376                 :            : 
    5377                 :          0 :         action_rule_ctx->action_set = sfc_mae_action_set_attach(sa, ctx);
    5378         [ #  # ]:          0 :         if (action_rule_ctx->action_set != NULL) {
    5379                 :          0 :                 sfc_mae_counter_del(sa, ctx->counter);
    5380                 :          0 :                 sfc_mae_mac_addr_del(sa, ctx->src_mac);
    5381                 :          0 :                 sfc_mae_mac_addr_del(sa, ctx->dst_mac);
    5382                 :          0 :                 sfc_mae_encap_header_del(sa, ctx->encap_header);
    5383                 :          0 :                 efx_mae_action_set_spec_fini(sa->nic, ctx->spec);
    5384                 :            :         } else {
    5385                 :          0 :                 rc = sfc_mae_action_set_add(sa, ctx,
    5386                 :            :                                             &action_rule_ctx->action_set);
    5387         [ #  # ]:          0 :                 if (rc != 0)
    5388                 :          0 :                         goto fail_action_set_add;
    5389                 :            :         }
    5390                 :            : 
    5391                 :            :         memset(ctx, 0, sizeof(*ctx));
    5392                 :            : 
    5393                 :          0 :         rc = sfc_mae_rule_process_replay(sa, action_rule_ctx);
    5394         [ #  # ]:          0 :         if (rc != 0)
    5395                 :          0 :                 goto fail_rule_parse_replay;
    5396                 :            : 
    5397                 :            :         return 0;
    5398                 :            : 
    5399                 :            : fail_rule_parse_replay:
    5400                 :          0 :         sfc_mae_action_set_del(sa, action_rule_ctx->action_set);
    5401                 :            : 
    5402                 :          0 : fail_action_set_add:
    5403                 :          0 : fail_check_fate_action:
    5404                 :          0 : fail_check_indirect_counter_ft_ctx:
    5405                 :          0 : fail_add_implicit_counter:
    5406                 :          0 : fail_workaround_tunnel_delivery:
    5407                 :          0 : fail_rule_parse_action:
    5408                 :          0 :         sfc_mae_encap_header_del(sa, ctx->encap_header);
    5409                 :          0 :         sfc_mae_counter_del(sa, ctx->counter);
    5410                 :          0 :         sfc_mae_mac_addr_del(sa, ctx->src_mac);
    5411                 :          0 :         sfc_mae_mac_addr_del(sa, ctx->dst_mac);
    5412                 :            : 
    5413         [ #  # ]:          0 :         if (ctx->spec != NULL)
    5414                 :          0 :                 efx_mae_action_set_spec_fini(sa->nic, ctx->spec);
    5415                 :            : 
    5416                 :          0 : fail_enforce_ft_count:
    5417                 :          0 : fail_enforce_ft_decap:
    5418                 :          0 : fail_action_set_spec_init:
    5419   [ #  #  #  # ]:          0 :         if (rc > 0 && rte_errno == 0) {
    5420                 :          0 :                 rc = rte_flow_error_set(error, rc,
    5421                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5422                 :            :                         NULL, "Failed to process the action");
    5423                 :            :         }
    5424                 :            :         return rc;
    5425                 :            : }
    5426                 :            : 
    5427                 :            : int
    5428                 :          0 : sfc_mae_rule_parse(struct sfc_adapter *sa, const struct rte_flow_item pattern[],
    5429                 :            :                    const struct rte_flow_action actions[],
    5430                 :            :                    struct rte_flow *flow, struct rte_flow_error *error)
    5431                 :            : {
    5432                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    5433                 :          0 :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    5434                 :          0 :         struct sfc_mae_action_rule_ctx ctx = {};
    5435                 :            :         int rc;
    5436                 :            : 
    5437                 :            :         /*
    5438                 :            :          * If the flow is meant to be a TUNNEL rule in a FT context,
    5439                 :            :          * preparse its actions and save its properties in spec_mae.
    5440                 :            :          */
    5441                 :          0 :         rc = sfc_ft_tunnel_rule_detect(sa, actions, spec_mae, error);
    5442         [ #  # ]:          0 :         if (rc != 0)
    5443                 :          0 :                 goto fail;
    5444                 :            : 
    5445                 :          0 :         rc = sfc_mae_rule_parse_pattern(sa, pattern, flow, &ctx, error);
    5446         [ #  # ]:          0 :         if (rc != 0)
    5447                 :          0 :                 goto fail;
    5448                 :            : 
    5449                 :            :         if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    5450                 :            :                 /*
    5451                 :            :                  * By design, this flow should be represented solely by the
    5452                 :            :                  * outer rule. But the HW/FW hasn't got support for setting
    5453                 :            :                  * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
    5454                 :            :                  * does it support outer rule counters. As a workaround, an
    5455                 :            :                  * action rule of lower priority is used to do the job.
    5456                 :            :                  *
    5457                 :            :                  * So don't skip sfc_mae_rule_parse_actions() below.
    5458                 :            :                  */
    5459                 :            :         }
    5460                 :            : 
    5461                 :          0 :         spec_mae->outer_rule = ctx.outer_rule;
    5462                 :            : 
    5463                 :          0 :         rc = sfc_mae_rule_parse_actions(sa, actions, flow, &ctx, error);
    5464         [ #  # ]:          0 :         if (rc != 0)
    5465                 :          0 :                 goto fail;
    5466                 :            : 
    5467                 :          0 :         rc = sfc_mae_action_rule_attach(sa, &ctx, &spec_mae->action_rule,
    5468                 :            :                                         error);
    5469         [ #  # ]:          0 :         if (rc == 0) {
    5470                 :          0 :                 efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
    5471                 :          0 :                 sfc_mae_action_set_list_del(sa, ctx.action_set_list);
    5472                 :          0 :                 sfc_mae_action_set_del(sa, ctx.action_set);
    5473                 :          0 :                 sfc_mae_outer_rule_del(sa, ctx.outer_rule);
    5474         [ #  # ]:          0 :         } else if (rc == -ENOENT) {
    5475                 :          0 :                 rc = sfc_mae_action_rule_add(sa, &ctx, &spec_mae->action_rule);
    5476         [ #  # ]:          0 :                 if (rc != 0) {
    5477                 :          0 :                         rc = rte_flow_error_set(error, rc,
    5478                 :            :                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5479                 :            :                                         NULL, "AR: failed to add the entry");
    5480                 :          0 :                         goto fail;
    5481                 :            :                 }
    5482                 :            :         } else {
    5483                 :          0 :                 goto fail;
    5484                 :            :         }
    5485                 :            : 
    5486         [ #  # ]:          0 :         if (spec_mae->ft_ctx != NULL) {
    5487         [ #  # ]:          0 :                 if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL)
    5488                 :          0 :                         spec_mae->ft_ctx->tunnel_rule_is_set = B_TRUE;
    5489                 :            : 
    5490                 :          0 :                 ++(spec_mae->ft_ctx->refcnt);
    5491                 :            :         }
    5492                 :            : 
    5493                 :            :         return 0;
    5494                 :            : 
    5495                 :          0 : fail:
    5496         [ #  # ]:          0 :         if (ctx.match_spec != NULL)
    5497                 :          0 :                 efx_mae_match_spec_fini(sa->nic, ctx.match_spec);
    5498                 :            : 
    5499                 :          0 :         sfc_mae_action_set_list_del(sa, ctx.action_set_list);
    5500                 :          0 :         sfc_mae_action_set_del(sa, ctx.action_set);
    5501                 :          0 :         sfc_mae_outer_rule_del(sa, ctx.outer_rule);
    5502                 :            : 
    5503                 :            :         /* Reset these values to avoid confusing sfc_mae_flow_cleanup(). */
    5504                 :          0 :         spec_mae->ft_rule_type = SFC_FT_RULE_NONE;
    5505                 :          0 :         spec_mae->ft_ctx = NULL;
    5506                 :            : 
    5507                 :          0 :         return rc;
    5508                 :            : }
    5509                 :            : 
    5510                 :            : static bool
    5511                 :            : sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
    5512                 :            :                         const efx_mae_match_spec_t *left,
    5513                 :            :                         const efx_mae_match_spec_t *right)
    5514                 :            : {
    5515                 :            :         bool have_same_class;
    5516                 :            :         int rc;
    5517                 :            : 
    5518                 :          0 :         rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
    5519                 :            :                                            &have_same_class);
    5520                 :            : 
    5521   [ #  #  #  #  :          0 :         return (rc == 0) ? have_same_class : false;
             #  #  #  # ]
    5522                 :            : }
    5523                 :            : 
    5524                 :            : static int
    5525                 :          0 : sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
    5526                 :            :                                 struct sfc_mae_outer_rule *rule)
    5527                 :            : {
    5528                 :            :         struct sfc_mae_outer_rule *entry;
    5529                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc;
    5530                 :            :         struct sfc_mae *mae = &sa->mae;
    5531                 :            : 
    5532         [ #  # ]:          0 :         if (rule == NULL)
    5533                 :            :                 return 0;
    5534                 :            : 
    5535                 :            :         fw_rsrc = &rule->fw_rsrc;
    5536                 :            : 
    5537         [ #  # ]:          0 :         if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
    5538                 :            :                 /* An active rule is reused. It's class is wittingly valid. */
    5539                 :            :                 return 0;
    5540                 :            :         }
    5541                 :            : 
    5542         [ #  # ]:          0 :         TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules,
    5543                 :            :                               sfc_mae_outer_rules, entries) {
    5544                 :          0 :                 const efx_mae_match_spec_t *left = entry->match_spec;
    5545                 :          0 :                 const efx_mae_match_spec_t *right = rule->match_spec;
    5546                 :            : 
    5547         [ #  # ]:          0 :                 if (entry == rule)
    5548                 :          0 :                         continue;
    5549                 :            : 
    5550                 :            :                 if (sfc_mae_rules_class_cmp(sa, left, right))
    5551                 :          0 :                         return 0;
    5552                 :            :         }
    5553                 :            : 
    5554                 :          0 :         sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
    5555                 :            :                  "support for outer frame pattern items is not guaranteed; "
    5556                 :            :                  "other than that, the items are valid from SW standpoint");
    5557                 :          0 :         return 0;
    5558                 :            : }
    5559                 :            : 
    5560                 :            : static int
    5561                 :          0 : sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
    5562                 :            :                                  struct sfc_mae_action_rule *rule)
    5563                 :            : {
    5564                 :            :         struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
    5565                 :            :         const struct sfc_mae_action_rule *entry;
    5566                 :            :         struct sfc_mae *mae = &sa->mae;
    5567                 :            : 
    5568         [ #  # ]:          0 :         if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
    5569                 :            :                 /* An active rule is reused. Its class is known to be valid. */
    5570                 :            :                 return 0;
    5571                 :            :         }
    5572                 :            : 
    5573         [ #  # ]:          0 :         TAILQ_FOREACH_REVERSE(entry, &mae->action_rules,
    5574                 :            :                               sfc_mae_action_rules, entries) {
    5575                 :          0 :                 const efx_mae_match_spec_t *left = entry->match_spec;
    5576                 :          0 :                 const efx_mae_match_spec_t *right = rule->match_spec;
    5577                 :            : 
    5578         [ #  # ]:          0 :                 if (entry == rule)
    5579                 :          0 :                         continue;
    5580                 :            : 
    5581                 :            :                 if (sfc_mae_rules_class_cmp(sa, left, right))
    5582                 :          0 :                         return 0;
    5583                 :            :         }
    5584                 :            : 
    5585                 :          0 :         sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
    5586                 :            :                  "support for inner frame pattern items is not guaranteed; "
    5587                 :            :                  "other than that, the items are valid from SW standpoint");
    5588                 :          0 :         return 0;
    5589                 :            : }
    5590                 :            : 
    5591                 :            : /**
    5592                 :            :  * Confirm that a given flow can be accepted by the FW.
    5593                 :            :  *
    5594                 :            :  * @param sa
    5595                 :            :  *   Software adapter context
    5596                 :            :  * @param flow
    5597                 :            :  *   Flow to be verified
    5598                 :            :  * @return
    5599                 :            :  *   Zero on success and non-zero in the case of error.
    5600                 :            :  *   A special value of EAGAIN indicates that the adapter is
    5601                 :            :  *   not in started state. This state is compulsory because
    5602                 :            :  *   it only makes sense to compare the rule class of the flow
    5603                 :            :  *   being validated with classes of the active rules.
    5604                 :            :  *   Such classes are wittingly supported by the FW.
    5605                 :            :  */
    5606                 :            : int
    5607                 :          0 : sfc_mae_flow_verify(struct sfc_adapter *sa,
    5608                 :            :                     struct rte_flow *flow)
    5609                 :            : {
    5610                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    5611                 :            :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    5612                 :          0 :         struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
    5613                 :          0 :         struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
    5614                 :            :         int rc;
    5615                 :            : 
    5616                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    5617                 :            : 
    5618         [ #  # ]:          0 :         if (sa->state != SFC_ETHDEV_STARTED)
    5619                 :            :                 return EAGAIN;
    5620                 :            : 
    5621                 :          0 :         rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
    5622         [ #  # ]:          0 :         if (rc != 0)
    5623                 :            :                 return rc;
    5624                 :            : 
    5625                 :          0 :         return sfc_mae_action_rule_class_verify(sa, action_rule);
    5626                 :            : }
    5627                 :            : 
    5628                 :            : int
    5629                 :          0 : sfc_mae_flow_insert(struct sfc_adapter *sa,
    5630                 :            :                     struct rte_flow *flow)
    5631                 :            : {
    5632                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    5633                 :            :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    5634                 :          0 :         struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
    5635                 :            :         int rc;
    5636                 :            : 
    5637         [ #  # ]:          0 :         if (spec_mae->ft_rule_type == SFC_FT_RULE_TUNNEL) {
    5638                 :          0 :                 spec_mae->ft_ctx->reset_tunnel_hit_counter =
    5639                 :          0 :                         spec_mae->ft_ctx->switch_hit_counter;
    5640                 :            :         }
    5641                 :            : 
    5642         [ #  # ]:          0 :         if (action_rule == NULL)
    5643                 :            :                 return 0;
    5644                 :            : 
    5645                 :          0 :         rc = sfc_mae_action_rule_enable(sa, action_rule);
    5646         [ #  # ]:          0 :         if (rc != 0)
    5647                 :            :                 return rc;
    5648                 :            : 
    5649         [ #  # ]:          0 :         if (spec_mae->action_rule->ct_mark != 0) {
    5650                 :          0 :                 struct sfc_mae_counter *counter = spec_mae->ct_counter;
    5651                 :            : 
    5652                 :          0 :                 rc = sfc_mae_counter_enable(sa, counter, NULL);
    5653         [ #  # ]:          0 :                 if (rc != 0) {
    5654                 :          0 :                         sfc_mae_action_rule_disable(sa, action_rule);
    5655                 :          0 :                         return rc;
    5656                 :            :                 }
    5657                 :            : 
    5658         [ #  # ]:          0 :                 if (counter != NULL) {
    5659                 :            :                         struct sfc_mae_fw_rsrc *fw_rsrc = &counter->fw_rsrc;
    5660                 :            : 
    5661                 :          0 :                         spec_mae->ct_resp.counter_id = fw_rsrc->counter_id.id;
    5662                 :            : 
    5663                 :          0 :                         rc = sfc_mae_counter_start(sa);
    5664         [ #  # ]:          0 :                         if (rc != 0) {
    5665                 :          0 :                                 sfc_mae_action_rule_disable(sa, action_rule);
    5666                 :          0 :                                 return rc;
    5667                 :            :                         }
    5668                 :            :                 } else {
    5669                 :          0 :                         spec_mae->ct_resp.counter_id = EFX_MAE_RSRC_ID_INVALID;
    5670                 :            :                 }
    5671                 :            : 
    5672                 :          0 :                 spec_mae->ct_resp.ct_mark = spec_mae->action_rule->ct_mark;
    5673                 :            : 
    5674                 :          0 :                 rc = sfc_mae_conntrack_insert(sa, &spec_mae->ct_key,
    5675                 :          0 :                                               &spec_mae->ct_resp);
    5676         [ #  # ]:          0 :                 if (rc != 0) {
    5677                 :          0 :                         sfc_mae_counter_disable(sa, counter);
    5678                 :          0 :                         sfc_mae_action_rule_disable(sa, action_rule);
    5679                 :          0 :                         return rc;
    5680                 :            :                 }
    5681                 :            :         }
    5682                 :            : 
    5683                 :            :         return 0;
    5684                 :            : }
    5685                 :            : 
    5686                 :            : int
    5687                 :          0 : sfc_mae_flow_remove(struct sfc_adapter *sa,
    5688                 :            :                     struct rte_flow *flow)
    5689                 :            : {
    5690                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    5691                 :            :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    5692                 :          0 :         struct sfc_mae_action_rule *action_rule = spec_mae->action_rule;
    5693                 :            : 
    5694         [ #  # ]:          0 :         if (action_rule == NULL)
    5695                 :            :                 return 0;
    5696                 :            : 
    5697         [ #  # ]:          0 :         if (action_rule->ct_mark != 0)
    5698                 :          0 :                 (void)sfc_mae_conntrack_delete(sa, &spec_mae->ct_key);
    5699                 :            : 
    5700                 :          0 :         sfc_mae_counter_disable(sa, spec_mae->ct_counter);
    5701                 :            : 
    5702                 :          0 :         sfc_mae_action_rule_disable(sa, action_rule);
    5703                 :            : 
    5704                 :          0 :         return 0;
    5705                 :            : }
    5706                 :            : 
    5707                 :            : static int
    5708                 :          0 : sfc_mae_query_counter(struct sfc_adapter *sa,
    5709                 :            :                       struct sfc_flow_spec_mae *spec,
    5710                 :            :                       const struct rte_flow_action *action,
    5711                 :            :                       struct rte_flow_query_count *data,
    5712                 :            :                       struct rte_flow_error *error)
    5713                 :            : {
    5714                 :          0 :         const struct sfc_mae_action_rule *action_rule = spec->action_rule;
    5715                 :          0 :         const struct rte_flow_action_count *conf = action->conf;
    5716                 :            :         struct sfc_mae_counter *counters[1 /* action rule counter */ +
    5717                 :            :                                          1 /* conntrack counter */];
    5718                 :            :         struct sfc_mae_counter *counter;
    5719                 :            :         unsigned int i;
    5720                 :            :         int rc;
    5721                 :            : 
    5722                 :            :         /*
    5723                 :            :          * The check for counter unavailability is done based
    5724                 :            :          * on counter traversal results. See error set below.
    5725                 :            :          */
    5726   [ #  #  #  # ]:          0 :         if (action_rule != NULL && action_rule->action_set != NULL &&
    5727         [ #  # ]:          0 :             action_rule->action_set->counter != NULL &&
    5728         [ #  # ]:          0 :             !action_rule->action_set->counter->indirect)
    5729                 :          0 :                 counters[0] = action_rule->action_set->counter;
    5730                 :            :         else
    5731                 :          0 :                 counters[0] = NULL;
    5732                 :            : 
    5733                 :          0 :         counters[1] = spec->ct_counter;
    5734                 :            : 
    5735         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(counters); ++i) {
    5736                 :          0 :                 counter = counters[i];
    5737                 :            : 
    5738         [ #  # ]:          0 :                 if (counter == NULL)
    5739                 :          0 :                         continue;
    5740                 :            : 
    5741         [ #  # ]:          0 :                 if (conf == NULL ||
    5742   [ #  #  #  # ]:          0 :                     (counter->rte_id_valid && conf->id == counter->rte_id)) {
    5743                 :          0 :                         rc = sfc_mae_counter_get(sa, counter, data);
    5744         [ #  # ]:          0 :                         if (rc != 0) {
    5745                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5746                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5747                 :            :                                         "Queried flow rule counter action is invalid");
    5748                 :            :                         }
    5749                 :            : 
    5750                 :            :                         return 0;
    5751                 :            :                 }
    5752                 :            :         }
    5753                 :            : 
    5754   [ #  #  #  # ]:          0 :         if (action_rule == NULL || action_rule->action_set_list == NULL)
    5755                 :          0 :                 goto exit;
    5756                 :            : 
    5757         [ #  # ]:          0 :         for (i = 0; i < action_rule->action_set_list->nb_action_sets; ++i) {
    5758                 :          0 :                 counter = action_rule->action_set_list->action_sets[i]->counter;
    5759                 :            : 
    5760   [ #  #  #  # ]:          0 :                 if (counter == NULL || counter->indirect)
    5761                 :          0 :                         continue;
    5762                 :            : 
    5763         [ #  # ]:          0 :                 if (conf == NULL ||
    5764   [ #  #  #  # ]:          0 :                     (counter->rte_id_valid && conf->id == counter->rte_id)) {
    5765                 :          0 :                         rc = sfc_mae_counter_get(sa, counter, data);
    5766         [ #  # ]:          0 :                         if (rc != 0) {
    5767                 :          0 :                                 return rte_flow_error_set(error, EINVAL,
    5768                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
    5769                 :            :                                         "Queried flow rule counter action is invalid");
    5770                 :            :                         }
    5771                 :            : 
    5772                 :            :                         return 0;
    5773                 :            :                 }
    5774                 :            :         }
    5775                 :            : 
    5776                 :          0 : exit:
    5777                 :          0 :         return rte_flow_error_set(error, ENOENT,
    5778                 :            :                                   RTE_FLOW_ERROR_TYPE_ACTION, action,
    5779                 :            :                                   "no such flow rule action or such count ID");
    5780                 :            : }
    5781                 :            : 
    5782                 :            : int
    5783         [ #  # ]:          0 : sfc_mae_flow_query(struct rte_eth_dev *dev,
    5784                 :            :                    struct rte_flow *flow,
    5785                 :            :                    const struct rte_flow_action *action,
    5786                 :            :                    void *data,
    5787                 :            :                    struct rte_flow_error *error)
    5788                 :            : {
    5789                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    5790                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    5791                 :          0 :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    5792                 :            : 
    5793         [ #  # ]:          0 :         switch (action->type) {
    5794                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    5795                 :          0 :                 return sfc_mae_query_counter(sa, spec_mae, action,
    5796                 :            :                                              data, error);
    5797                 :          0 :         default:
    5798                 :          0 :                 return rte_flow_error_set(error, ENOTSUP,
    5799                 :            :                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    5800                 :            :                         "Query for action of this type is not supported");
    5801                 :            :         }
    5802                 :            : }
    5803                 :            : 
    5804                 :            : int
    5805                 :          0 : sfc_mae_switchdev_init(struct sfc_adapter *sa)
    5806                 :            : {
    5807                 :            :         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
    5808                 :            :         struct sfc_mae *mae = &sa->mae;
    5809                 :            :         int rc = EINVAL;
    5810                 :            : 
    5811                 :          0 :         sfc_log_init(sa, "entry");
    5812                 :            : 
    5813         [ #  # ]:          0 :         if (!sa->switchdev) {
    5814                 :          0 :                 sfc_log_init(sa, "switchdev is not enabled - skip");
    5815                 :          0 :                 return 0;
    5816                 :            :         }
    5817                 :            : 
    5818         [ #  # ]:          0 :         if (mae->status != SFC_MAE_STATUS_ADMIN) {
    5819                 :            :                 rc = ENOTSUP;
    5820                 :          0 :                 sfc_err(sa, "failed to init switchdev - no admin MAE privilege");
    5821                 :          0 :                 goto fail_no_mae;
    5822                 :            :         }
    5823                 :            : 
    5824                 :          0 :         mae->switchdev_rule_pf_to_ext = sfc_mae_repr_flow_create(sa,
    5825                 :          0 :                                          SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
    5826                 :            :                                          RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
    5827                 :            :                                          RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR);
    5828         [ #  # ]:          0 :         if (mae->switchdev_rule_pf_to_ext == NULL) {
    5829                 :          0 :                 sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
    5830                 :          0 :                 goto fail_pf_add;
    5831                 :            :         }
    5832                 :            : 
    5833                 :          0 :         mae->switchdev_rule_ext_to_pf = sfc_mae_repr_flow_create(sa,
    5834                 :          0 :                                          SFC_MAE_RULE_PRIO_LOWEST, sas->port_id,
    5835                 :            :                                          RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
    5836                 :            :                                          RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT);
    5837         [ #  # ]:          0 :         if (mae->switchdev_rule_ext_to_pf == NULL) {
    5838                 :          0 :                 sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
    5839                 :          0 :                 goto fail_phy_add;
    5840                 :            :         }
    5841                 :            : 
    5842                 :          0 :         sfc_log_init(sa, "done");
    5843                 :            : 
    5844                 :          0 :         return 0;
    5845                 :            : 
    5846                 :            : fail_phy_add:
    5847                 :          0 :         sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
    5848                 :            : 
    5849                 :          0 : fail_pf_add:
    5850                 :          0 : fail_no_mae:
    5851                 :          0 :         sfc_log_init(sa, "failed: %s", rte_strerror(rc));
    5852                 :          0 :         return rc;
    5853                 :            : }
    5854                 :            : 
    5855                 :            : void
    5856                 :          0 : sfc_mae_switchdev_fini(struct sfc_adapter *sa)
    5857                 :            : {
    5858                 :            :         struct sfc_mae *mae = &sa->mae;
    5859                 :            : 
    5860         [ #  # ]:          0 :         if (!sa->switchdev)
    5861                 :            :                 return;
    5862                 :            : 
    5863                 :          0 :         sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext);
    5864                 :          0 :         sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf);
    5865                 :            : }
    5866                 :            : 
    5867                 :            : int
    5868                 :          0 : sfc_mae_indir_action_create(struct sfc_adapter *sa,
    5869                 :            :                             const struct rte_flow_action *action,
    5870                 :            :                             struct rte_flow_action_handle *handle,
    5871                 :            :                             struct rte_flow_error *error)
    5872                 :            : {
    5873                 :          0 :         struct sfc_mae *mae = &sa->mae;
    5874                 :            :         bool custom_error = false;
    5875                 :            :         int ret;
    5876                 :            : 
    5877                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    5878                 :            :         SFC_ASSERT(handle != NULL);
    5879                 :            : 
    5880      [ #  #  # ]:          0 :         switch (action->type) {
    5881                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    5882                 :            :                 /* Cleanup after previous encap. header bounce buffer usage. */
    5883                 :            :                 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
    5884                 :            : 
    5885                 :          0 :                 ret = sfc_mae_rule_parse_action_vxlan_encap(mae, action->conf,
    5886                 :            :                                                             NULL, error);
    5887         [ #  # ]:          0 :                 if (ret != 0) {
    5888                 :            :                         custom_error = true;
    5889                 :            :                         break;
    5890                 :            :                 }
    5891                 :            : 
    5892                 :          0 :                 ret = sfc_mae_encap_header_add(sa, &mae->bounce_eh,
    5893                 :            :                                                &handle->encap_header);
    5894         [ #  # ]:          0 :                 if (ret == 0)
    5895                 :          0 :                         handle->encap_header->indirect = true;
    5896                 :            :                 break;
    5897                 :            : 
    5898                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    5899                 :          0 :                 ret = sfc_mae_rule_parse_action_count(sa, action->conf,
    5900                 :            :                                                       EFX_COUNTER_TYPE_ACTION,
    5901                 :            :                                                       &handle->counter, NULL);
    5902         [ #  # ]:          0 :                 if (ret == 0)
    5903                 :          0 :                         handle->counter->indirect = true;
    5904                 :            :                 break;
    5905                 :            :         default:
    5906                 :            :                 ret = ENOTSUP;
    5907                 :            :         }
    5908                 :            : 
    5909                 :            :         if (custom_error)
    5910                 :            :                 return ret;
    5911                 :            : 
    5912         [ #  # ]:          0 :         if (ret != 0) {
    5913                 :          0 :                 return rte_flow_error_set(error, ret,
    5914                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5915                 :            :                                 "failed to parse indirect action to mae object");
    5916                 :            :         }
    5917                 :            : 
    5918                 :          0 :         handle->type = action->type;
    5919                 :            : 
    5920                 :          0 :         return 0;
    5921                 :            : }
    5922                 :            : 
    5923                 :            : int
    5924                 :          0 : sfc_mae_indir_action_destroy(struct sfc_adapter *sa,
    5925                 :            :                              const struct rte_flow_action_handle *handle,
    5926                 :            :                              struct rte_flow_error *error)
    5927                 :            : {
    5928                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    5929                 :            :         SFC_ASSERT(handle != NULL);
    5930                 :            : 
    5931      [ #  #  # ]:          0 :         switch (handle->type) {
    5932                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    5933         [ #  # ]:          0 :                 if (handle->encap_header->refcnt != 1)
    5934                 :          0 :                         goto fail;
    5935                 :            : 
    5936                 :          0 :                 sfc_mae_encap_header_del(sa, handle->encap_header);
    5937                 :          0 :                 break;
    5938                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    5939         [ #  # ]:          0 :                 if (handle->counter->refcnt != 1)
    5940                 :          0 :                         goto fail;
    5941                 :            : 
    5942                 :          0 :                 sfc_mae_counter_del(sa, handle->counter);
    5943                 :          0 :                 break;
    5944                 :            :         default:
    5945                 :            :                 SFC_ASSERT(B_FALSE);
    5946                 :            :                 break;
    5947                 :            :         }
    5948                 :            : 
    5949                 :            :         return 0;
    5950                 :            : 
    5951                 :          0 : fail:
    5952                 :          0 :         return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    5953                 :            :                                   NULL, "indirect action is still in use");
    5954                 :            : }
    5955                 :            : 
    5956                 :            : int
    5957                 :          0 : sfc_mae_indir_action_update(struct sfc_adapter *sa,
    5958                 :            :                             struct rte_flow_action_handle *handle,
    5959                 :            :                             const void *update, struct rte_flow_error *error)
    5960                 :            : {
    5961                 :            :         const struct rte_flow_action *action = update;
    5962                 :          0 :         struct sfc_mae *mae = &sa->mae;
    5963                 :            :         bool custom_error = false;
    5964                 :            :         int ret;
    5965                 :            : 
    5966                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    5967                 :            :         SFC_ASSERT(action != NULL);
    5968                 :            :         SFC_ASSERT(handle != NULL);
    5969                 :            : 
    5970         [ #  # ]:          0 :         switch (handle->type) {
    5971                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
    5972                 :            :                 /* Cleanup after previous encap. header bounce buffer usage. */
    5973                 :            :                 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
    5974                 :            : 
    5975                 :          0 :                 ret = sfc_mae_rule_parse_action_vxlan_encap(mae, action->conf,
    5976                 :            :                                                             NULL, error);
    5977         [ #  # ]:          0 :                 if (ret != 0) {
    5978                 :            :                         custom_error = true;
    5979                 :            :                         break;
    5980                 :            :                 }
    5981                 :            : 
    5982                 :          0 :                 ret = sfc_mae_encap_header_update(sa, handle->encap_header);
    5983                 :            :                 break;
    5984                 :            :         default:
    5985                 :            :                 ret = ENOTSUP;
    5986                 :            :         }
    5987                 :            : 
    5988                 :            :         if (custom_error)
    5989                 :            :                 return ret;
    5990                 :            : 
    5991         [ #  # ]:          0 :         if (ret != 0) {
    5992                 :          0 :                 return rte_flow_error_set(error, ret,
    5993                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    5994                 :            :                                 "failed to parse indirect action to mae object");
    5995                 :            :         }
    5996                 :            : 
    5997                 :            :         return 0;
    5998                 :            : }
    5999                 :            : 
    6000                 :            : int
    6001                 :          0 : sfc_mae_indir_action_query(struct sfc_adapter *sa,
    6002                 :            :                            const struct rte_flow_action_handle *handle,
    6003                 :            :                            void *data, struct rte_flow_error *error)
    6004                 :            : {
    6005                 :            :         int ret;
    6006                 :            : 
    6007                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    6008                 :            :         SFC_ASSERT(handle != NULL);
    6009                 :            : 
    6010         [ #  # ]:          0 :         switch (handle->type) {
    6011                 :          0 :         case RTE_FLOW_ACTION_TYPE_COUNT:
    6012                 :            :                 SFC_ASSERT(handle->counter != NULL);
    6013                 :            : 
    6014         [ #  # ]:          0 :                 if (handle->counter->fw_rsrc.refcnt == 0)
    6015                 :          0 :                         goto fail_not_in_use;
    6016                 :            : 
    6017                 :          0 :                 ret = sfc_mae_counter_get(sa, handle->counter, data);
    6018         [ #  # ]:          0 :                 if (ret != 0)
    6019                 :          0 :                         goto fail_counter_get;
    6020                 :            : 
    6021                 :            :                 break;
    6022                 :          0 :         default:
    6023                 :          0 :                 goto fail_unsup;
    6024                 :            :         }
    6025                 :            : 
    6026                 :            :         return 0;
    6027                 :            : 
    6028                 :            : fail_not_in_use:
    6029                 :          0 :         return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6030                 :            :                                   NULL, "indirect action is not in use");
    6031                 :            : 
    6032                 :            : fail_counter_get:
    6033                 :          0 :         return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6034                 :            :                                   NULL, "failed to collect indirect action COUNT data");
    6035                 :            : 
    6036                 :            : fail_unsup:
    6037                 :          0 :         return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    6038                 :            :                                   NULL, "indirect action of this type cannot be queried");
    6039                 :            : }

Generated by: LCOV version 1.14