LCOV - code coverage report
Current view: top level - drivers/net/sfc - sfc_flow.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 839 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 62 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 583 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) 2017-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_tailq.h>
      14                 :            : #include <rte_common.h>
      15                 :            : #include <ethdev_driver.h>
      16                 :            : #include <rte_ether.h>
      17                 :            : #include <rte_flow.h>
      18                 :            : #include <rte_flow_driver.h>
      19                 :            : 
      20                 :            : #include "efx.h"
      21                 :            : 
      22                 :            : #include "sfc.h"
      23                 :            : #include "sfc_debug.h"
      24                 :            : #include "sfc_rx.h"
      25                 :            : #include "sfc_filter.h"
      26                 :            : #include "sfc_flow.h"
      27                 :            : #include "sfc_flow_rss.h"
      28                 :            : #include "sfc_flow_tunnel.h"
      29                 :            : #include "sfc_log.h"
      30                 :            : #include "sfc_dp_rx.h"
      31                 :            : #include "sfc_mae_counter.h"
      32                 :            : #include "sfc_switch.h"
      33                 :            : 
      34                 :            : struct sfc_flow_ops_by_spec {
      35                 :            :         sfc_flow_parse_cb_t     *parse;
      36                 :            :         sfc_flow_verify_cb_t    *verify;
      37                 :            :         sfc_flow_cleanup_cb_t   *cleanup;
      38                 :            :         sfc_flow_insert_cb_t    *insert;
      39                 :            :         sfc_flow_remove_cb_t    *remove;
      40                 :            :         sfc_flow_query_cb_t     *query;
      41                 :            : };
      42                 :            : 
      43                 :            : static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;
      44                 :            : static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_mae;
      45                 :            : static sfc_flow_insert_cb_t sfc_flow_filter_insert;
      46                 :            : static sfc_flow_remove_cb_t sfc_flow_filter_remove;
      47                 :            : static sfc_flow_cleanup_cb_t sfc_flow_cleanup;
      48                 :            : 
      49                 :            : static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
      50                 :            :         .parse = sfc_flow_parse_rte_to_filter,
      51                 :            :         .verify = NULL,
      52                 :            :         .cleanup = sfc_flow_cleanup,
      53                 :            :         .insert = sfc_flow_filter_insert,
      54                 :            :         .remove = sfc_flow_filter_remove,
      55                 :            :         .query = NULL,
      56                 :            : };
      57                 :            : 
      58                 :            : static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
      59                 :            :         .parse = sfc_flow_parse_rte_to_mae,
      60                 :            :         .verify = sfc_mae_flow_verify,
      61                 :            :         .cleanup = sfc_mae_flow_cleanup,
      62                 :            :         .insert = sfc_mae_flow_insert,
      63                 :            :         .remove = sfc_mae_flow_remove,
      64                 :            :         .query = sfc_mae_flow_query,
      65                 :            : };
      66                 :            : 
      67                 :            : static const struct sfc_flow_ops_by_spec *
      68                 :            : sfc_flow_get_ops_by_spec(struct rte_flow *flow)
      69                 :            : {
      70                 :            :         struct sfc_flow_spec *spec = &flow->spec;
      71                 :            :         const struct sfc_flow_ops_by_spec *ops = NULL;
      72                 :            : 
      73   [ #  #  #  #  :          0 :         switch (spec->type) {
                   #  # ]
      74                 :            :         case SFC_FLOW_SPEC_FILTER:
      75                 :            :                 ops = &sfc_flow_ops_filter;
      76                 :            :                 break;
      77                 :          0 :         case SFC_FLOW_SPEC_MAE:
      78                 :            :                 ops = &sfc_flow_ops_mae;
      79                 :          0 :                 break;
      80                 :            :         default:
      81                 :            :                 SFC_ASSERT(false);
      82                 :            :                 break;
      83                 :            :         }
      84                 :            : 
      85                 :            :         return ops;
      86                 :            : }
      87                 :            : 
      88                 :            : /*
      89                 :            :  * Currently, filter-based (VNIC) flow API is implemented in such a manner
      90                 :            :  * that each flow rule is converted to one or more hardware filters.
      91                 :            :  * All elements of flow rule (attributes, pattern items, actions)
      92                 :            :  * correspond to one or more fields in the efx_filter_spec_s structure
      93                 :            :  * that is responsible for the hardware filter.
      94                 :            :  * If some required field is unset in the flow rule, then a handful
      95                 :            :  * of filter copies will be created to cover all possible values
      96                 :            :  * of such a field.
      97                 :            :  */
      98                 :            : 
      99                 :            : static sfc_flow_item_parse sfc_flow_parse_void;
     100                 :            : static sfc_flow_item_parse sfc_flow_parse_eth;
     101                 :            : static sfc_flow_item_parse sfc_flow_parse_vlan;
     102                 :            : static sfc_flow_item_parse sfc_flow_parse_ipv4;
     103                 :            : static sfc_flow_item_parse sfc_flow_parse_ipv6;
     104                 :            : static sfc_flow_item_parse sfc_flow_parse_tcp;
     105                 :            : static sfc_flow_item_parse sfc_flow_parse_udp;
     106                 :            : static sfc_flow_item_parse sfc_flow_parse_vxlan;
     107                 :            : static sfc_flow_item_parse sfc_flow_parse_geneve;
     108                 :            : static sfc_flow_item_parse sfc_flow_parse_nvgre;
     109                 :            : static sfc_flow_item_parse sfc_flow_parse_pppoex;
     110                 :            : 
     111                 :            : typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec,
     112                 :            :                                      unsigned int filters_count_for_one_val,
     113                 :            :                                      struct rte_flow_error *error);
     114                 :            : 
     115                 :            : typedef boolean_t (sfc_flow_spec_check)(efx_filter_match_flags_t match,
     116                 :            :                                         efx_filter_spec_t *spec,
     117                 :            :                                         struct sfc_filter *filter);
     118                 :            : 
     119                 :            : struct sfc_flow_copy_flag {
     120                 :            :         /* EFX filter specification match flag */
     121                 :            :         efx_filter_match_flags_t flag;
     122                 :            :         /* Number of values of corresponding field */
     123                 :            :         unsigned int vals_count;
     124                 :            :         /* Function to set values in specifications */
     125                 :            :         sfc_flow_spec_set_vals *set_vals;
     126                 :            :         /*
     127                 :            :          * Function to check that the specification is suitable
     128                 :            :          * for adding this match flag
     129                 :            :          */
     130                 :            :         sfc_flow_spec_check *spec_check;
     131                 :            : };
     132                 :            : 
     133                 :            : static sfc_flow_spec_set_vals sfc_flow_set_unknown_dst_flags;
     134                 :            : static sfc_flow_spec_check sfc_flow_check_unknown_dst_flags;
     135                 :            : static sfc_flow_spec_set_vals sfc_flow_set_ethertypes;
     136                 :            : static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags;
     137                 :            : static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags;
     138                 :            : static sfc_flow_spec_set_vals sfc_flow_set_outer_vid_flag;
     139                 :            : static sfc_flow_spec_check sfc_flow_check_outer_vid_flag;
     140                 :            : 
     141                 :            : static boolean_t
     142                 :            : sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
     143                 :            : {
     144                 :            :         uint8_t sum = 0;
     145                 :            :         unsigned int i;
     146                 :            : 
     147   [ #  #  #  #  :          0 :         for (i = 0; i < size; i++)
             #  #  #  # ]
     148                 :          0 :                 sum |= buf[i];
     149                 :            : 
     150                 :            :         return (sum == 0) ? B_TRUE : B_FALSE;
     151                 :            : }
     152                 :            : 
     153                 :            : /*
     154                 :            :  * Validate item and prepare structures spec and mask for parsing
     155                 :            :  */
     156                 :            : int
     157                 :          0 : sfc_flow_parse_init(const struct rte_flow_item *item,
     158                 :            :                     const void **spec_ptr,
     159                 :            :                     const void **mask_ptr,
     160                 :            :                     const void *supp_mask,
     161                 :            :                     const void *def_mask,
     162                 :            :                     unsigned int size,
     163                 :            :                     struct rte_flow_error *error)
     164                 :            : {
     165                 :            :         const uint8_t *spec;
     166                 :            :         const uint8_t *mask;
     167                 :            :         const uint8_t *last;
     168                 :            :         uint8_t supp;
     169                 :            :         unsigned int i;
     170                 :            : 
     171         [ #  # ]:          0 :         if (item == NULL) {
     172                 :          0 :                 rte_flow_error_set(error, EINVAL,
     173                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     174                 :            :                                    "NULL item");
     175                 :          0 :                 return -rte_errno;
     176                 :            :         }
     177                 :            : 
     178   [ #  #  #  #  :          0 :         if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
                   #  # ]
     179                 :          0 :                 rte_flow_error_set(error, EINVAL,
     180                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     181                 :            :                                    "Mask or last is set without spec");
     182                 :          0 :                 return -rte_errno;
     183                 :            :         }
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * If "mask" is not set, default mask is used,
     187                 :            :          * but if default mask is NULL, "mask" should be set
     188                 :            :          */
     189         [ #  # ]:          0 :         if (item->mask == NULL) {
     190         [ #  # ]:          0 :                 if (def_mask == NULL) {
     191                 :          0 :                         rte_flow_error_set(error, EINVAL,
     192                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
     193                 :            :                                 "Mask should be specified");
     194                 :          0 :                         return -rte_errno;
     195                 :            :                 }
     196                 :            : 
     197                 :            :                 mask = def_mask;
     198                 :            :         } else {
     199                 :            :                 mask = item->mask;
     200                 :            :         }
     201                 :            : 
     202                 :          0 :         spec = item->spec;
     203                 :            :         last = item->last;
     204                 :            : 
     205         [ #  # ]:          0 :         if (spec == NULL)
     206                 :          0 :                 goto exit;
     207                 :            : 
     208                 :            :         /*
     209                 :            :          * If field values in "last" are either 0 or equal to the corresponding
     210                 :            :          * values in "spec" then they are ignored
     211                 :            :          */
     212   [ #  #  #  # ]:          0 :         if (last != NULL &&
     213                 :          0 :             !sfc_flow_is_zero(last, size) &&
     214         [ #  # ]:          0 :             memcmp(last, spec, size) != 0) {
     215                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
     216                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     217                 :            :                                    "Ranging is not supported");
     218                 :          0 :                 return -rte_errno;
     219                 :            :         }
     220                 :            : 
     221         [ #  # ]:          0 :         if (supp_mask == NULL) {
     222                 :          0 :                 rte_flow_error_set(error, EINVAL,
     223                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
     224                 :            :                         "Supported mask for item should be specified");
     225                 :          0 :                 return -rte_errno;
     226                 :            :         }
     227                 :            : 
     228                 :            :         /* Check that mask does not ask for more match than supp_mask */
     229         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
     230                 :          0 :                 supp = ((const uint8_t *)supp_mask)[i];
     231                 :            : 
     232         [ #  # ]:          0 :                 if (~supp & mask[i]) {
     233                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
     234                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     235                 :            :                                            "Item's field is not supported");
     236                 :          0 :                         return -rte_errno;
     237                 :            :                 }
     238                 :            :         }
     239                 :            : 
     240                 :          0 : exit:
     241                 :          0 :         *spec_ptr = spec;
     242                 :          0 :         *mask_ptr = mask;
     243                 :          0 :         return 0;
     244                 :            : }
     245                 :            : 
     246                 :            : /*
     247                 :            :  * Protocol parsers.
     248                 :            :  * Masking is not supported, so masks in items should be either
     249                 :            :  * full or empty (zeroed) and set only for supported fields which
     250                 :            :  * are specified in the supp_mask.
     251                 :            :  */
     252                 :            : 
     253                 :            : static int
     254                 :          0 : sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
     255                 :            :                     __rte_unused struct sfc_flow_parse_ctx *parse_ctx,
     256                 :            :                     __rte_unused struct rte_flow_error *error)
     257                 :            : {
     258                 :          0 :         return 0;
     259                 :            : }
     260                 :            : 
     261                 :            : /**
     262                 :            :  * Convert Ethernet item to EFX filter specification.
     263                 :            :  *
     264                 :            :  * @param item[in]
     265                 :            :  *   Item specification. Outer frame specification may only comprise
     266                 :            :  *   source/destination addresses and Ethertype field.
     267                 :            :  *   Inner frame specification may contain destination address only.
     268                 :            :  *   There is support for individual/group mask as well as for empty and full.
     269                 :            :  *   If the mask is NULL, default mask will be used. Ranging is not supported.
     270                 :            :  * @param efx_spec[in, out]
     271                 :            :  *   EFX filter specification to update.
     272                 :            :  * @param[out] error
     273                 :            :  *   Perform verbose error reporting if not NULL.
     274                 :            :  */
     275                 :            : static int
     276                 :          0 : sfc_flow_parse_eth(const struct rte_flow_item *item,
     277                 :            :                    struct sfc_flow_parse_ctx *parse_ctx,
     278                 :            :                    struct rte_flow_error *error)
     279                 :            : {
     280                 :            :         int rc;
     281                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     282                 :          0 :         const struct rte_flow_item_eth *spec = NULL;
     283                 :          0 :         const struct rte_flow_item_eth *mask = NULL;
     284                 :          0 :         const struct rte_flow_item_eth supp_mask = {
     285                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     286                 :            :                 .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     287                 :            :                 .hdr.ether_type = 0xffff,
     288                 :            :         };
     289                 :          0 :         const struct rte_flow_item_eth ifrm_supp_mask = {
     290                 :            :                 .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     291                 :            :         };
     292                 :          0 :         const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
     293                 :            :                 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
     294                 :            :         };
     295                 :            :         const struct rte_flow_item_eth *supp_mask_p;
     296                 :            :         const struct rte_flow_item_eth *def_mask_p;
     297                 :            :         uint8_t *loc_mac = NULL;
     298                 :          0 :         boolean_t is_ifrm = (efx_spec->efs_encap_type !=
     299                 :            :                 EFX_TUNNEL_PROTOCOL_NONE);
     300                 :            : 
     301         [ #  # ]:          0 :         if (is_ifrm) {
     302                 :            :                 supp_mask_p = &ifrm_supp_mask;
     303                 :            :                 def_mask_p = &ifrm_supp_mask;
     304                 :          0 :                 loc_mac = efx_spec->efs_ifrm_loc_mac;
     305                 :            :         } else {
     306                 :            :                 supp_mask_p = &supp_mask;
     307                 :            :                 def_mask_p = &rte_flow_item_eth_mask;
     308                 :          0 :                 loc_mac = efx_spec->efs_loc_mac;
     309                 :            :         }
     310                 :            : 
     311                 :          0 :         rc = sfc_flow_parse_init(item,
     312                 :            :                                  (const void **)&spec,
     313                 :            :                                  (const void **)&mask,
     314                 :            :                                  supp_mask_p, def_mask_p,
     315                 :            :                                  sizeof(struct rte_flow_item_eth),
     316                 :            :                                  error);
     317         [ #  # ]:          0 :         if (rc != 0)
     318                 :            :                 return rc;
     319                 :            : 
     320                 :            :         /* If "spec" is not set, could be any Ethernet */
     321         [ #  # ]:          0 :         if (spec == NULL)
     322                 :            :                 return 0;
     323                 :            : 
     324         [ #  # ]:          0 :         if (rte_is_same_ether_addr(&mask->hdr.dst_addr, &supp_mask.hdr.dst_addr)) {
     325                 :          0 :                 efx_spec->efs_match_flags |= is_ifrm ?
     326         [ #  # ]:          0 :                         EFX_FILTER_MATCH_IFRM_LOC_MAC :
     327                 :            :                         EFX_FILTER_MATCH_LOC_MAC;
     328         [ #  # ]:          0 :                 rte_memcpy(loc_mac, spec->hdr.dst_addr.addr_bytes,
     329                 :            :                            EFX_MAC_ADDR_LEN);
     330         [ #  # ]:          0 :         } else if (memcmp(mask->hdr.dst_addr.addr_bytes, ig_mask,
     331                 :            :                           EFX_MAC_ADDR_LEN) == 0) {
     332         [ #  # ]:          0 :                 if (rte_is_unicast_ether_addr(&spec->hdr.dst_addr))
     333                 :          0 :                         efx_spec->efs_match_flags |= is_ifrm ?
     334         [ #  # ]:          0 :                                 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST :
     335                 :            :                                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
     336                 :            :                 else
     337                 :          0 :                         efx_spec->efs_match_flags |= is_ifrm ?
     338         [ #  # ]:          0 :                                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST :
     339                 :            :                                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
     340         [ #  # ]:          0 :         } else if (!rte_is_zero_ether_addr(&mask->hdr.dst_addr)) {
     341                 :          0 :                 goto fail_bad_mask;
     342                 :            :         }
     343                 :            : 
     344                 :            :         /*
     345                 :            :          * ifrm_supp_mask ensures that the source address and
     346                 :            :          * ethertype masks are equal to zero in inner frame,
     347                 :            :          * so these fields are filled in only for the outer frame
     348                 :            :          */
     349         [ #  # ]:          0 :         if (rte_is_same_ether_addr(&mask->hdr.src_addr, &supp_mask.hdr.src_addr)) {
     350                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
     351         [ #  # ]:          0 :                 rte_memcpy(efx_spec->efs_rem_mac, spec->hdr.src_addr.addr_bytes,
     352                 :            :                            EFX_MAC_ADDR_LEN);
     353         [ #  # ]:          0 :         } else if (!rte_is_zero_ether_addr(&mask->hdr.src_addr)) {
     354                 :          0 :                 goto fail_bad_mask;
     355                 :            :         }
     356                 :            : 
     357                 :            :         /*
     358                 :            :          * Ether type is in big-endian byte order in item and
     359                 :            :          * in little-endian in efx_spec, so byte swap is used
     360                 :            :          */
     361         [ #  # ]:          0 :         if (mask->hdr.ether_type == supp_mask.hdr.ether_type) {
     362                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
     363         [ #  # ]:          0 :                 efx_spec->efs_ether_type = rte_bswap16(spec->hdr.ether_type);
     364         [ #  # ]:          0 :         } else if (mask->hdr.ether_type != 0) {
     365                 :          0 :                 goto fail_bad_mask;
     366                 :            :         }
     367                 :            : 
     368                 :            :         return 0;
     369                 :            : 
     370                 :          0 : fail_bad_mask:
     371                 :          0 :         rte_flow_error_set(error, EINVAL,
     372                 :            :                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     373                 :            :                            "Bad mask in the ETH pattern item");
     374                 :          0 :         return -rte_errno;
     375                 :            : }
     376                 :            : 
     377                 :            : /**
     378                 :            :  * Convert VLAN item to EFX filter specification.
     379                 :            :  *
     380                 :            :  * @param item[in]
     381                 :            :  *   Item specification. Only VID field is supported.
     382                 :            :  *   The mask can not be NULL. Ranging is not supported.
     383                 :            :  * @param efx_spec[in, out]
     384                 :            :  *   EFX filter specification to update.
     385                 :            :  * @param[out] error
     386                 :            :  *   Perform verbose error reporting if not NULL.
     387                 :            :  */
     388                 :            : static int
     389                 :          0 : sfc_flow_parse_vlan(const struct rte_flow_item *item,
     390                 :            :                     struct sfc_flow_parse_ctx *parse_ctx,
     391                 :            :                     struct rte_flow_error *error)
     392                 :            : {
     393                 :            :         int rc;
     394                 :            :         uint16_t vid;
     395                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     396                 :          0 :         const struct rte_flow_item_vlan *spec = NULL;
     397                 :          0 :         const struct rte_flow_item_vlan *mask = NULL;
     398                 :          0 :         const struct rte_flow_item_vlan supp_mask = {
     399                 :            :                 .hdr.vlan_tci = rte_cpu_to_be_16(RTE_ETH_VLAN_ID_MAX),
     400                 :            :                 .hdr.eth_proto = RTE_BE16(0xffff),
     401                 :            :         };
     402                 :            : 
     403                 :          0 :         rc = sfc_flow_parse_init(item,
     404                 :            :                                  (const void **)&spec,
     405                 :            :                                  (const void **)&mask,
     406                 :            :                                  &supp_mask,
     407                 :            :                                  NULL,
     408                 :            :                                  sizeof(struct rte_flow_item_vlan),
     409                 :            :                                  error);
     410         [ #  # ]:          0 :         if (rc != 0)
     411                 :            :                 return rc;
     412                 :            : 
     413                 :            :         /*
     414                 :            :          * VID is in big-endian byte order in item and
     415                 :            :          * in little-endian in efx_spec, so byte swap is used.
     416                 :            :          * If two VLAN items are included, the first matches
     417                 :            :          * the outer tag and the next matches the inner tag.
     418                 :            :          */
     419         [ #  # ]:          0 :         if (mask->hdr.vlan_tci == supp_mask.hdr.vlan_tci) {
     420                 :            :                 /* Apply mask to keep VID only */
     421         [ #  # ]:          0 :                 vid = rte_bswap16(spec->hdr.vlan_tci & mask->hdr.vlan_tci);
     422                 :            : 
     423         [ #  # ]:          0 :                 if (!(efx_spec->efs_match_flags &
     424                 :            :                       EFX_FILTER_MATCH_OUTER_VID)) {
     425                 :          0 :                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
     426                 :          0 :                         efx_spec->efs_outer_vid = vid;
     427         [ #  # ]:          0 :                 } else if (!(efx_spec->efs_match_flags &
     428                 :            :                              EFX_FILTER_MATCH_INNER_VID)) {
     429                 :          0 :                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
     430                 :          0 :                         efx_spec->efs_inner_vid = vid;
     431                 :            :                 } else {
     432                 :          0 :                         rte_flow_error_set(error, EINVAL,
     433                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     434                 :            :                                            "More than two VLAN items");
     435                 :          0 :                         return -rte_errno;
     436                 :            :                 }
     437                 :            :         } else {
     438                 :          0 :                 rte_flow_error_set(error, EINVAL,
     439                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     440                 :            :                                    "VLAN ID in TCI match is required");
     441                 :          0 :                 return -rte_errno;
     442                 :            :         }
     443                 :            : 
     444         [ #  # ]:          0 :         if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE) {
     445                 :          0 :                 rte_flow_error_set(error, EINVAL,
     446                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     447                 :            :                                    "VLAN TPID matching is not supported");
     448                 :          0 :                 return -rte_errno;
     449                 :            :         }
     450         [ #  # ]:          0 :         if (mask->hdr.eth_proto == supp_mask.hdr.eth_proto) {
     451                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
     452         [ #  # ]:          0 :                 efx_spec->efs_ether_type = rte_bswap16(spec->hdr.eth_proto);
     453         [ #  # ]:          0 :         } else if (mask->hdr.eth_proto) {
     454                 :          0 :                 rte_flow_error_set(error, EINVAL,
     455                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     456                 :            :                                    "Bad mask for VLAN inner type");
     457                 :          0 :                 return -rte_errno;
     458                 :            :         }
     459                 :            : 
     460                 :            :         return 0;
     461                 :            : }
     462                 :            : 
     463                 :            : /**
     464                 :            :  * Convert IPv4 item to EFX filter specification.
     465                 :            :  *
     466                 :            :  * @param item[in]
     467                 :            :  *   Item specification. Only source and destination addresses and
     468                 :            :  *   protocol fields are supported. If the mask is NULL, default
     469                 :            :  *   mask will be used. Ranging is not supported.
     470                 :            :  * @param efx_spec[in, out]
     471                 :            :  *   EFX filter specification to update.
     472                 :            :  * @param[out] error
     473                 :            :  *   Perform verbose error reporting if not NULL.
     474                 :            :  */
     475                 :            : static int
     476                 :          0 : sfc_flow_parse_ipv4(const struct rte_flow_item *item,
     477                 :            :                     struct sfc_flow_parse_ctx *parse_ctx,
     478                 :            :                     struct rte_flow_error *error)
     479                 :            : {
     480                 :            :         int rc;
     481                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     482                 :          0 :         const struct rte_flow_item_ipv4 *spec = NULL;
     483                 :          0 :         const struct rte_flow_item_ipv4 *mask = NULL;
     484                 :            :         const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
     485                 :          0 :         const struct rte_flow_item_ipv4 supp_mask = {
     486                 :            :                 .hdr = {
     487                 :            :                         .src_addr = 0xffffffff,
     488                 :            :                         .dst_addr = 0xffffffff,
     489                 :            :                         .next_proto_id = 0xff,
     490                 :            :                 }
     491                 :            :         };
     492                 :            : 
     493                 :          0 :         rc = sfc_flow_parse_init(item,
     494                 :            :                                  (const void **)&spec,
     495                 :            :                                  (const void **)&mask,
     496                 :            :                                  &supp_mask,
     497                 :            :                                  &rte_flow_item_ipv4_mask,
     498                 :            :                                  sizeof(struct rte_flow_item_ipv4),
     499                 :            :                                  error);
     500         [ #  # ]:          0 :         if (rc != 0)
     501                 :            :                 return rc;
     502                 :            : 
     503                 :            :         /*
     504                 :            :          * Filtering by IPv4 source and destination addresses requires
     505                 :            :          * the appropriate ETHER_TYPE in hardware filters
     506                 :            :          */
     507         [ #  # ]:          0 :         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
     508                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
     509                 :          0 :                 efx_spec->efs_ether_type = ether_type_ipv4;
     510         [ #  # ]:          0 :         } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
     511                 :          0 :                 rte_flow_error_set(error, EINVAL,
     512                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
     513                 :            :                         "Ethertype in pattern with IPV4 item should be appropriate");
     514                 :          0 :                 return -rte_errno;
     515                 :            :         }
     516                 :            : 
     517         [ #  # ]:          0 :         if (spec == NULL)
     518                 :            :                 return 0;
     519                 :            : 
     520                 :            :         /*
     521                 :            :          * IPv4 addresses are in big-endian byte order in item and in
     522                 :            :          * efx_spec
     523                 :            :          */
     524         [ #  # ]:          0 :         if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
     525                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
     526                 :          0 :                 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
     527         [ #  # ]:          0 :         } else if (mask->hdr.src_addr != 0) {
     528                 :          0 :                 goto fail_bad_mask;
     529                 :            :         }
     530                 :            : 
     531         [ #  # ]:          0 :         if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
     532                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
     533                 :          0 :                 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
     534         [ #  # ]:          0 :         } else if (mask->hdr.dst_addr != 0) {
     535                 :          0 :                 goto fail_bad_mask;
     536                 :            :         }
     537                 :            : 
     538         [ #  # ]:          0 :         if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
     539                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
     540                 :          0 :                 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
     541         [ #  # ]:          0 :         } else if (mask->hdr.next_proto_id != 0) {
     542                 :          0 :                 goto fail_bad_mask;
     543                 :            :         }
     544                 :            : 
     545                 :            :         return 0;
     546                 :            : 
     547                 :          0 : fail_bad_mask:
     548                 :          0 :         rte_flow_error_set(error, EINVAL,
     549                 :            :                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     550                 :            :                            "Bad mask in the IPV4 pattern item");
     551                 :          0 :         return -rte_errno;
     552                 :            : }
     553                 :            : 
     554                 :            : /**
     555                 :            :  * Convert IPv6 item to EFX filter specification.
     556                 :            :  *
     557                 :            :  * @param item[in]
     558                 :            :  *   Item specification. Only source and destination addresses and
     559                 :            :  *   next header fields are supported. If the mask is NULL, default
     560                 :            :  *   mask will be used. Ranging is not supported.
     561                 :            :  * @param efx_spec[in, out]
     562                 :            :  *   EFX filter specification to update.
     563                 :            :  * @param[out] error
     564                 :            :  *   Perform verbose error reporting if not NULL.
     565                 :            :  */
     566                 :            : static int
     567                 :          0 : sfc_flow_parse_ipv6(const struct rte_flow_item *item,
     568                 :            :                     struct sfc_flow_parse_ctx *parse_ctx,
     569                 :            :                     struct rte_flow_error *error)
     570                 :            : {
     571                 :            :         int rc;
     572                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     573                 :          0 :         const struct rte_flow_item_ipv6 *spec = NULL;
     574                 :          0 :         const struct rte_flow_item_ipv6 *mask = NULL;
     575                 :            :         const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
     576                 :          0 :         const struct rte_flow_item_ipv6 supp_mask = {
     577                 :            :                 .hdr = {
     578                 :            :                         .src_addr = RTE_IPV6_MASK_FULL,
     579                 :            :                         .dst_addr = RTE_IPV6_MASK_FULL,
     580                 :            :                         .proto = 0xff,
     581                 :            :                 }
     582                 :            :         };
     583                 :            : 
     584                 :          0 :         rc = sfc_flow_parse_init(item,
     585                 :            :                                  (const void **)&spec,
     586                 :            :                                  (const void **)&mask,
     587                 :            :                                  &supp_mask,
     588                 :            :                                  &rte_flow_item_ipv6_mask,
     589                 :            :                                  sizeof(struct rte_flow_item_ipv6),
     590                 :            :                                  error);
     591         [ #  # ]:          0 :         if (rc != 0)
     592                 :            :                 return rc;
     593                 :            : 
     594                 :            :         /*
     595                 :            :          * Filtering by IPv6 source and destination addresses requires
     596                 :            :          * the appropriate ETHER_TYPE in hardware filters
     597                 :            :          */
     598         [ #  # ]:          0 :         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
     599                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
     600                 :          0 :                 efx_spec->efs_ether_type = ether_type_ipv6;
     601         [ #  # ]:          0 :         } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
     602                 :          0 :                 rte_flow_error_set(error, EINVAL,
     603                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
     604                 :            :                         "Ethertype in pattern with IPV6 item should be appropriate");
     605                 :          0 :                 return -rte_errno;
     606                 :            :         }
     607                 :            : 
     608         [ #  # ]:          0 :         if (spec == NULL)
     609                 :            :                 return 0;
     610                 :            : 
     611                 :            :         /*
     612                 :            :          * IPv6 addresses are in big-endian byte order in item and in
     613                 :            :          * efx_spec
     614                 :            :          */
     615         [ #  # ]:          0 :         if (memcmp(&mask->hdr.src_addr, &supp_mask.hdr.src_addr,
     616                 :            :                    sizeof(mask->hdr.src_addr)) == 0) {
     617                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
     618                 :            : 
     619                 :            :                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
     620                 :            :                                  sizeof(spec->hdr.src_addr));
     621         [ #  # ]:          0 :                 rte_memcpy(&efx_spec->efs_rem_host, &spec->hdr.src_addr,
     622                 :            :                            sizeof(efx_spec->efs_rem_host));
     623         [ #  # ]:          0 :         } else if (!sfc_flow_is_zero(mask->hdr.src_addr.a,
     624                 :            :                                      sizeof(mask->hdr.src_addr))) {
     625                 :          0 :                 goto fail_bad_mask;
     626                 :            :         }
     627                 :            : 
     628         [ #  # ]:          0 :         if (memcmp(&mask->hdr.dst_addr, &supp_mask.hdr.dst_addr,
     629                 :            :                    sizeof(mask->hdr.dst_addr)) == 0) {
     630                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
     631                 :            : 
     632                 :            :                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
     633                 :            :                                  sizeof(spec->hdr.dst_addr));
     634         [ #  # ]:          0 :                 rte_memcpy(&efx_spec->efs_loc_host, &spec->hdr.dst_addr,
     635                 :            :                            sizeof(efx_spec->efs_loc_host));
     636         [ #  # ]:          0 :         } else if (!sfc_flow_is_zero(mask->hdr.dst_addr.a,
     637                 :            :                                      sizeof(mask->hdr.dst_addr))) {
     638                 :          0 :                 goto fail_bad_mask;
     639                 :            :         }
     640                 :            : 
     641         [ #  # ]:          0 :         if (mask->hdr.proto == supp_mask.hdr.proto) {
     642                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
     643                 :          0 :                 efx_spec->efs_ip_proto = spec->hdr.proto;
     644         [ #  # ]:          0 :         } else if (mask->hdr.proto != 0) {
     645                 :          0 :                 goto fail_bad_mask;
     646                 :            :         }
     647                 :            : 
     648                 :            :         return 0;
     649                 :            : 
     650                 :          0 : fail_bad_mask:
     651                 :          0 :         rte_flow_error_set(error, EINVAL,
     652                 :            :                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     653                 :            :                            "Bad mask in the IPV6 pattern item");
     654                 :          0 :         return -rte_errno;
     655                 :            : }
     656                 :            : 
     657                 :            : /**
     658                 :            :  * Convert TCP item to EFX filter specification.
     659                 :            :  *
     660                 :            :  * @param item[in]
     661                 :            :  *   Item specification. Only source and destination ports fields
     662                 :            :  *   are supported. If the mask is NULL, default mask will be used.
     663                 :            :  *   Ranging is not supported.
     664                 :            :  * @param efx_spec[in, out]
     665                 :            :  *   EFX filter specification to update.
     666                 :            :  * @param[out] error
     667                 :            :  *   Perform verbose error reporting if not NULL.
     668                 :            :  */
     669                 :            : static int
     670                 :          0 : sfc_flow_parse_tcp(const struct rte_flow_item *item,
     671                 :            :                    struct sfc_flow_parse_ctx *parse_ctx,
     672                 :            :                    struct rte_flow_error *error)
     673                 :            : {
     674                 :            :         int rc;
     675                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     676                 :          0 :         const struct rte_flow_item_tcp *spec = NULL;
     677                 :          0 :         const struct rte_flow_item_tcp *mask = NULL;
     678                 :          0 :         const struct rte_flow_item_tcp supp_mask = {
     679                 :            :                 .hdr = {
     680                 :            :                         .src_port = 0xffff,
     681                 :            :                         .dst_port = 0xffff,
     682                 :            :                 }
     683                 :            :         };
     684                 :            : 
     685                 :          0 :         rc = sfc_flow_parse_init(item,
     686                 :            :                                  (const void **)&spec,
     687                 :            :                                  (const void **)&mask,
     688                 :            :                                  &supp_mask,
     689                 :            :                                  &rte_flow_item_tcp_mask,
     690                 :            :                                  sizeof(struct rte_flow_item_tcp),
     691                 :            :                                  error);
     692         [ #  # ]:          0 :         if (rc != 0)
     693                 :            :                 return rc;
     694                 :            : 
     695                 :            :         /*
     696                 :            :          * Filtering by TCP source and destination ports requires
     697                 :            :          * the appropriate IP_PROTO in hardware filters
     698                 :            :          */
     699         [ #  # ]:          0 :         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
     700                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
     701                 :          0 :                 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
     702         [ #  # ]:          0 :         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
     703                 :          0 :                 rte_flow_error_set(error, EINVAL,
     704                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
     705                 :            :                         "IP proto in pattern with TCP item should be appropriate");
     706                 :          0 :                 return -rte_errno;
     707                 :            :         }
     708                 :            : 
     709         [ #  # ]:          0 :         if (spec == NULL)
     710                 :            :                 return 0;
     711                 :            : 
     712                 :            :         /*
     713                 :            :          * Source and destination ports are in big-endian byte order in item and
     714                 :            :          * in little-endian in efx_spec, so byte swap is used
     715                 :            :          */
     716         [ #  # ]:          0 :         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
     717                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
     718         [ #  # ]:          0 :                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
     719         [ #  # ]:          0 :         } else if (mask->hdr.src_port != 0) {
     720                 :          0 :                 goto fail_bad_mask;
     721                 :            :         }
     722                 :            : 
     723         [ #  # ]:          0 :         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
     724                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
     725         [ #  # ]:          0 :                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
     726         [ #  # ]:          0 :         } else if (mask->hdr.dst_port != 0) {
     727                 :          0 :                 goto fail_bad_mask;
     728                 :            :         }
     729                 :            : 
     730                 :            :         return 0;
     731                 :            : 
     732                 :          0 : fail_bad_mask:
     733                 :          0 :         rte_flow_error_set(error, EINVAL,
     734                 :            :                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     735                 :            :                            "Bad mask in the TCP pattern item");
     736                 :          0 :         return -rte_errno;
     737                 :            : }
     738                 :            : 
     739                 :            : /**
     740                 :            :  * Convert UDP item to EFX filter specification.
     741                 :            :  *
     742                 :            :  * @param item[in]
     743                 :            :  *   Item specification. Only source and destination ports fields
     744                 :            :  *   are supported. If the mask is NULL, default mask will be used.
     745                 :            :  *   Ranging is not supported.
     746                 :            :  * @param efx_spec[in, out]
     747                 :            :  *   EFX filter specification to update.
     748                 :            :  * @param[out] error
     749                 :            :  *   Perform verbose error reporting if not NULL.
     750                 :            :  */
     751                 :            : static int
     752                 :          0 : sfc_flow_parse_udp(const struct rte_flow_item *item,
     753                 :            :                    struct sfc_flow_parse_ctx *parse_ctx,
     754                 :            :                    struct rte_flow_error *error)
     755                 :            : {
     756                 :            :         int rc;
     757                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     758                 :          0 :         const struct rte_flow_item_udp *spec = NULL;
     759                 :          0 :         const struct rte_flow_item_udp *mask = NULL;
     760                 :          0 :         const struct rte_flow_item_udp supp_mask = {
     761                 :            :                 .hdr = {
     762                 :            :                         .src_port = 0xffff,
     763                 :            :                         .dst_port = 0xffff,
     764                 :            :                 }
     765                 :            :         };
     766                 :            : 
     767                 :          0 :         rc = sfc_flow_parse_init(item,
     768                 :            :                                  (const void **)&spec,
     769                 :            :                                  (const void **)&mask,
     770                 :            :                                  &supp_mask,
     771                 :            :                                  &rte_flow_item_udp_mask,
     772                 :            :                                  sizeof(struct rte_flow_item_udp),
     773                 :            :                                  error);
     774         [ #  # ]:          0 :         if (rc != 0)
     775                 :            :                 return rc;
     776                 :            : 
     777                 :            :         /*
     778                 :            :          * Filtering by UDP source and destination ports requires
     779                 :            :          * the appropriate IP_PROTO in hardware filters
     780                 :            :          */
     781         [ #  # ]:          0 :         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
     782                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
     783                 :          0 :                 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
     784         [ #  # ]:          0 :         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
     785                 :          0 :                 rte_flow_error_set(error, EINVAL,
     786                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
     787                 :            :                         "IP proto in pattern with UDP item should be appropriate");
     788                 :          0 :                 return -rte_errno;
     789                 :            :         }
     790                 :            : 
     791         [ #  # ]:          0 :         if (spec == NULL)
     792                 :            :                 return 0;
     793                 :            : 
     794                 :            :         /*
     795                 :            :          * Source and destination ports are in big-endian byte order in item and
     796                 :            :          * in little-endian in efx_spec, so byte swap is used
     797                 :            :          */
     798         [ #  # ]:          0 :         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
     799                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
     800         [ #  # ]:          0 :                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
     801         [ #  # ]:          0 :         } else if (mask->hdr.src_port != 0) {
     802                 :          0 :                 goto fail_bad_mask;
     803                 :            :         }
     804                 :            : 
     805         [ #  # ]:          0 :         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
     806                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
     807         [ #  # ]:          0 :                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
     808         [ #  # ]:          0 :         } else if (mask->hdr.dst_port != 0) {
     809                 :          0 :                 goto fail_bad_mask;
     810                 :            :         }
     811                 :            : 
     812                 :            :         return 0;
     813                 :            : 
     814                 :          0 : fail_bad_mask:
     815                 :          0 :         rte_flow_error_set(error, EINVAL,
     816                 :            :                            RTE_FLOW_ERROR_TYPE_ITEM, item,
     817                 :            :                            "Bad mask in the UDP pattern item");
     818                 :          0 :         return -rte_errno;
     819                 :            : }
     820                 :            : 
     821                 :            : /*
     822                 :            :  * Filters for encapsulated packets match based on the EtherType and IP
     823                 :            :  * protocol in the outer frame.
     824                 :            :  */
     825                 :            : static int
     826                 :          0 : sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item,
     827                 :            :                                         efx_filter_spec_t *efx_spec,
     828                 :            :                                         uint8_t ip_proto,
     829                 :            :                                         struct rte_flow_error *error)
     830                 :            : {
     831         [ #  # ]:          0 :         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
     832                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
     833                 :          0 :                 efx_spec->efs_ip_proto = ip_proto;
     834         [ #  # ]:          0 :         } else if (efx_spec->efs_ip_proto != ip_proto) {
     835      [ #  #  # ]:          0 :                 switch (ip_proto) {
     836                 :          0 :                 case EFX_IPPROTO_UDP:
     837                 :          0 :                         rte_flow_error_set(error, EINVAL,
     838                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
     839                 :            :                                 "Outer IP header protocol must be UDP "
     840                 :            :                                 "in VxLAN/GENEVE pattern");
     841                 :          0 :                         return -rte_errno;
     842                 :            : 
     843                 :          0 :                 case EFX_IPPROTO_GRE:
     844                 :          0 :                         rte_flow_error_set(error, EINVAL,
     845                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
     846                 :            :                                 "Outer IP header protocol must be GRE "
     847                 :            :                                 "in NVGRE pattern");
     848                 :          0 :                         return -rte_errno;
     849                 :            : 
     850                 :          0 :                 default:
     851                 :          0 :                         rte_flow_error_set(error, EINVAL,
     852                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
     853                 :            :                                 "Only VxLAN/GENEVE/NVGRE tunneling patterns "
     854                 :            :                                 "are supported");
     855                 :          0 :                         return -rte_errno;
     856                 :            :                 }
     857                 :            :         }
     858                 :            : 
     859         [ #  # ]:          0 :         if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE &&
     860   [ #  #  #  # ]:          0 :             efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 &&
     861                 :            :             efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) {
     862                 :          0 :                 rte_flow_error_set(error, EINVAL,
     863                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
     864                 :            :                         "Outer frame EtherType in pattern with tunneling "
     865                 :            :                         "must be IPv4 or IPv6");
     866                 :          0 :                 return -rte_errno;
     867                 :            :         }
     868                 :            : 
     869                 :            :         return 0;
     870                 :            : }
     871                 :            : 
     872                 :            : static int
     873                 :          0 : sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec,
     874                 :            :                                   const uint8_t *vni_or_vsid_val,
     875                 :            :                                   const uint8_t *vni_or_vsid_mask,
     876                 :            :                                   const struct rte_flow_item *item,
     877                 :            :                                   struct rte_flow_error *error)
     878                 :            : {
     879                 :          0 :         const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = {
     880                 :            :                 0xff, 0xff, 0xff
     881                 :            :         };
     882                 :            : 
     883         [ #  # ]:          0 :         if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask,
     884                 :            :                    EFX_VNI_OR_VSID_LEN) == 0) {
     885                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
     886         [ #  # ]:          0 :                 rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val,
     887                 :            :                            EFX_VNI_OR_VSID_LEN);
     888         [ #  # ]:          0 :         } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) {
     889                 :          0 :                 rte_flow_error_set(error, EINVAL,
     890                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
     891                 :            :                                    "Unsupported VNI/VSID mask");
     892                 :          0 :                 return -rte_errno;
     893                 :            :         }
     894                 :            : 
     895                 :            :         return 0;
     896                 :            : }
     897                 :            : 
     898                 :            : /**
     899                 :            :  * Convert VXLAN item to EFX filter specification.
     900                 :            :  *
     901                 :            :  * @param item[in]
     902                 :            :  *   Item specification. Only VXLAN network identifier field is supported.
     903                 :            :  *   If the mask is NULL, default mask will be used.
     904                 :            :  *   Ranging is not supported.
     905                 :            :  * @param efx_spec[in, out]
     906                 :            :  *   EFX filter specification to update.
     907                 :            :  * @param[out] error
     908                 :            :  *   Perform verbose error reporting if not NULL.
     909                 :            :  */
     910                 :            : static int
     911                 :          0 : sfc_flow_parse_vxlan(const struct rte_flow_item *item,
     912                 :            :                      struct sfc_flow_parse_ctx *parse_ctx,
     913                 :            :                      struct rte_flow_error *error)
     914                 :            : {
     915                 :            :         int rc;
     916                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     917                 :          0 :         const struct rte_flow_item_vxlan *spec = NULL;
     918                 :          0 :         const struct rte_flow_item_vxlan *mask = NULL;
     919                 :          0 :         const struct rte_flow_item_vxlan supp_mask = {
     920                 :            :                 .hdr.vni = { 0xff, 0xff, 0xff }
     921                 :            :         };
     922                 :            : 
     923                 :          0 :         rc = sfc_flow_parse_init(item,
     924                 :            :                                  (const void **)&spec,
     925                 :            :                                  (const void **)&mask,
     926                 :            :                                  &supp_mask,
     927                 :            :                                  &rte_flow_item_vxlan_mask,
     928                 :            :                                  sizeof(struct rte_flow_item_vxlan),
     929                 :            :                                  error);
     930         [ #  # ]:          0 :         if (rc != 0)
     931                 :            :                 return rc;
     932                 :            : 
     933                 :          0 :         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
     934                 :            :                                                      EFX_IPPROTO_UDP, error);
     935         [ #  # ]:          0 :         if (rc != 0)
     936                 :            :                 return rc;
     937                 :            : 
     938                 :          0 :         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
     939                 :          0 :         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
     940                 :            : 
     941         [ #  # ]:          0 :         if (spec == NULL)
     942                 :            :                 return 0;
     943                 :            : 
     944                 :          0 :         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->hdr.vni,
     945                 :          0 :                                                mask->hdr.vni, item, error);
     946                 :            : 
     947                 :          0 :         return rc;
     948                 :            : }
     949                 :            : 
     950                 :            : /**
     951                 :            :  * Convert GENEVE item to EFX filter specification.
     952                 :            :  *
     953                 :            :  * @param item[in]
     954                 :            :  *   Item specification. Only Virtual Network Identifier and protocol type
     955                 :            :  *   fields are supported. But protocol type can be only Ethernet (0x6558).
     956                 :            :  *   If the mask is NULL, default mask will be used.
     957                 :            :  *   Ranging is not supported.
     958                 :            :  * @param efx_spec[in, out]
     959                 :            :  *   EFX filter specification to update.
     960                 :            :  * @param[out] error
     961                 :            :  *   Perform verbose error reporting if not NULL.
     962                 :            :  */
     963                 :            : static int
     964                 :          0 : sfc_flow_parse_geneve(const struct rte_flow_item *item,
     965                 :            :                       struct sfc_flow_parse_ctx *parse_ctx,
     966                 :            :                       struct rte_flow_error *error)
     967                 :            : {
     968                 :            :         int rc;
     969                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
     970                 :          0 :         const struct rte_flow_item_geneve *spec = NULL;
     971                 :          0 :         const struct rte_flow_item_geneve *mask = NULL;
     972                 :          0 :         const struct rte_flow_item_geneve supp_mask = {
     973                 :            :                 .protocol = RTE_BE16(0xffff),
     974                 :            :                 .vni = { 0xff, 0xff, 0xff }
     975                 :            :         };
     976                 :            : 
     977                 :          0 :         rc = sfc_flow_parse_init(item,
     978                 :            :                                  (const void **)&spec,
     979                 :            :                                  (const void **)&mask,
     980                 :            :                                  &supp_mask,
     981                 :            :                                  &rte_flow_item_geneve_mask,
     982                 :            :                                  sizeof(struct rte_flow_item_geneve),
     983                 :            :                                  error);
     984         [ #  # ]:          0 :         if (rc != 0)
     985                 :            :                 return rc;
     986                 :            : 
     987                 :          0 :         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
     988                 :            :                                                      EFX_IPPROTO_UDP, error);
     989         [ #  # ]:          0 :         if (rc != 0)
     990                 :            :                 return rc;
     991                 :            : 
     992                 :          0 :         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
     993                 :          0 :         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
     994                 :            : 
     995         [ #  # ]:          0 :         if (spec == NULL)
     996                 :            :                 return 0;
     997                 :            : 
     998         [ #  # ]:          0 :         if (mask->protocol == supp_mask.protocol) {
     999         [ #  # ]:          0 :                 if (spec->protocol != rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB)) {
    1000                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1001                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
    1002                 :            :                                 "GENEVE encap. protocol must be Ethernet "
    1003                 :            :                                 "(0x6558) in the GENEVE pattern item");
    1004                 :          0 :                         return -rte_errno;
    1005                 :            :                 }
    1006         [ #  # ]:          0 :         } else if (mask->protocol != 0) {
    1007                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1008                 :            :                         RTE_FLOW_ERROR_TYPE_ITEM, item,
    1009                 :            :                         "Unsupported mask for GENEVE encap. protocol");
    1010                 :          0 :                 return -rte_errno;
    1011                 :            :         }
    1012                 :            : 
    1013                 :          0 :         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
    1014                 :          0 :                                                mask->vni, item, error);
    1015                 :            : 
    1016                 :          0 :         return rc;
    1017                 :            : }
    1018                 :            : 
    1019                 :            : /**
    1020                 :            :  * Convert NVGRE item to EFX filter specification.
    1021                 :            :  *
    1022                 :            :  * @param item[in]
    1023                 :            :  *   Item specification. Only virtual subnet ID field is supported.
    1024                 :            :  *   If the mask is NULL, default mask will be used.
    1025                 :            :  *   Ranging is not supported.
    1026                 :            :  * @param efx_spec[in, out]
    1027                 :            :  *   EFX filter specification to update.
    1028                 :            :  * @param[out] error
    1029                 :            :  *   Perform verbose error reporting if not NULL.
    1030                 :            :  */
    1031                 :            : static int
    1032                 :          0 : sfc_flow_parse_nvgre(const struct rte_flow_item *item,
    1033                 :            :                      struct sfc_flow_parse_ctx *parse_ctx,
    1034                 :            :                      struct rte_flow_error *error)
    1035                 :            : {
    1036                 :            :         int rc;
    1037                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
    1038                 :          0 :         const struct rte_flow_item_nvgre *spec = NULL;
    1039                 :          0 :         const struct rte_flow_item_nvgre *mask = NULL;
    1040                 :          0 :         const struct rte_flow_item_nvgre supp_mask = {
    1041                 :            :                 .tni = { 0xff, 0xff, 0xff }
    1042                 :            :         };
    1043                 :            : 
    1044                 :          0 :         rc = sfc_flow_parse_init(item,
    1045                 :            :                                  (const void **)&spec,
    1046                 :            :                                  (const void **)&mask,
    1047                 :            :                                  &supp_mask,
    1048                 :            :                                  &rte_flow_item_nvgre_mask,
    1049                 :            :                                  sizeof(struct rte_flow_item_nvgre),
    1050                 :            :                                  error);
    1051         [ #  # ]:          0 :         if (rc != 0)
    1052                 :            :                 return rc;
    1053                 :            : 
    1054                 :          0 :         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
    1055                 :            :                                                      EFX_IPPROTO_GRE, error);
    1056         [ #  # ]:          0 :         if (rc != 0)
    1057                 :            :                 return rc;
    1058                 :            : 
    1059                 :          0 :         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
    1060                 :          0 :         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
    1061                 :            : 
    1062         [ #  # ]:          0 :         if (spec == NULL)
    1063                 :            :                 return 0;
    1064                 :            : 
    1065                 :          0 :         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->tni,
    1066                 :          0 :                                                mask->tni, item, error);
    1067                 :            : 
    1068                 :          0 :         return rc;
    1069                 :            : }
    1070                 :            : 
    1071                 :            : /**
    1072                 :            :  * Convert PPPoEx item to EFX filter specification.
    1073                 :            :  *
    1074                 :            :  * @param item[in]
    1075                 :            :  *   Item specification.
    1076                 :            :  *   Matching on PPPoEx fields is not supported.
    1077                 :            :  *   This item can only be used to set or validate the EtherType filter.
    1078                 :            :  *   Only zero masks are allowed.
    1079                 :            :  *   Ranging is not supported.
    1080                 :            :  * @param efx_spec[in, out]
    1081                 :            :  *   EFX filter specification to update.
    1082                 :            :  * @param[out] error
    1083                 :            :  *   Perform verbose error reporting if not NULL.
    1084                 :            :  */
    1085                 :            : static int
    1086                 :          0 : sfc_flow_parse_pppoex(const struct rte_flow_item *item,
    1087                 :            :                       struct sfc_flow_parse_ctx *parse_ctx,
    1088                 :            :                       struct rte_flow_error *error)
    1089                 :            : {
    1090                 :          0 :         efx_filter_spec_t *efx_spec = parse_ctx->filter;
    1091                 :          0 :         const struct rte_flow_item_pppoe *spec = NULL;
    1092                 :          0 :         const struct rte_flow_item_pppoe *mask = NULL;
    1093                 :          0 :         const struct rte_flow_item_pppoe supp_mask = {};
    1094                 :          0 :         const struct rte_flow_item_pppoe def_mask = {};
    1095                 :            :         uint16_t ether_type;
    1096                 :            :         int rc;
    1097                 :            : 
    1098                 :          0 :         rc = sfc_flow_parse_init(item,
    1099                 :            :                                  (const void **)&spec,
    1100                 :            :                                  (const void **)&mask,
    1101                 :            :                                  &supp_mask,
    1102                 :            :                                  &def_mask,
    1103                 :            :                                  sizeof(struct rte_flow_item_pppoe),
    1104                 :            :                                  error);
    1105         [ #  # ]:          0 :         if (rc != 0)
    1106                 :            :                 return rc;
    1107                 :            : 
    1108         [ #  # ]:          0 :         if (item->type == RTE_FLOW_ITEM_TYPE_PPPOED)
    1109                 :            :                 ether_type = RTE_ETHER_TYPE_PPPOE_DISCOVERY;
    1110                 :            :         else
    1111                 :            :                 ether_type = RTE_ETHER_TYPE_PPPOE_SESSION;
    1112                 :            : 
    1113         [ #  # ]:          0 :         if ((efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE) != 0) {
    1114         [ #  # ]:          0 :                 if (efx_spec->efs_ether_type != ether_type) {
    1115                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1116                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
    1117                 :            :                                            "Invalid EtherType for a PPPoE flow item");
    1118                 :          0 :                         return -rte_errno;
    1119                 :            :                 }
    1120                 :            :         } else {
    1121                 :          0 :                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
    1122                 :          0 :                 efx_spec->efs_ether_type = ether_type;
    1123                 :            :         }
    1124                 :            : 
    1125                 :            :         return 0;
    1126                 :            : }
    1127                 :            : 
    1128                 :            : static const struct sfc_flow_item sfc_flow_items[] = {
    1129                 :            :         {
    1130                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VOID,
    1131                 :            :                 .name = "VOID",
    1132                 :            :                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
    1133                 :            :                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
    1134                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1135                 :            :                 .parse = sfc_flow_parse_void,
    1136                 :            :         },
    1137                 :            :         {
    1138                 :            :                 .type = RTE_FLOW_ITEM_TYPE_ETH,
    1139                 :            :                 .name = "ETH",
    1140                 :            :                 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
    1141                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    1142                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1143                 :            :                 .parse = sfc_flow_parse_eth,
    1144                 :            :         },
    1145                 :            :         {
    1146                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
    1147                 :            :                 .name = "VLAN",
    1148                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    1149                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    1150                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1151                 :            :                 .parse = sfc_flow_parse_vlan,
    1152                 :            :         },
    1153                 :            :         {
    1154                 :            :                 .type = RTE_FLOW_ITEM_TYPE_PPPOED,
    1155                 :            :                 .name = "PPPOED",
    1156                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    1157                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    1158                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1159                 :            :                 .parse = sfc_flow_parse_pppoex,
    1160                 :            :         },
    1161                 :            :         {
    1162                 :            :                 .type = RTE_FLOW_ITEM_TYPE_PPPOES,
    1163                 :            :                 .name = "PPPOES",
    1164                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    1165                 :            :                 .layer = SFC_FLOW_ITEM_L2,
    1166                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1167                 :            :                 .parse = sfc_flow_parse_pppoex,
    1168                 :            :         },
    1169                 :            :         {
    1170                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
    1171                 :            :                 .name = "IPV4",
    1172                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    1173                 :            :                 .layer = SFC_FLOW_ITEM_L3,
    1174                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1175                 :            :                 .parse = sfc_flow_parse_ipv4,
    1176                 :            :         },
    1177                 :            :         {
    1178                 :            :                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
    1179                 :            :                 .name = "IPV6",
    1180                 :            :                 .prev_layer = SFC_FLOW_ITEM_L2,
    1181                 :            :                 .layer = SFC_FLOW_ITEM_L3,
    1182                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1183                 :            :                 .parse = sfc_flow_parse_ipv6,
    1184                 :            :         },
    1185                 :            :         {
    1186                 :            :                 .type = RTE_FLOW_ITEM_TYPE_TCP,
    1187                 :            :                 .name = "TCP",
    1188                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    1189                 :            :                 .layer = SFC_FLOW_ITEM_L4,
    1190                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1191                 :            :                 .parse = sfc_flow_parse_tcp,
    1192                 :            :         },
    1193                 :            :         {
    1194                 :            :                 .type = RTE_FLOW_ITEM_TYPE_UDP,
    1195                 :            :                 .name = "UDP",
    1196                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    1197                 :            :                 .layer = SFC_FLOW_ITEM_L4,
    1198                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1199                 :            :                 .parse = sfc_flow_parse_udp,
    1200                 :            :         },
    1201                 :            :         {
    1202                 :            :                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
    1203                 :            :                 .name = "VXLAN",
    1204                 :            :                 .prev_layer = SFC_FLOW_ITEM_L4,
    1205                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    1206                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1207                 :            :                 .parse = sfc_flow_parse_vxlan,
    1208                 :            :         },
    1209                 :            :         {
    1210                 :            :                 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
    1211                 :            :                 .name = "GENEVE",
    1212                 :            :                 .prev_layer = SFC_FLOW_ITEM_L4,
    1213                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    1214                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1215                 :            :                 .parse = sfc_flow_parse_geneve,
    1216                 :            :         },
    1217                 :            :         {
    1218                 :            :                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
    1219                 :            :                 .name = "NVGRE",
    1220                 :            :                 .prev_layer = SFC_FLOW_ITEM_L3,
    1221                 :            :                 .layer = SFC_FLOW_ITEM_START_LAYER,
    1222                 :            :                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
    1223                 :            :                 .parse = sfc_flow_parse_nvgre,
    1224                 :            :         },
    1225                 :            : };
    1226                 :            : 
    1227                 :            : /*
    1228                 :            :  * Protocol-independent flow API support
    1229                 :            :  */
    1230                 :            : static int
    1231                 :          0 : sfc_flow_parse_attr(struct sfc_adapter *sa,
    1232                 :            :                     const struct rte_flow_attr *attr,
    1233                 :            :                     struct rte_flow *flow,
    1234                 :            :                     struct rte_flow_error *error)
    1235                 :            : {
    1236                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    1237                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1238                 :            :         struct sfc_flow_spec_mae *spec_mae = &spec->mae;
    1239                 :            :         struct sfc_mae *mae = &sa->mae;
    1240                 :            : 
    1241         [ #  # ]:          0 :         if (attr == NULL) {
    1242                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1243                 :            :                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
    1244                 :            :                                    "NULL attribute");
    1245                 :          0 :                 return -rte_errno;
    1246                 :            :         }
    1247         [ #  # ]:          0 :         if (attr->group != 0) {
    1248                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    1249                 :            :                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
    1250                 :            :                                    "Groups are not supported");
    1251                 :          0 :                 return -rte_errno;
    1252                 :            :         }
    1253         [ #  # ]:          0 :         if (attr->egress != 0 && attr->transfer == 0) {
    1254                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    1255                 :            :                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
    1256                 :            :                                    "Egress is not supported");
    1257                 :          0 :                 return -rte_errno;
    1258                 :            :         }
    1259         [ #  # ]:          0 :         if (attr->ingress == 0 && attr->transfer == 0) {
    1260                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    1261                 :            :                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
    1262                 :            :                                    "Ingress is compulsory");
    1263                 :          0 :                 return -rte_errno;
    1264                 :            :         }
    1265         [ #  # ]:          0 :         if (attr->transfer == 0) {
    1266         [ #  # ]:          0 :                 if (attr->priority != 0) {
    1267                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1268                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    1269                 :            :                                            attr, "Priorities are unsupported");
    1270                 :          0 :                         return -rte_errno;
    1271                 :            :                 }
    1272                 :          0 :                 spec->type = SFC_FLOW_SPEC_FILTER;
    1273                 :          0 :                 spec_filter->template.efs_flags |= EFX_FILTER_FLAG_RX;
    1274                 :          0 :                 spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
    1275                 :          0 :                 spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
    1276                 :            :         } else {
    1277         [ #  # ]:          0 :                 if (mae->status != SFC_MAE_STATUS_ADMIN) {
    1278                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1279                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
    1280                 :            :                                            attr, "Transfer is not supported");
    1281                 :          0 :                         return -rte_errno;
    1282                 :            :                 }
    1283         [ #  # ]:          0 :                 if (attr->priority > mae->nb_action_rule_prios_max) {
    1284                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1285                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    1286                 :            :                                            attr, "Unsupported priority level");
    1287                 :          0 :                         return -rte_errno;
    1288                 :            :                 }
    1289                 :          0 :                 spec->type = SFC_FLOW_SPEC_MAE;
    1290                 :          0 :                 spec_mae->priority = attr->priority;
    1291                 :          0 :                 spec_mae->action_rule = NULL;
    1292                 :            :         }
    1293                 :            : 
    1294                 :            :         return 0;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : /* Get item from array sfc_flow_items */
    1298                 :            : static const struct sfc_flow_item *
    1299                 :            : sfc_flow_get_item(const struct sfc_flow_item *items,
    1300                 :            :                   unsigned int nb_items,
    1301                 :            :                   enum rte_flow_item_type type)
    1302                 :            : {
    1303                 :            :         unsigned int i;
    1304                 :            : 
    1305         [ #  # ]:          0 :         for (i = 0; i < nb_items; i++)
    1306         [ #  # ]:          0 :                 if (items[i].type == type)
    1307                 :            :                         return &items[i];
    1308                 :            : 
    1309                 :            :         return NULL;
    1310                 :            : }
    1311                 :            : 
    1312                 :            : int
    1313                 :          0 : sfc_flow_parse_pattern(struct sfc_adapter *sa,
    1314                 :            :                        const struct sfc_flow_item *flow_items,
    1315                 :            :                        unsigned int nb_flow_items,
    1316                 :            :                        const struct rte_flow_item pattern[],
    1317                 :            :                        struct sfc_flow_parse_ctx *parse_ctx,
    1318                 :            :                        struct rte_flow_error *error)
    1319                 :            : {
    1320                 :            :         int rc;
    1321                 :            :         unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
    1322                 :            :         boolean_t is_ifrm = B_FALSE;
    1323                 :            :         const struct sfc_flow_item *item;
    1324                 :            : 
    1325         [ #  # ]:          0 :         if (pattern == NULL) {
    1326                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1327                 :            :                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
    1328                 :            :                                    "NULL pattern");
    1329                 :          0 :                 return -rte_errno;
    1330                 :            :         }
    1331                 :            : 
    1332         [ #  # ]:          0 :         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
    1333                 :            :                 item = sfc_flow_get_item(flow_items, nb_flow_items,
    1334                 :            :                                          pattern->type);
    1335         [ #  # ]:          0 :                 if (item == NULL) {
    1336                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1337                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
    1338                 :            :                                            "Unsupported pattern item");
    1339                 :          0 :                         return -rte_errno;
    1340                 :            :                 }
    1341                 :            : 
    1342                 :            :                 /*
    1343                 :            :                  * Omitting one or several protocol layers at the beginning
    1344                 :            :                  * of pattern is supported
    1345                 :            :                  */
    1346   [ #  #  #  # ]:          0 :                 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
    1347         [ #  # ]:          0 :                     prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
    1348                 :            :                     item->prev_layer != prev_layer) {
    1349                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1350                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
    1351                 :            :                                            "Unexpected sequence of pattern items");
    1352                 :          0 :                         return -rte_errno;
    1353                 :            :                 }
    1354                 :            : 
    1355                 :            :                 /*
    1356                 :            :                  * Allow only VOID and ETH pattern items in the inner frame.
    1357                 :            :                  * Also check that there is only one tunneling protocol.
    1358                 :            :                  */
    1359      [ #  #  # ]:          0 :                 switch (item->type) {
    1360                 :            :                 case RTE_FLOW_ITEM_TYPE_VOID:
    1361                 :            :                 case RTE_FLOW_ITEM_TYPE_ETH:
    1362                 :            :                         break;
    1363                 :            : 
    1364                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    1365                 :            :                 case RTE_FLOW_ITEM_TYPE_GENEVE:
    1366                 :            :                 case RTE_FLOW_ITEM_TYPE_NVGRE:
    1367         [ #  # ]:          0 :                         if (is_ifrm) {
    1368                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    1369                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
    1370                 :            :                                         pattern,
    1371                 :            :                                         "More than one tunneling protocol");
    1372                 :          0 :                                 return -rte_errno;
    1373                 :            :                         }
    1374                 :            :                         is_ifrm = B_TRUE;
    1375                 :            :                         break;
    1376                 :            : 
    1377                 :          0 :                 default:
    1378   [ #  #  #  # ]:          0 :                         if (parse_ctx->type == SFC_FLOW_PARSE_CTX_FILTER &&
    1379                 :            :                             is_ifrm) {
    1380                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    1381                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM,
    1382                 :            :                                         pattern,
    1383                 :            :                                         "There is an unsupported pattern item "
    1384                 :            :                                         "in the inner frame");
    1385                 :          0 :                                 return -rte_errno;
    1386                 :            :                         }
    1387                 :            :                         break;
    1388                 :            :                 }
    1389                 :            : 
    1390         [ #  # ]:          0 :                 if (parse_ctx->type != item->ctx_type) {
    1391                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1392                 :            :                                         RTE_FLOW_ERROR_TYPE_ITEM, pattern,
    1393                 :            :                                         "Parse context type mismatch");
    1394                 :          0 :                         return -rte_errno;
    1395                 :            :                 }
    1396                 :            : 
    1397                 :          0 :                 rc = item->parse(pattern, parse_ctx, error);
    1398         [ #  # ]:          0 :                 if (rc != 0) {
    1399                 :          0 :                         sfc_err(sa, "failed to parse item %s: %s",
    1400                 :            :                                 item->name, strerror(-rc));
    1401                 :          0 :                         return rc;
    1402                 :            :                 }
    1403                 :            : 
    1404         [ #  # ]:          0 :                 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
    1405                 :            :                         prev_layer = item->layer;
    1406                 :            :         }
    1407                 :            : 
    1408                 :            :         return 0;
    1409                 :            : }
    1410                 :            : 
    1411                 :            : static int
    1412                 :          0 : sfc_flow_parse_queue(struct sfc_adapter *sa,
    1413                 :            :                      const struct rte_flow_action_queue *queue,
    1414                 :            :                      struct rte_flow *flow)
    1415                 :            : {
    1416                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    1417                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1418                 :            :         struct sfc_rxq *rxq;
    1419                 :            :         struct sfc_rxq_info *rxq_info;
    1420                 :            : 
    1421         [ #  # ]:          0 :         if (queue->index >= sfc_sa2shared(sa)->ethdev_rxq_count)
    1422                 :            :                 return -EINVAL;
    1423                 :            : 
    1424                 :          0 :         rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, queue->index);
    1425         [ #  # ]:          0 :         spec_filter->template.efs_dmaq_id = (uint16_t)rxq->hw_index;
    1426                 :            : 
    1427                 :          0 :         rxq_info = &sfc_sa2shared(sa)->rxq_info[queue->index];
    1428                 :            : 
    1429         [ #  # ]:          0 :         if ((rxq_info->rxq_flags & SFC_RXQ_FLAG_RSS_HASH) != 0) {
    1430                 :            :                 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
    1431                 :            :                 struct sfc_rss *ethdev_rss = &sas->rss;
    1432                 :            : 
    1433                 :          0 :                 spec_filter->template.efs_flags |= EFX_FILTER_FLAG_RX_RSS;
    1434                 :          0 :                 spec_filter->rss_ctx = &ethdev_rss->dummy_ctx;
    1435                 :            :         }
    1436                 :            : 
    1437                 :            :         return 0;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : static int
    1441                 :          0 : sfc_flow_parse_rss(struct sfc_adapter *sa,
    1442                 :            :                    const struct rte_flow_action_rss *action_rss,
    1443                 :            :                    struct rte_flow *flow)
    1444                 :            : {
    1445                 :            :         struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
    1446                 :            :         struct sfc_flow_rss_conf conf;
    1447                 :            :         uint16_t sw_qid_min;
    1448                 :            :         struct sfc_rxq *rxq;
    1449                 :            :         int rc;
    1450                 :            : 
    1451                 :          0 :         spec_filter->template.efs_flags |= EFX_FILTER_FLAG_RX_RSS;
    1452                 :            : 
    1453                 :          0 :         rc = sfc_flow_rss_parse_conf(sa, action_rss, &conf, &sw_qid_min);
    1454         [ #  # ]:          0 :         if (rc != 0)
    1455                 :          0 :                 return -rc;
    1456                 :            : 
    1457                 :          0 :         rxq = sfc_rxq_ctrl_by_ethdev_qid(sa, sw_qid_min);
    1458                 :          0 :         spec_filter->template.efs_dmaq_id = rxq->hw_index;
    1459                 :            : 
    1460                 :          0 :         spec_filter->rss_ctx = sfc_flow_rss_ctx_reuse(sa, &conf, sw_qid_min,
    1461                 :          0 :                                                       action_rss->queue);
    1462         [ #  # ]:          0 :         if (spec_filter->rss_ctx != NULL)
    1463                 :            :                 return 0;
    1464                 :            : 
    1465                 :          0 :         rc = sfc_flow_rss_ctx_add(sa, &conf, sw_qid_min, action_rss->queue,
    1466                 :            :                                   &spec_filter->rss_ctx);
    1467         [ #  # ]:          0 :         if (rc != 0)
    1468                 :          0 :                 return -rc;
    1469                 :            : 
    1470                 :            :         return 0;
    1471                 :            : }
    1472                 :            : 
    1473                 :            : static int
    1474                 :          0 : sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec,
    1475                 :            :                     unsigned int filters_count)
    1476                 :            : {
    1477                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1478                 :            :         unsigned int i;
    1479                 :            :         int ret = 0;
    1480                 :            : 
    1481         [ #  # ]:          0 :         for (i = 0; i < filters_count; i++) {
    1482                 :            :                 int rc;
    1483                 :            : 
    1484                 :          0 :                 rc = efx_filter_remove(sa->nic, &spec_filter->filters[i]);
    1485         [ #  # ]:          0 :                 if (ret == 0 && rc != 0) {
    1486                 :          0 :                         sfc_err(sa, "failed to remove filter specification "
    1487                 :            :                                 "(rc = %d)", rc);
    1488                 :            :                         ret = rc;
    1489                 :            :                 }
    1490                 :            :         }
    1491                 :            : 
    1492                 :          0 :         return ret;
    1493                 :            : }
    1494                 :            : 
    1495                 :            : static int
    1496                 :          0 : sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
    1497                 :            : {
    1498                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1499                 :            :         unsigned int i;
    1500                 :            :         int rc = 0;
    1501                 :            : 
    1502         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    1503                 :          0 :                 rc = efx_filter_insert(sa->nic, &spec_filter->filters[i]);
    1504         [ #  # ]:          0 :                 if (rc != 0) {
    1505                 :          0 :                         sfc_flow_spec_flush(sa, spec, i);
    1506                 :          0 :                         break;
    1507                 :            :                 }
    1508                 :            :         }
    1509                 :            : 
    1510                 :          0 :         return rc;
    1511                 :            : }
    1512                 :            : 
    1513                 :            : static int
    1514                 :            : sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
    1515                 :            : {
    1516                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1517                 :            : 
    1518                 :          0 :         return sfc_flow_spec_flush(sa, spec, spec_filter->count);
    1519                 :            : }
    1520                 :            : 
    1521                 :            : static int
    1522                 :          0 : sfc_flow_filter_insert(struct sfc_adapter *sa,
    1523                 :            :                        struct rte_flow *flow)
    1524                 :            : {
    1525                 :            :         struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
    1526                 :          0 :         struct sfc_flow_rss_ctx *rss_ctx = spec_filter->rss_ctx;
    1527                 :            :         int rc = 0;
    1528                 :            : 
    1529                 :          0 :         rc = sfc_flow_rss_ctx_program(sa, rss_ctx);
    1530         [ #  # ]:          0 :         if (rc != 0)
    1531                 :          0 :                 goto fail_rss_ctx_program;
    1532                 :            : 
    1533         [ #  # ]:          0 :         if (rss_ctx != NULL) {
    1534                 :            :                 unsigned int i;
    1535                 :            : 
    1536                 :            :                 /*
    1537                 :            :                  * At this point, fully elaborated filter specifications
    1538                 :            :                  * have been produced from the template. To make sure that
    1539                 :            :                  * RSS behaviour is consistent between them, set the same
    1540                 :            :                  * RSS context value everywhere.
    1541                 :            :                  */
    1542         [ #  # ]:          0 :                 for (i = 0; i < spec_filter->count; i++) {
    1543                 :            :                         efx_filter_spec_t *spec = &spec_filter->filters[i];
    1544                 :            : 
    1545                 :          0 :                         spec->efs_rss_context = rss_ctx->nic_handle;
    1546                 :            :                 }
    1547                 :            :         }
    1548                 :            : 
    1549                 :          0 :         rc = sfc_flow_spec_insert(sa, &flow->spec);
    1550         [ #  # ]:          0 :         if (rc != 0)
    1551                 :          0 :                 goto fail_filter_insert;
    1552                 :            : 
    1553                 :            :         return 0;
    1554                 :            : 
    1555                 :            : fail_filter_insert:
    1556                 :          0 :         sfc_flow_rss_ctx_terminate(sa, rss_ctx);
    1557                 :            : 
    1558                 :            : fail_rss_ctx_program:
    1559                 :            :         return rc;
    1560                 :            : }
    1561                 :            : 
    1562                 :            : static int
    1563                 :          0 : sfc_flow_filter_remove(struct sfc_adapter *sa,
    1564                 :            :                        struct rte_flow *flow)
    1565                 :            : {
    1566                 :            :         struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
    1567                 :            :         int rc = 0;
    1568                 :            : 
    1569                 :          0 :         rc = sfc_flow_spec_remove(sa, &flow->spec);
    1570         [ #  # ]:          0 :         if (rc != 0)
    1571                 :            :                 return rc;
    1572                 :            : 
    1573                 :          0 :         sfc_flow_rss_ctx_terminate(sa, spec_filter->rss_ctx);
    1574                 :            : 
    1575                 :          0 :         return 0;
    1576                 :            : }
    1577                 :            : 
    1578                 :            : static int
    1579                 :          0 : sfc_flow_parse_mark(struct sfc_adapter *sa,
    1580                 :            :                     const struct rte_flow_action_mark *mark,
    1581                 :            :                     struct rte_flow *flow)
    1582                 :            : {
    1583                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    1584                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1585                 :          0 :         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
    1586                 :            :         uint32_t mark_max;
    1587                 :            : 
    1588                 :          0 :         mark_max = encp->enc_filter_action_mark_max;
    1589         [ #  # ]:          0 :         if (sfc_ft_is_active(sa))
    1590                 :          0 :                 mark_max = RTE_MIN(mark_max, SFC_FT_USER_MARK_MASK);
    1591                 :            : 
    1592   [ #  #  #  # ]:          0 :         if (mark == NULL || mark->id > mark_max)
    1593                 :            :                 return EINVAL;
    1594                 :            : 
    1595                 :          0 :         spec_filter->template.efs_flags |= EFX_FILTER_FLAG_ACTION_MARK;
    1596                 :          0 :         spec_filter->template.efs_mark = mark->id;
    1597                 :            : 
    1598                 :          0 :         return 0;
    1599                 :            : }
    1600                 :            : 
    1601                 :            : static int
    1602                 :          0 : sfc_flow_parse_actions(struct sfc_adapter *sa,
    1603                 :            :                        const struct rte_flow_action actions[],
    1604                 :            :                        struct rte_flow *flow,
    1605                 :            :                        struct rte_flow_error *error)
    1606                 :            : {
    1607                 :            :         int rc;
    1608                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    1609                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1610                 :          0 :         const unsigned int dp_rx_features = sa->priv.dp_rx->features;
    1611                 :          0 :         const uint64_t rx_metadata = sa->negotiated_rx_metadata;
    1612                 :            :         uint32_t actions_set = 0;
    1613                 :            :         const uint32_t fate_actions_mask = (1UL << RTE_FLOW_ACTION_TYPE_QUEUE) |
    1614                 :            :                                            (1UL << RTE_FLOW_ACTION_TYPE_RSS) |
    1615                 :            :                                            (1UL << RTE_FLOW_ACTION_TYPE_DROP);
    1616                 :            :         const uint32_t mark_actions_mask = (1UL << RTE_FLOW_ACTION_TYPE_MARK) |
    1617                 :            :                                            (1UL << RTE_FLOW_ACTION_TYPE_FLAG);
    1618                 :            : 
    1619         [ #  # ]:          0 :         if (actions == NULL) {
    1620                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1621                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
    1622                 :            :                                    "NULL actions");
    1623                 :          0 :                 return -rte_errno;
    1624                 :            :         }
    1625                 :            : 
    1626         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    1627   [ #  #  #  #  :          0 :                 switch (actions->type) {
                #  #  # ]
    1628                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    1629                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VOID,
    1630                 :            :                                                actions_set);
    1631                 :            :                         break;
    1632                 :            : 
    1633                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
    1634                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_QUEUE,
    1635                 :            :                                                actions_set);
    1636         [ #  # ]:          0 :                         if ((actions_set & fate_actions_mask) != 0)
    1637                 :          0 :                                 goto fail_fate_actions;
    1638                 :            : 
    1639                 :          0 :                         rc = sfc_flow_parse_queue(sa, actions->conf, flow);
    1640         [ #  # ]:          0 :                         if (rc != 0) {
    1641                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    1642                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1643                 :            :                                         "Bad QUEUE action");
    1644                 :          0 :                                 return -rte_errno;
    1645                 :            :                         }
    1646                 :            :                         break;
    1647                 :            : 
    1648                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS:
    1649                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_RSS,
    1650                 :            :                                                actions_set);
    1651         [ #  # ]:          0 :                         if ((actions_set & fate_actions_mask) != 0)
    1652                 :          0 :                                 goto fail_fate_actions;
    1653                 :            : 
    1654                 :          0 :                         rc = sfc_flow_parse_rss(sa, actions->conf, flow);
    1655         [ #  # ]:          0 :                         if (rc != 0) {
    1656                 :          0 :                                 rte_flow_error_set(error, -rc,
    1657                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1658                 :            :                                         "Bad RSS action");
    1659                 :          0 :                                 return -rte_errno;
    1660                 :            :                         }
    1661                 :            :                         break;
    1662                 :            : 
    1663                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
    1664                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
    1665                 :            :                                                actions_set);
    1666         [ #  # ]:          0 :                         if ((actions_set & fate_actions_mask) != 0)
    1667                 :          0 :                                 goto fail_fate_actions;
    1668                 :            : 
    1669                 :          0 :                         spec_filter->template.efs_dmaq_id =
    1670                 :            :                                 EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
    1671                 :          0 :                         break;
    1672                 :            : 
    1673                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG:
    1674                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
    1675                 :            :                                                actions_set);
    1676         [ #  # ]:          0 :                         if ((actions_set & mark_actions_mask) != 0)
    1677                 :          0 :                                 goto fail_actions_overlap;
    1678                 :            : 
    1679         [ #  # ]:          0 :                         if ((dp_rx_features & SFC_DP_RX_FEAT_FLOW_FLAG) == 0) {
    1680                 :          0 :                                 rte_flow_error_set(error, ENOTSUP,
    1681                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1682                 :            :                                         "FLAG action is not supported on the current Rx datapath");
    1683                 :          0 :                                 return -rte_errno;
    1684         [ #  # ]:          0 :                         } else if ((rx_metadata &
    1685                 :            :                                     RTE_ETH_RX_METADATA_USER_FLAG) == 0) {
    1686                 :          0 :                                 rte_flow_error_set(error, ENOTSUP,
    1687                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1688                 :            :                                         "flag delivery has not been negotiated");
    1689                 :          0 :                                 return -rte_errno;
    1690                 :            :                         }
    1691                 :            : 
    1692                 :          0 :                         spec_filter->template.efs_flags |=
    1693                 :            :                                 EFX_FILTER_FLAG_ACTION_FLAG;
    1694                 :          0 :                         break;
    1695                 :            : 
    1696                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK:
    1697                 :            :                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
    1698                 :            :                                                actions_set);
    1699         [ #  # ]:          0 :                         if ((actions_set & mark_actions_mask) != 0)
    1700                 :          0 :                                 goto fail_actions_overlap;
    1701                 :            : 
    1702         [ #  # ]:          0 :                         if ((dp_rx_features & SFC_DP_RX_FEAT_FLOW_MARK) == 0) {
    1703                 :          0 :                                 rte_flow_error_set(error, ENOTSUP,
    1704                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1705                 :            :                                         "MARK action is not supported on the current Rx datapath");
    1706                 :          0 :                                 return -rte_errno;
    1707         [ #  # ]:          0 :                         } else if ((rx_metadata &
    1708                 :            :                                     RTE_ETH_RX_METADATA_USER_MARK) == 0) {
    1709                 :          0 :                                 rte_flow_error_set(error, ENOTSUP,
    1710                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1711                 :            :                                         "mark delivery has not been negotiated");
    1712                 :          0 :                                 return -rte_errno;
    1713                 :            :                         }
    1714                 :            : 
    1715                 :          0 :                         rc = sfc_flow_parse_mark(sa, actions->conf, flow);
    1716         [ #  # ]:          0 :                         if (rc != 0) {
    1717                 :          0 :                                 rte_flow_error_set(error, rc,
    1718                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1719                 :            :                                         "Bad MARK action");
    1720                 :          0 :                                 return -rte_errno;
    1721                 :            :                         }
    1722                 :            :                         break;
    1723                 :            : 
    1724                 :          0 :                 default:
    1725                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1726                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1727                 :            :                                            "Action is not supported");
    1728                 :          0 :                         return -rte_errno;
    1729                 :            :                 }
    1730                 :            : 
    1731                 :          0 :                 actions_set |= (1UL << actions->type);
    1732                 :            :         }
    1733                 :            : 
    1734                 :            :         /* When fate is unknown, drop traffic. */
    1735         [ #  # ]:          0 :         if ((actions_set & fate_actions_mask) == 0) {
    1736                 :          0 :                 spec_filter->template.efs_dmaq_id =
    1737                 :            :                         EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
    1738                 :            :         }
    1739                 :            : 
    1740                 :            :         return 0;
    1741                 :            : 
    1742                 :          0 : fail_fate_actions:
    1743                 :          0 :         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1744                 :            :                            "Cannot combine several fate-deciding actions, "
    1745                 :            :                            "choose between QUEUE, RSS or DROP");
    1746                 :          0 :         return -rte_errno;
    1747                 :            : 
    1748                 :          0 : fail_actions_overlap:
    1749                 :          0 :         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions,
    1750                 :            :                            "Overlapping actions are not supported");
    1751                 :          0 :         return -rte_errno;
    1752                 :            : }
    1753                 :            : 
    1754                 :            : /**
    1755                 :            :  * Set the EFX_FILTER_MATCH_UNKNOWN_UCAST_DST
    1756                 :            :  * and EFX_FILTER_MATCH_UNKNOWN_MCAST_DST match flags in the same
    1757                 :            :  * specifications after copying.
    1758                 :            :  *
    1759                 :            :  * @param spec[in, out]
    1760                 :            :  *   SFC flow specification to update.
    1761                 :            :  * @param filters_count_for_one_val[in]
    1762                 :            :  *   How many specifications should have the same match flag, what is the
    1763                 :            :  *   number of specifications before copying.
    1764                 :            :  * @param error[out]
    1765                 :            :  *   Perform verbose error reporting if not NULL.
    1766                 :            :  */
    1767                 :            : static int
    1768                 :          0 : sfc_flow_set_unknown_dst_flags(struct sfc_flow_spec *spec,
    1769                 :            :                                unsigned int filters_count_for_one_val,
    1770                 :            :                                struct rte_flow_error *error)
    1771                 :            : {
    1772                 :            :         unsigned int i;
    1773                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1774                 :            :         static const efx_filter_match_flags_t vals[] = {
    1775                 :            :                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
    1776                 :            :                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST
    1777                 :            :         };
    1778                 :            : 
    1779         [ #  # ]:          0 :         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
    1780                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1781                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1782                 :            :                         "Number of specifications is incorrect while copying "
    1783                 :            :                         "by unknown destination flags");
    1784                 :          0 :                 return -rte_errno;
    1785                 :            :         }
    1786                 :            : 
    1787         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    1788                 :            :                 /* The check above ensures that divisor can't be zero here */
    1789                 :          0 :                 spec_filter->filters[i].efs_match_flags |=
    1790                 :          0 :                         vals[i / filters_count_for_one_val];
    1791                 :            :         }
    1792                 :            : 
    1793                 :            :         return 0;
    1794                 :            : }
    1795                 :            : 
    1796                 :            : /**
    1797                 :            :  * Check that the following conditions are met:
    1798                 :            :  * - the list of supported filters has a filter
    1799                 :            :  *   with EFX_FILTER_MATCH_UNKNOWN_MCAST_DST flag instead of
    1800                 :            :  *   EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, since this filter will also
    1801                 :            :  *   be inserted.
    1802                 :            :  *
    1803                 :            :  * @param match[in]
    1804                 :            :  *   The match flags of filter.
    1805                 :            :  * @param spec[in]
    1806                 :            :  *   Specification to be supplemented.
    1807                 :            :  * @param filter[in]
    1808                 :            :  *   SFC filter with list of supported filters.
    1809                 :            :  */
    1810                 :            : static boolean_t
    1811                 :          0 : sfc_flow_check_unknown_dst_flags(efx_filter_match_flags_t match,
    1812                 :            :                                  __rte_unused efx_filter_spec_t *spec,
    1813                 :            :                                  struct sfc_filter *filter)
    1814                 :            : {
    1815                 :            :         unsigned int i;
    1816                 :            :         efx_filter_match_flags_t match_mcast_dst;
    1817                 :            : 
    1818                 :          0 :         match_mcast_dst =
    1819                 :          0 :                 (match & ~EFX_FILTER_MATCH_UNKNOWN_UCAST_DST) |
    1820                 :            :                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
    1821         [ #  # ]:          0 :         for (i = 0; i < filter->supported_match_num; i++) {
    1822         [ #  # ]:          0 :                 if (match_mcast_dst == filter->supported_match[i])
    1823                 :            :                         return B_TRUE;
    1824                 :            :         }
    1825                 :            : 
    1826                 :            :         return B_FALSE;
    1827                 :            : }
    1828                 :            : 
    1829                 :            : /**
    1830                 :            :  * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and
    1831                 :            :  * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same
    1832                 :            :  * specifications after copying.
    1833                 :            :  *
    1834                 :            :  * @param spec[in, out]
    1835                 :            :  *   SFC flow specification to update.
    1836                 :            :  * @param filters_count_for_one_val[in]
    1837                 :            :  *   How many specifications should have the same EtherType value, what is the
    1838                 :            :  *   number of specifications before copying.
    1839                 :            :  * @param error[out]
    1840                 :            :  *   Perform verbose error reporting if not NULL.
    1841                 :            :  */
    1842                 :            : static int
    1843                 :          0 : sfc_flow_set_ethertypes(struct sfc_flow_spec *spec,
    1844                 :            :                         unsigned int filters_count_for_one_val,
    1845                 :            :                         struct rte_flow_error *error)
    1846                 :            : {
    1847                 :            :         unsigned int i;
    1848                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1849                 :            :         static const uint16_t vals[] = {
    1850                 :            :                 EFX_ETHER_TYPE_IPV4, EFX_ETHER_TYPE_IPV6
    1851                 :            :         };
    1852                 :            : 
    1853         [ #  # ]:          0 :         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
    1854                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1855                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1856                 :            :                         "Number of specifications is incorrect "
    1857                 :            :                         "while copying by Ethertype");
    1858                 :          0 :                 return -rte_errno;
    1859                 :            :         }
    1860                 :            : 
    1861         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    1862                 :          0 :                 spec_filter->filters[i].efs_match_flags |=
    1863                 :            :                         EFX_FILTER_MATCH_ETHER_TYPE;
    1864                 :            : 
    1865                 :            :                 /*
    1866                 :            :                  * The check above ensures that
    1867                 :            :                  * filters_count_for_one_val is not 0
    1868                 :            :                  */
    1869                 :          0 :                 spec_filter->filters[i].efs_ether_type =
    1870                 :          0 :                         vals[i / filters_count_for_one_val];
    1871                 :            :         }
    1872                 :            : 
    1873                 :            :         return 0;
    1874                 :            : }
    1875                 :            : 
    1876                 :            : /**
    1877                 :            :  * Set the EFX_FILTER_MATCH_OUTER_VID match flag with value 0
    1878                 :            :  * in the same specifications after copying.
    1879                 :            :  *
    1880                 :            :  * @param spec[in, out]
    1881                 :            :  *   SFC flow specification to update.
    1882                 :            :  * @param filters_count_for_one_val[in]
    1883                 :            :  *   How many specifications should have the same match flag, what is the
    1884                 :            :  *   number of specifications before copying.
    1885                 :            :  * @param error[out]
    1886                 :            :  *   Perform verbose error reporting if not NULL.
    1887                 :            :  */
    1888                 :            : static int
    1889                 :          0 : sfc_flow_set_outer_vid_flag(struct sfc_flow_spec *spec,
    1890                 :            :                             unsigned int filters_count_for_one_val,
    1891                 :            :                             struct rte_flow_error *error)
    1892                 :            : {
    1893                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1894                 :            :         unsigned int i;
    1895                 :            : 
    1896         [ #  # ]:          0 :         if (filters_count_for_one_val != spec_filter->count) {
    1897                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1898                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1899                 :            :                         "Number of specifications is incorrect "
    1900                 :            :                         "while copying by outer VLAN ID");
    1901                 :          0 :                 return -rte_errno;
    1902                 :            :         }
    1903                 :            : 
    1904         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    1905                 :          0 :                 spec_filter->filters[i].efs_match_flags |=
    1906                 :            :                         EFX_FILTER_MATCH_OUTER_VID;
    1907                 :            : 
    1908                 :          0 :                 spec_filter->filters[i].efs_outer_vid = 0;
    1909                 :            :         }
    1910                 :            : 
    1911                 :            :         return 0;
    1912                 :            : }
    1913                 :            : 
    1914                 :            : /**
    1915                 :            :  * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and
    1916                 :            :  * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same
    1917                 :            :  * specifications after copying.
    1918                 :            :  *
    1919                 :            :  * @param spec[in, out]
    1920                 :            :  *   SFC flow specification to update.
    1921                 :            :  * @param filters_count_for_one_val[in]
    1922                 :            :  *   How many specifications should have the same match flag, what is the
    1923                 :            :  *   number of specifications before copying.
    1924                 :            :  * @param error[out]
    1925                 :            :  *   Perform verbose error reporting if not NULL.
    1926                 :            :  */
    1927                 :            : static int
    1928                 :          0 : sfc_flow_set_ifrm_unknown_dst_flags(struct sfc_flow_spec *spec,
    1929                 :            :                                     unsigned int filters_count_for_one_val,
    1930                 :            :                                     struct rte_flow_error *error)
    1931                 :            : {
    1932                 :            :         unsigned int i;
    1933                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    1934                 :            :         static const efx_filter_match_flags_t vals[] = {
    1935                 :            :                 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
    1936                 :            :                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST
    1937                 :            :         };
    1938                 :            : 
    1939         [ #  # ]:          0 :         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
    1940                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1941                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1942                 :            :                         "Number of specifications is incorrect while copying "
    1943                 :            :                         "by inner frame unknown destination flags");
    1944                 :          0 :                 return -rte_errno;
    1945                 :            :         }
    1946                 :            : 
    1947         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    1948                 :            :                 /* The check above ensures that divisor can't be zero here */
    1949                 :          0 :                 spec_filter->filters[i].efs_match_flags |=
    1950                 :          0 :                         vals[i / filters_count_for_one_val];
    1951                 :            :         }
    1952                 :            : 
    1953                 :            :         return 0;
    1954                 :            : }
    1955                 :            : 
    1956                 :            : /**
    1957                 :            :  * Check that the following conditions are met:
    1958                 :            :  * - the specification corresponds to a filter for encapsulated traffic
    1959                 :            :  * - the list of supported filters has a filter
    1960                 :            :  *   with EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST flag instead of
    1961                 :            :  *   EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, since this filter will also
    1962                 :            :  *   be inserted.
    1963                 :            :  *
    1964                 :            :  * @param match[in]
    1965                 :            :  *   The match flags of filter.
    1966                 :            :  * @param spec[in]
    1967                 :            :  *   Specification to be supplemented.
    1968                 :            :  * @param filter[in]
    1969                 :            :  *   SFC filter with list of supported filters.
    1970                 :            :  */
    1971                 :            : static boolean_t
    1972                 :          0 : sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match,
    1973                 :            :                                       efx_filter_spec_t *spec,
    1974                 :            :                                       struct sfc_filter *filter)
    1975                 :            : {
    1976                 :            :         unsigned int i;
    1977                 :          0 :         efx_tunnel_protocol_t encap_type = spec->efs_encap_type;
    1978                 :            :         efx_filter_match_flags_t match_mcast_dst;
    1979                 :            : 
    1980         [ #  # ]:          0 :         if (encap_type == EFX_TUNNEL_PROTOCOL_NONE)
    1981                 :            :                 return B_FALSE;
    1982                 :            : 
    1983                 :          0 :         match_mcast_dst =
    1984                 :          0 :                 (match & ~EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST) |
    1985                 :            :                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
    1986         [ #  # ]:          0 :         for (i = 0; i < filter->supported_match_num; i++) {
    1987         [ #  # ]:          0 :                 if (match_mcast_dst == filter->supported_match[i])
    1988                 :            :                         return B_TRUE;
    1989                 :            :         }
    1990                 :            : 
    1991                 :            :         return B_FALSE;
    1992                 :            : }
    1993                 :            : 
    1994                 :            : /**
    1995                 :            :  * Check that the list of supported filters has a filter that differs
    1996                 :            :  * from @p match in that it has no flag EFX_FILTER_MATCH_OUTER_VID
    1997                 :            :  * in this case that filter will be used and the flag
    1998                 :            :  * EFX_FILTER_MATCH_OUTER_VID is not needed.
    1999                 :            :  *
    2000                 :            :  * @param match[in]
    2001                 :            :  *   The match flags of filter.
    2002                 :            :  * @param spec[in]
    2003                 :            :  *   Specification to be supplemented.
    2004                 :            :  * @param filter[in]
    2005                 :            :  *   SFC filter with list of supported filters.
    2006                 :            :  */
    2007                 :            : static boolean_t
    2008                 :          0 : sfc_flow_check_outer_vid_flag(efx_filter_match_flags_t match,
    2009                 :            :                               __rte_unused efx_filter_spec_t *spec,
    2010                 :            :                               struct sfc_filter *filter)
    2011                 :            : {
    2012                 :            :         unsigned int i;
    2013                 :          0 :         efx_filter_match_flags_t match_without_vid =
    2014                 :            :                 match & ~EFX_FILTER_MATCH_OUTER_VID;
    2015                 :            : 
    2016         [ #  # ]:          0 :         for (i = 0; i < filter->supported_match_num; i++) {
    2017         [ #  # ]:          0 :                 if (match_without_vid == filter->supported_match[i])
    2018                 :            :                         return B_FALSE;
    2019                 :            :         }
    2020                 :            : 
    2021                 :            :         return B_TRUE;
    2022                 :            : }
    2023                 :            : 
    2024                 :            : /*
    2025                 :            :  * Match flags that can be automatically added to filters.
    2026                 :            :  * Selecting the last minimum when searching for the copy flag ensures that the
    2027                 :            :  * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST flag has a higher priority than
    2028                 :            :  * EFX_FILTER_MATCH_ETHER_TYPE. This is because the filter
    2029                 :            :  * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST is at the end of the list of supported
    2030                 :            :  * filters.
    2031                 :            :  */
    2032                 :            : static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = {
    2033                 :            :         {
    2034                 :            :                 .flag = EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
    2035                 :            :                 .vals_count = 2,
    2036                 :            :                 .set_vals = sfc_flow_set_unknown_dst_flags,
    2037                 :            :                 .spec_check = sfc_flow_check_unknown_dst_flags,
    2038                 :            :         },
    2039                 :            :         {
    2040                 :            :                 .flag = EFX_FILTER_MATCH_ETHER_TYPE,
    2041                 :            :                 .vals_count = 2,
    2042                 :            :                 .set_vals = sfc_flow_set_ethertypes,
    2043                 :            :                 .spec_check = NULL,
    2044                 :            :         },
    2045                 :            :         {
    2046                 :            :                 .flag = EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
    2047                 :            :                 .vals_count = 2,
    2048                 :            :                 .set_vals = sfc_flow_set_ifrm_unknown_dst_flags,
    2049                 :            :                 .spec_check = sfc_flow_check_ifrm_unknown_dst_flags,
    2050                 :            :         },
    2051                 :            :         {
    2052                 :            :                 .flag = EFX_FILTER_MATCH_OUTER_VID,
    2053                 :            :                 .vals_count = 1,
    2054                 :            :                 .set_vals = sfc_flow_set_outer_vid_flag,
    2055                 :            :                 .spec_check = sfc_flow_check_outer_vid_flag,
    2056                 :            :         },
    2057                 :            : };
    2058                 :            : 
    2059                 :            : /* Get item from array sfc_flow_copy_flags */
    2060                 :            : static const struct sfc_flow_copy_flag *
    2061                 :            : sfc_flow_get_copy_flag(efx_filter_match_flags_t flag)
    2062                 :            : {
    2063                 :            :         unsigned int i;
    2064                 :            : 
    2065         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
    2066         [ #  # ]:          0 :                 if (sfc_flow_copy_flags[i].flag == flag)
    2067                 :          0 :                         return &sfc_flow_copy_flags[i];
    2068                 :            :         }
    2069                 :            : 
    2070                 :            :         return NULL;
    2071                 :            : }
    2072                 :            : 
    2073                 :            : /**
    2074                 :            :  * Make copies of the specifications, set match flag and values
    2075                 :            :  * of the field that corresponds to it.
    2076                 :            :  *
    2077                 :            :  * @param spec[in, out]
    2078                 :            :  *   SFC flow specification to update.
    2079                 :            :  * @param flag[in]
    2080                 :            :  *   The match flag to add.
    2081                 :            :  * @param error[out]
    2082                 :            :  *   Perform verbose error reporting if not NULL.
    2083                 :            :  */
    2084                 :            : static int
    2085                 :          0 : sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec,
    2086                 :            :                              efx_filter_match_flags_t flag,
    2087                 :            :                              struct rte_flow_error *error)
    2088                 :            : {
    2089                 :            :         unsigned int i;
    2090                 :            :         unsigned int new_filters_count;
    2091                 :            :         unsigned int filters_count_for_one_val;
    2092                 :            :         const struct sfc_flow_copy_flag *copy_flag;
    2093                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    2094                 :            :         int rc;
    2095                 :            : 
    2096                 :            :         copy_flag = sfc_flow_get_copy_flag(flag);
    2097         [ #  # ]:          0 :         if (copy_flag == NULL) {
    2098                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2099                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2100                 :            :                                    "Unsupported spec field for copying");
    2101                 :          0 :                 return -rte_errno;
    2102                 :            :         }
    2103                 :            : 
    2104                 :          0 :         new_filters_count = spec_filter->count * copy_flag->vals_count;
    2105         [ #  # ]:          0 :         if (new_filters_count > SF_FLOW_SPEC_NB_FILTERS_MAX) {
    2106                 :          0 :                 rte_flow_error_set(error, EINVAL,
    2107                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2108                 :            :                         "Too much EFX specifications in the flow rule");
    2109                 :          0 :                 return -rte_errno;
    2110                 :            :         }
    2111                 :            : 
    2112                 :            :         /* Copy filters specifications */
    2113         [ #  # ]:          0 :         for (i = spec_filter->count; i < new_filters_count; i++) {
    2114                 :          0 :                 spec_filter->filters[i] =
    2115                 :          0 :                         spec_filter->filters[i - spec_filter->count];
    2116                 :            :         }
    2117                 :            : 
    2118                 :            :         filters_count_for_one_val = spec_filter->count;
    2119                 :          0 :         spec_filter->count = new_filters_count;
    2120                 :            : 
    2121                 :          0 :         rc = copy_flag->set_vals(spec, filters_count_for_one_val, error);
    2122         [ #  # ]:          0 :         if (rc != 0)
    2123                 :          0 :                 return rc;
    2124                 :            : 
    2125                 :            :         return 0;
    2126                 :            : }
    2127                 :            : 
    2128                 :            : /**
    2129                 :            :  * Check that the given set of match flags missing in the original filter spec
    2130                 :            :  * could be covered by adding spec copies which specify the corresponding
    2131                 :            :  * flags and packet field values to match.
    2132                 :            :  *
    2133                 :            :  * @param miss_flags[in]
    2134                 :            :  *   Flags that are missing until the supported filter.
    2135                 :            :  * @param spec[in]
    2136                 :            :  *   Specification to be supplemented.
    2137                 :            :  * @param filter[in]
    2138                 :            :  *   SFC filter.
    2139                 :            :  *
    2140                 :            :  * @return
    2141                 :            :  *   Number of specifications after copy or 0, if the flags can not be added.
    2142                 :            :  */
    2143                 :            : static unsigned int
    2144                 :          0 : sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags,
    2145                 :            :                              efx_filter_spec_t *spec,
    2146                 :            :                              struct sfc_filter *filter)
    2147                 :            : {
    2148                 :            :         unsigned int i;
    2149                 :            :         efx_filter_match_flags_t copy_flags = 0;
    2150                 :            :         efx_filter_match_flags_t flag;
    2151                 :          0 :         efx_filter_match_flags_t match = spec->efs_match_flags | miss_flags;
    2152                 :            :         sfc_flow_spec_check *check;
    2153                 :            :         unsigned int multiplier = 1;
    2154                 :            : 
    2155         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
    2156                 :          0 :                 flag = sfc_flow_copy_flags[i].flag;
    2157                 :          0 :                 check = sfc_flow_copy_flags[i].spec_check;
    2158         [ #  # ]:          0 :                 if ((flag & miss_flags) == flag) {
    2159   [ #  #  #  # ]:          0 :                         if (check != NULL && (!check(match, spec, filter)))
    2160                 :          0 :                                 continue;
    2161                 :            : 
    2162                 :          0 :                         copy_flags |= flag;
    2163                 :          0 :                         multiplier *= sfc_flow_copy_flags[i].vals_count;
    2164                 :            :                 }
    2165                 :            :         }
    2166                 :            : 
    2167         [ #  # ]:          0 :         if (copy_flags == miss_flags)
    2168                 :          0 :                 return multiplier;
    2169                 :            : 
    2170                 :            :         return 0;
    2171                 :            : }
    2172                 :            : 
    2173                 :            : /**
    2174                 :            :  * Attempt to supplement the specification template to the minimally
    2175                 :            :  * supported set of match flags. To do this, it is necessary to copy
    2176                 :            :  * the specifications, filling them with the values of fields that
    2177                 :            :  * correspond to the missing flags.
    2178                 :            :  * The necessary and sufficient filter is built from the fewest number
    2179                 :            :  * of copies which could be made to cover the minimally required set
    2180                 :            :  * of flags.
    2181                 :            :  *
    2182                 :            :  * @param sa[in]
    2183                 :            :  *   SFC adapter.
    2184                 :            :  * @param spec[in, out]
    2185                 :            :  *   SFC flow specification to update.
    2186                 :            :  * @param error[out]
    2187                 :            :  *   Perform verbose error reporting if not NULL.
    2188                 :            :  */
    2189                 :            : static int
    2190                 :          0 : sfc_flow_spec_filters_complete(struct sfc_adapter *sa,
    2191                 :            :                                struct sfc_flow_spec *spec,
    2192                 :            :                                struct rte_flow_error *error)
    2193                 :            : {
    2194                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    2195                 :          0 :         struct sfc_filter *filter = &sa->filter;
    2196                 :            :         efx_filter_match_flags_t miss_flags;
    2197                 :            :         efx_filter_match_flags_t min_miss_flags = 0;
    2198                 :            :         efx_filter_match_flags_t match;
    2199                 :            :         unsigned int min_multiplier = UINT_MAX;
    2200                 :            :         unsigned int multiplier;
    2201                 :            :         unsigned int i;
    2202                 :            :         int rc;
    2203                 :            : 
    2204                 :          0 :         match = spec_filter->template.efs_match_flags;
    2205         [ #  # ]:          0 :         for (i = 0; i < filter->supported_match_num; i++) {
    2206         [ #  # ]:          0 :                 if ((match & filter->supported_match[i]) == match) {
    2207                 :          0 :                         miss_flags = filter->supported_match[i] & (~match);
    2208                 :          0 :                         multiplier = sfc_flow_check_missing_flags(miss_flags,
    2209                 :            :                                 &spec_filter->template, filter);
    2210         [ #  # ]:          0 :                         if (multiplier > 0) {
    2211         [ #  # ]:          0 :                                 if (multiplier <= min_multiplier) {
    2212                 :            :                                         min_multiplier = multiplier;
    2213                 :            :                                         min_miss_flags = miss_flags;
    2214                 :            :                                 }
    2215                 :            :                         }
    2216                 :            :                 }
    2217                 :            :         }
    2218                 :            : 
    2219         [ #  # ]:          0 :         if (min_multiplier == UINT_MAX) {
    2220                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2221                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2222                 :            :                                    "The flow rule pattern is unsupported");
    2223                 :          0 :                 return -rte_errno;
    2224                 :            :         }
    2225                 :            : 
    2226         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
    2227                 :          0 :                 efx_filter_match_flags_t flag = sfc_flow_copy_flags[i].flag;
    2228                 :            : 
    2229         [ #  # ]:          0 :                 if ((flag & min_miss_flags) == flag) {
    2230                 :          0 :                         rc = sfc_flow_spec_add_match_flag(spec, flag, error);
    2231         [ #  # ]:          0 :                         if (rc != 0)
    2232                 :          0 :                                 return rc;
    2233                 :            :                 }
    2234                 :            :         }
    2235                 :            : 
    2236                 :            :         return 0;
    2237                 :            : }
    2238                 :            : 
    2239                 :            : /**
    2240                 :            :  * Check that set of match flags is referred to by a filter. Filter is
    2241                 :            :  * described by match flags with the ability to add OUTER_VID and INNER_VID
    2242                 :            :  * flags.
    2243                 :            :  *
    2244                 :            :  * @param match_flags[in]
    2245                 :            :  *   Set of match flags.
    2246                 :            :  * @param flags_pattern[in]
    2247                 :            :  *   Pattern of filter match flags.
    2248                 :            :  */
    2249                 :            : static boolean_t
    2250                 :            : sfc_flow_is_match_with_vids(efx_filter_match_flags_t match_flags,
    2251                 :            :                             efx_filter_match_flags_t flags_pattern)
    2252                 :            : {
    2253   [ #  #  #  #  :          0 :         if ((match_flags & flags_pattern) != flags_pattern)
                   #  # ]
    2254                 :            :                 return B_FALSE;
    2255                 :            : 
    2256   [ #  #  #  #  :          0 :         switch (match_flags & ~flags_pattern) {
             #  #  #  # ]
    2257                 :            :         case 0:
    2258                 :            :         case EFX_FILTER_MATCH_OUTER_VID:
    2259                 :            :         case EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_INNER_VID:
    2260                 :            :                 return B_TRUE;
    2261                 :            :         default:
    2262                 :            :                 return B_FALSE;
    2263                 :            :         }
    2264                 :            : }
    2265                 :            : 
    2266                 :            : /**
    2267                 :            :  * Check whether the spec maps to a hardware filter which is known to be
    2268                 :            :  * ineffective despite being valid.
    2269                 :            :  *
    2270                 :            :  * @param filter[in]
    2271                 :            :  *   SFC filter with list of supported filters.
    2272                 :            :  * @param spec[in]
    2273                 :            :  *   SFC flow specification.
    2274                 :            :  */
    2275                 :            : static boolean_t
    2276                 :          0 : sfc_flow_is_match_flags_exception(struct sfc_filter *filter,
    2277                 :            :                                   struct sfc_flow_spec *spec)
    2278                 :            : {
    2279                 :            :         unsigned int i;
    2280                 :            :         uint16_t ether_type;
    2281                 :            :         uint8_t ip_proto;
    2282                 :            :         efx_filter_match_flags_t match_flags;
    2283                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    2284                 :            : 
    2285         [ #  # ]:          0 :         for (i = 0; i < spec_filter->count; i++) {
    2286         [ #  # ]:          0 :                 match_flags = spec_filter->filters[i].efs_match_flags;
    2287                 :            : 
    2288                 :            :                 if (sfc_flow_is_match_with_vids(match_flags,
    2289                 :            :                                                 EFX_FILTER_MATCH_ETHER_TYPE) ||
    2290                 :            :                     sfc_flow_is_match_with_vids(match_flags,
    2291                 :            :                                                 EFX_FILTER_MATCH_ETHER_TYPE |
    2292                 :            :                                                 EFX_FILTER_MATCH_LOC_MAC)) {
    2293                 :          0 :                         ether_type = spec_filter->filters[i].efs_ether_type;
    2294         [ #  # ]:          0 :                         if (filter->supports_ip_proto_or_addr_filter &&
    2295                 :          0 :                             (ether_type == EFX_ETHER_TYPE_IPV4 ||
    2296         [ #  # ]:          0 :                              ether_type == EFX_ETHER_TYPE_IPV6))
    2297                 :            :                                 return B_TRUE;
    2298                 :            :                 } else if (sfc_flow_is_match_with_vids(match_flags,
    2299                 :            :                                 EFX_FILTER_MATCH_ETHER_TYPE |
    2300                 :            :                                 EFX_FILTER_MATCH_IP_PROTO) ||
    2301                 :            :                            sfc_flow_is_match_with_vids(match_flags,
    2302                 :            :                                 EFX_FILTER_MATCH_ETHER_TYPE |
    2303                 :            :                                 EFX_FILTER_MATCH_IP_PROTO |
    2304                 :            :                                 EFX_FILTER_MATCH_LOC_MAC)) {
    2305                 :          0 :                         ip_proto = spec_filter->filters[i].efs_ip_proto;
    2306         [ #  # ]:          0 :                         if (filter->supports_rem_or_local_port_filter &&
    2307                 :          0 :                             (ip_proto == EFX_IPPROTO_TCP ||
    2308         [ #  # ]:          0 :                              ip_proto == EFX_IPPROTO_UDP))
    2309                 :            :                                 return B_TRUE;
    2310                 :            :                 }
    2311                 :            :         }
    2312                 :            : 
    2313                 :            :         return B_FALSE;
    2314                 :            : }
    2315                 :            : 
    2316                 :            : static int
    2317                 :          0 : sfc_flow_validate_match_flags(struct sfc_adapter *sa,
    2318                 :            :                               struct rte_flow *flow,
    2319                 :            :                               struct rte_flow_error *error)
    2320                 :            : {
    2321                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    2322                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    2323                 :            :         efx_filter_spec_t *spec_tmpl = &spec_filter->template;
    2324                 :          0 :         efx_filter_match_flags_t match_flags = spec_tmpl->efs_match_flags;
    2325                 :            :         int rc;
    2326                 :            : 
    2327                 :            :         /* Initialize the first filter spec with template */
    2328                 :          0 :         spec_filter->filters[0] = *spec_tmpl;
    2329                 :          0 :         spec_filter->count = 1;
    2330                 :            : 
    2331         [ #  # ]:          0 :         if (!sfc_filter_is_match_supported(sa, match_flags)) {
    2332                 :          0 :                 rc = sfc_flow_spec_filters_complete(sa, &flow->spec, error);
    2333         [ #  # ]:          0 :                 if (rc != 0)
    2334                 :            :                         return rc;
    2335                 :            :         }
    2336                 :            : 
    2337         [ #  # ]:          0 :         if (sfc_flow_is_match_flags_exception(&sa->filter, &flow->spec)) {
    2338                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2339                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2340                 :            :                         "The flow rule pattern is unsupported");
    2341                 :          0 :                 return -rte_errno;
    2342                 :            :         }
    2343                 :            : 
    2344                 :            :         return 0;
    2345                 :            : }
    2346                 :            : 
    2347                 :            : static int
    2348                 :          0 : sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
    2349                 :            :                              const struct rte_flow_item pattern[],
    2350                 :            :                              const struct rte_flow_action actions[],
    2351                 :            :                              struct rte_flow *flow,
    2352                 :            :                              struct rte_flow_error *error)
    2353                 :            : {
    2354                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2355                 :            :         struct sfc_flow_spec *spec = &flow->spec;
    2356                 :            :         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
    2357                 :            :         struct sfc_flow_parse_ctx ctx;
    2358                 :            :         int rc;
    2359                 :            : 
    2360                 :          0 :         ctx.type = SFC_FLOW_PARSE_CTX_FILTER;
    2361                 :          0 :         ctx.filter = &spec_filter->template;
    2362                 :            : 
    2363                 :          0 :         rc = sfc_flow_parse_pattern(sa, sfc_flow_items, RTE_DIM(sfc_flow_items),
    2364                 :            :                                     pattern, &ctx, error);
    2365         [ #  # ]:          0 :         if (rc != 0)
    2366                 :          0 :                 goto fail_bad_value;
    2367                 :            : 
    2368                 :          0 :         rc = sfc_flow_parse_actions(sa, actions, flow, error);
    2369         [ #  # ]:          0 :         if (rc != 0)
    2370                 :          0 :                 goto fail_bad_value;
    2371                 :            : 
    2372                 :          0 :         rc = sfc_flow_validate_match_flags(sa, flow, error);
    2373         [ #  # ]:          0 :         if (rc != 0)
    2374                 :          0 :                 goto fail_bad_value;
    2375                 :            : 
    2376                 :            :         return 0;
    2377                 :            : 
    2378                 :            : fail_bad_value:
    2379                 :            :         return rc;
    2380                 :            : }
    2381                 :            : 
    2382                 :            : static int
    2383                 :          0 : sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
    2384                 :            :                           const struct rte_flow_item pattern[],
    2385                 :            :                           const struct rte_flow_action actions[],
    2386                 :            :                           struct rte_flow *flow,
    2387                 :            :                           struct rte_flow_error *error)
    2388                 :            : {
    2389                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2390                 :            : 
    2391                 :          0 :         return sfc_mae_rule_parse(sa, pattern, actions, flow, error);
    2392                 :            : }
    2393                 :            : 
    2394                 :            : static int
    2395                 :          0 : sfc_flow_parse(struct rte_eth_dev *dev,
    2396                 :            :                const struct rte_flow_attr *attr,
    2397                 :            :                const struct rte_flow_item pattern[],
    2398                 :            :                const struct rte_flow_action actions[],
    2399                 :            :                struct rte_flow *flow,
    2400                 :            :                struct rte_flow_error *error)
    2401                 :            : {
    2402                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2403                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2404                 :            :         int rc;
    2405                 :            : 
    2406                 :          0 :         rc = sfc_flow_parse_attr(sa, attr, flow, error);
    2407         [ #  # ]:          0 :         if (rc != 0)
    2408                 :            :                 return rc;
    2409                 :            : 
    2410                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2411         [ #  # ]:          0 :         if (ops == NULL || ops->parse == NULL) {
    2412                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2413                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2414                 :            :                                    "No backend to handle this flow");
    2415                 :          0 :                 return -rte_errno;
    2416                 :            :         }
    2417                 :            : 
    2418                 :          0 :         return ops->parse(dev, pattern, actions, flow, error);
    2419                 :            : }
    2420                 :            : 
    2421                 :            : static struct rte_flow *
    2422                 :          0 : sfc_flow_zmalloc(struct rte_flow_error *error)
    2423                 :            : {
    2424                 :            :         struct rte_flow *flow;
    2425                 :            : 
    2426                 :          0 :         flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
    2427         [ #  # ]:          0 :         if (flow == NULL) {
    2428                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    2429                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2430                 :            :                                    "Failed to allocate memory");
    2431                 :            :         }
    2432                 :            : 
    2433                 :          0 :         return flow;
    2434                 :            : }
    2435                 :            : 
    2436                 :            : static void
    2437      [ #  #  # ]:          0 : sfc_flow_free(struct sfc_adapter *sa, struct rte_flow *flow)
    2438                 :            : {
    2439                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2440                 :            : 
    2441                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2442         [ #  # ]:          0 :         if (ops != NULL && ops->cleanup != NULL)
    2443                 :          0 :                 ops->cleanup(sa, flow);
    2444                 :            : 
    2445                 :          0 :         rte_free(flow);
    2446                 :          0 : }
    2447                 :            : 
    2448                 :            : static int
    2449      [ #  #  # ]:          0 : sfc_flow_insert(struct sfc_adapter *sa, struct rte_flow *flow,
    2450                 :            :                 struct rte_flow_error *error)
    2451                 :            : {
    2452                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2453                 :            :         int rc;
    2454                 :            : 
    2455                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2456         [ #  # ]:          0 :         if (ops == NULL || ops->insert == NULL) {
    2457                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2458                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2459                 :            :                                    "No backend to handle this flow");
    2460                 :          0 :                 return rte_errno;
    2461                 :            :         }
    2462                 :            : 
    2463                 :          0 :         rc = ops->insert(sa, flow);
    2464         [ #  # ]:          0 :         if (rc != 0) {
    2465                 :          0 :                 rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2466                 :            :                                    NULL, "Failed to insert the flow rule");
    2467                 :            :         }
    2468                 :            : 
    2469                 :            :         return rc;
    2470                 :            : }
    2471                 :            : 
    2472                 :            : static int
    2473      [ #  #  # ]:          0 : sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow,
    2474                 :            :                 struct rte_flow_error *error)
    2475                 :            : {
    2476                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2477                 :            :         int rc;
    2478                 :            : 
    2479                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2480         [ #  # ]:          0 :         if (ops == NULL || ops->remove == NULL) {
    2481                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2482                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2483                 :            :                                    "No backend to handle this flow");
    2484                 :          0 :                 return rte_errno;
    2485                 :            :         }
    2486                 :            : 
    2487                 :          0 :         rc = ops->remove(sa, flow);
    2488         [ #  # ]:          0 :         if (rc != 0) {
    2489                 :          0 :                 rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2490                 :            :                                    NULL, "Failed to remove the flow rule");
    2491                 :            :         }
    2492                 :            : 
    2493                 :            :         return rc;
    2494                 :            : }
    2495                 :            : 
    2496                 :            : static int
    2497      [ #  #  # ]:          0 : sfc_flow_verify(struct sfc_adapter *sa, struct rte_flow *flow,
    2498                 :            :                 struct rte_flow_error *error)
    2499                 :            : {
    2500                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2501                 :            :         int rc = 0;
    2502                 :            : 
    2503                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2504                 :            :         if (ops == NULL) {
    2505                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2506                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2507                 :            :                                    "No backend to handle this flow");
    2508                 :          0 :                 return -rte_errno;
    2509                 :            :         }
    2510                 :            : 
    2511         [ #  # ]:          0 :         if (ops->verify != NULL) {
    2512                 :            :                 SFC_ASSERT(sfc_adapter_is_locked(sa));
    2513                 :          0 :                 rc = ops->verify(sa, flow);
    2514                 :            :         }
    2515                 :            : 
    2516         [ #  # ]:          0 :         if (rc != 0) {
    2517                 :          0 :                 rte_flow_error_set(error, rc,
    2518                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2519                 :            :                         "Failed to verify flow validity with FW");
    2520                 :          0 :                 return -rte_errno;
    2521                 :            :         }
    2522                 :            : 
    2523                 :            :         return 0;
    2524                 :            : }
    2525                 :            : 
    2526                 :            : static int
    2527                 :          0 : sfc_flow_validate(struct rte_eth_dev *dev,
    2528                 :            :                   const struct rte_flow_attr *attr,
    2529                 :            :                   const struct rte_flow_item pattern[],
    2530                 :            :                   const struct rte_flow_action actions[],
    2531                 :            :                   struct rte_flow_error *error)
    2532                 :            : {
    2533                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2534                 :            :         struct rte_flow *flow;
    2535                 :            :         int rc;
    2536                 :            : 
    2537                 :          0 :         flow = sfc_flow_zmalloc(error);
    2538         [ #  # ]:          0 :         if (flow == NULL)
    2539                 :          0 :                 return -rte_errno;
    2540                 :            : 
    2541                 :          0 :         sfc_adapter_lock(sa);
    2542                 :            : 
    2543                 :          0 :         rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
    2544         [ #  # ]:          0 :         if (rc == 0)
    2545                 :          0 :                 rc = sfc_flow_verify(sa, flow, error);
    2546                 :            : 
    2547                 :          0 :         sfc_flow_free(sa, flow);
    2548                 :            : 
    2549                 :            :         sfc_adapter_unlock(sa);
    2550                 :            : 
    2551                 :          0 :         return rc;
    2552                 :            : }
    2553                 :            : 
    2554                 :            : static struct rte_flow *
    2555                 :          0 : sfc_flow_create(struct rte_eth_dev *dev,
    2556                 :            :                 const struct rte_flow_attr *attr,
    2557                 :            :                 const struct rte_flow_item pattern[],
    2558                 :            :                 const struct rte_flow_action actions[],
    2559                 :            :                 struct rte_flow_error *error)
    2560                 :            : {
    2561                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2562                 :            :         struct rte_flow *flow;
    2563                 :            : 
    2564                 :          0 :         sfc_adapter_lock(sa);
    2565                 :          0 :         flow = sfc_flow_create_locked(sa, false, attr, pattern, actions, error);
    2566                 :            :         sfc_adapter_unlock(sa);
    2567                 :            : 
    2568                 :          0 :         return flow;
    2569                 :            : }
    2570                 :            : 
    2571                 :            : struct rte_flow *
    2572                 :          0 : sfc_flow_create_locked(struct sfc_adapter *sa, bool internal,
    2573                 :            :                        const struct rte_flow_attr *attr,
    2574                 :            :                        const struct rte_flow_item pattern[],
    2575                 :            :                        const struct rte_flow_action actions[],
    2576                 :            :                        struct rte_flow_error *error)
    2577                 :            : {
    2578                 :            :         struct rte_flow *flow = NULL;
    2579                 :            :         int rc;
    2580                 :            : 
    2581                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    2582                 :            : 
    2583                 :          0 :         flow = sfc_flow_zmalloc(error);
    2584         [ #  # ]:          0 :         if (flow == NULL)
    2585                 :          0 :                 goto fail_no_mem;
    2586                 :            : 
    2587                 :          0 :         flow->internal = internal;
    2588                 :            : 
    2589                 :          0 :         rc = sfc_flow_parse(sa->eth_dev, attr, pattern, actions, flow, error);
    2590         [ #  # ]:          0 :         if (rc != 0)
    2591                 :          0 :                 goto fail_bad_value;
    2592                 :            : 
    2593                 :          0 :         TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
    2594                 :            : 
    2595   [ #  #  #  # ]:          0 :         if (flow->internal || sa->state == SFC_ETHDEV_STARTED) {
    2596                 :          0 :                 rc = sfc_flow_insert(sa, flow, error);
    2597         [ #  # ]:          0 :                 if (rc != 0)
    2598                 :          0 :                         goto fail_flow_insert;
    2599                 :            :         }
    2600                 :            : 
    2601                 :            :         return flow;
    2602                 :            : 
    2603                 :            : fail_flow_insert:
    2604         [ #  # ]:          0 :         TAILQ_REMOVE(&sa->flow_list, flow, entries);
    2605                 :            : 
    2606                 :          0 : fail_bad_value:
    2607                 :          0 :         sfc_flow_free(sa, flow);
    2608                 :            : 
    2609                 :            : fail_no_mem:
    2610                 :            :         return NULL;
    2611                 :            : }
    2612                 :            : 
    2613                 :            : static int
    2614                 :          0 : sfc_flow_destroy(struct rte_eth_dev *dev,
    2615                 :            :                  struct rte_flow *flow,
    2616                 :            :                  struct rte_flow_error *error)
    2617                 :            : {
    2618                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2619                 :            :         int rc;
    2620                 :            : 
    2621                 :          0 :         sfc_adapter_lock(sa);
    2622                 :          0 :         rc = sfc_flow_destroy_locked(sa, flow, error);
    2623                 :            :         sfc_adapter_unlock(sa);
    2624                 :            : 
    2625                 :          0 :         return rc;
    2626                 :            : }
    2627                 :            : 
    2628                 :            : int
    2629                 :          0 : sfc_flow_destroy_locked(struct sfc_adapter *sa, struct rte_flow *flow,
    2630                 :            :                         struct rte_flow_error *error)
    2631                 :            : {
    2632                 :            :         struct rte_flow *flow_ptr;
    2633                 :            :         int rc = EINVAL;
    2634                 :            : 
    2635                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    2636                 :            : 
    2637         [ #  # ]:          0 :         TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
    2638         [ #  # ]:          0 :                 if (flow_ptr == flow)
    2639                 :            :                         rc = 0;
    2640                 :            :         }
    2641         [ #  # ]:          0 :         if (rc != 0) {
    2642                 :          0 :                 rte_flow_error_set(error, rc,
    2643                 :            :                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
    2644                 :            :                                    "Failed to find flow rule to destroy");
    2645                 :          0 :                 goto fail_bad_value;
    2646                 :            :         }
    2647                 :            : 
    2648   [ #  #  #  # ]:          0 :         if (flow->internal || sa->state == SFC_ETHDEV_STARTED)
    2649                 :          0 :                 rc = sfc_flow_remove(sa, flow, error);
    2650                 :            : 
    2651         [ #  # ]:          0 :         TAILQ_REMOVE(&sa->flow_list, flow, entries);
    2652                 :          0 :         sfc_flow_free(sa, flow);
    2653                 :            : 
    2654                 :          0 : fail_bad_value:
    2655                 :          0 :         return -rc;
    2656                 :            : }
    2657                 :            : 
    2658                 :            : static int
    2659                 :          0 : sfc_flow_flush(struct rte_eth_dev *dev,
    2660                 :            :                struct rte_flow_error *error)
    2661                 :            : {
    2662                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2663                 :            :         struct rte_flow *flow;
    2664                 :            :         int ret = 0;
    2665                 :            :         void *tmp;
    2666                 :            : 
    2667                 :          0 :         sfc_adapter_lock(sa);
    2668                 :            : 
    2669         [ #  # ]:          0 :         RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
    2670         [ #  # ]:          0 :                 if (flow->internal)
    2671                 :          0 :                         continue;
    2672                 :            : 
    2673         [ #  # ]:          0 :                 if (sa->state == SFC_ETHDEV_STARTED) {
    2674                 :            :                         int rc;
    2675                 :            : 
    2676                 :          0 :                         rc = sfc_flow_remove(sa, flow, error);
    2677         [ #  # ]:          0 :                         if (rc != 0)
    2678                 :            :                                 ret = rc;
    2679                 :            :                 }
    2680                 :            : 
    2681         [ #  # ]:          0 :                 TAILQ_REMOVE(&sa->flow_list, flow, entries);
    2682                 :          0 :                 sfc_flow_free(sa, flow);
    2683                 :            :         }
    2684                 :            : 
    2685                 :            :         sfc_adapter_unlock(sa);
    2686                 :            : 
    2687                 :          0 :         return -ret;
    2688                 :            : }
    2689                 :            : 
    2690                 :            : static int
    2691                 :          0 : sfc_flow_query(struct rte_eth_dev *dev,
    2692                 :            :                struct rte_flow *flow,
    2693                 :            :                const struct rte_flow_action *action,
    2694                 :            :                void *data,
    2695                 :            :                struct rte_flow_error *error)
    2696                 :            : {
    2697                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2698                 :            :         const struct sfc_flow_ops_by_spec *ops;
    2699                 :            :         int ret;
    2700                 :            : 
    2701                 :          0 :         sfc_adapter_lock(sa);
    2702                 :            : 
    2703                 :            :         ops = sfc_flow_get_ops_by_spec(flow);
    2704         [ #  # ]:          0 :         if (ops == NULL || ops->query == NULL) {
    2705                 :          0 :                 ret = rte_flow_error_set(error, ENOTSUP,
    2706                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2707                 :            :                         "No backend to handle this flow");
    2708                 :          0 :                 goto fail_no_backend;
    2709                 :            :         }
    2710                 :            : 
    2711         [ #  # ]:          0 :         if (sa->state != SFC_ETHDEV_STARTED) {
    2712                 :          0 :                 ret = rte_flow_error_set(error, EINVAL,
    2713                 :            :                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2714                 :            :                         "Can't query the flow: the adapter is not started");
    2715                 :          0 :                 goto fail_not_started;
    2716                 :            :         }
    2717                 :            : 
    2718                 :          0 :         ret = ops->query(dev, flow, action, data, error);
    2719         [ #  # ]:          0 :         if (ret != 0)
    2720                 :          0 :                 goto fail_query;
    2721                 :            : 
    2722                 :            :         sfc_adapter_unlock(sa);
    2723                 :            : 
    2724                 :          0 :         return 0;
    2725                 :            : 
    2726                 :            : fail_query:
    2727                 :          0 : fail_not_started:
    2728                 :          0 : fail_no_backend:
    2729                 :            :         sfc_adapter_unlock(sa);
    2730                 :          0 :         return ret;
    2731                 :            : }
    2732                 :            : 
    2733                 :            : static int
    2734                 :          0 : sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
    2735                 :            :                  struct rte_flow_error *error)
    2736                 :            : {
    2737                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2738                 :            :         int ret = 0;
    2739                 :            : 
    2740                 :          0 :         sfc_adapter_lock(sa);
    2741         [ #  # ]:          0 :         if (sa->state != SFC_ETHDEV_INITIALIZED) {
    2742                 :          0 :                 rte_flow_error_set(error, EBUSY,
    2743                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2744                 :            :                                    NULL, "please close the port first");
    2745                 :          0 :                 ret = -rte_errno;
    2746                 :            :         } else {
    2747                 :          0 :                 sfc_sa2shared(sa)->isolated = (enable) ? B_TRUE : B_FALSE;
    2748                 :            :         }
    2749                 :            :         sfc_adapter_unlock(sa);
    2750                 :            : 
    2751                 :          0 :         return ret;
    2752                 :            : }
    2753                 :            : 
    2754                 :            : static int
    2755                 :          0 : sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
    2756                 :            :                              uint16_t *transfer_proxy_port,
    2757                 :            :                              struct rte_flow_error *error)
    2758                 :            : {
    2759                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2760                 :            :         int ret;
    2761                 :            : 
    2762                 :          0 :         ret = sfc_mae_get_switch_domain_admin(sa->mae.switch_domain_id,
    2763                 :            :                                               transfer_proxy_port);
    2764         [ #  # ]:          0 :         if (ret != 0) {
    2765                 :          0 :                 return rte_flow_error_set(error, ret,
    2766                 :            :                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2767                 :            :                                           NULL, NULL);
    2768                 :            :         }
    2769                 :            : 
    2770                 :            :         return 0;
    2771                 :            : }
    2772                 :            : 
    2773                 :            : static struct rte_flow_action_handle *
    2774         [ #  # ]:          0 : sfc_flow_action_handle_create(struct rte_eth_dev *dev,
    2775                 :            :                               const struct rte_flow_indir_action_conf *conf,
    2776                 :            :                               const struct rte_flow_action *action,
    2777                 :            :                               struct rte_flow_error *error)
    2778                 :            : {
    2779                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2780                 :            :         struct rte_flow_action_handle *handle;
    2781                 :            :         int ret;
    2782                 :            : 
    2783         [ #  # ]:          0 :         if (!conf->transfer) {
    2784                 :          0 :                 rte_flow_error_set(error, ENOTSUP,
    2785                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2786                 :            :                                    "non-transfer domain does not support indirect actions");
    2787                 :          0 :                 return NULL;
    2788                 :            :         }
    2789                 :            : 
    2790         [ #  # ]:          0 :         if (conf->ingress || conf->egress) {
    2791                 :          0 :                 rte_flow_error_set(error, EINVAL,
    2792                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
    2793                 :            :                                    NULL, "cannot combine ingress/egress with transfer");
    2794                 :          0 :                 return NULL;
    2795                 :            :         }
    2796                 :            : 
    2797                 :          0 :         handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0);
    2798         [ #  # ]:          0 :         if (handle == NULL) {
    2799                 :          0 :                 rte_flow_error_set(error, ENOMEM,
    2800                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2801                 :            :                                    "failed to allocate memory");
    2802                 :          0 :                 return NULL;
    2803                 :            :         }
    2804                 :            : 
    2805                 :          0 :         sfc_adapter_lock(sa);
    2806                 :            : 
    2807                 :          0 :         ret = sfc_mae_indir_action_create(sa, action, handle, error);
    2808         [ #  # ]:          0 :         if (ret != 0) {
    2809                 :            :                 sfc_adapter_unlock(sa);
    2810                 :          0 :                 rte_free(handle);
    2811                 :          0 :                 return NULL;
    2812                 :            :         }
    2813                 :            : 
    2814                 :          0 :         TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries);
    2815                 :            : 
    2816                 :          0 :         handle->transfer = (bool)conf->transfer;
    2817                 :            : 
    2818                 :            :         sfc_adapter_unlock(sa);
    2819                 :            : 
    2820                 :          0 :         return handle;
    2821                 :            : }
    2822                 :            : 
    2823                 :            : static int
    2824                 :          0 : sfc_flow_action_handle_destroy(struct rte_eth_dev *dev,
    2825                 :            :                                struct rte_flow_action_handle *handle,
    2826                 :            :                                struct rte_flow_error *error)
    2827                 :            : {
    2828                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2829                 :            :         struct rte_flow_action_handle *entry;
    2830                 :            :         int rc = EINVAL;
    2831                 :            : 
    2832                 :          0 :         sfc_adapter_lock(sa);
    2833                 :            : 
    2834         [ #  # ]:          0 :         TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
    2835         [ #  # ]:          0 :                 if (entry != handle)
    2836                 :            :                         continue;
    2837                 :            : 
    2838         [ #  # ]:          0 :                 if (entry->transfer) {
    2839                 :          0 :                         rc = sfc_mae_indir_action_destroy(sa, handle,
    2840                 :            :                                                           error);
    2841         [ #  # ]:          0 :                         if (rc != 0)
    2842                 :          0 :                                 goto exit;
    2843                 :            :                 } else {
    2844                 :            :                         SFC_ASSERT(B_FALSE);
    2845                 :            :                 }
    2846                 :            : 
    2847         [ #  # ]:          0 :                 TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries);
    2848                 :          0 :                 rte_free(entry);
    2849                 :          0 :                 goto exit;
    2850                 :            :         }
    2851                 :            : 
    2852                 :          0 :         rc = rte_flow_error_set(error, ENOENT,
    2853                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2854                 :            :                                 "indirect action handle not found");
    2855                 :            : 
    2856                 :          0 : exit:
    2857                 :            :         sfc_adapter_unlock(sa);
    2858                 :          0 :         return rc;
    2859                 :            : }
    2860                 :            : 
    2861                 :            : static int
    2862                 :          0 : sfc_flow_action_handle_update(struct rte_eth_dev *dev,
    2863                 :            :                               struct rte_flow_action_handle *handle,
    2864                 :            :                               const void *update, struct rte_flow_error *error)
    2865                 :            : {
    2866                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2867                 :            :         struct rte_flow_action_handle *entry;
    2868                 :            :         int rc = EINVAL;
    2869                 :            : 
    2870                 :          0 :         sfc_adapter_lock(sa);
    2871                 :            : 
    2872         [ #  # ]:          0 :         TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
    2873         [ #  # ]:          0 :                 if (entry != handle)
    2874                 :            :                         continue;
    2875                 :            : 
    2876         [ #  # ]:          0 :                 if (entry->transfer) {
    2877                 :          0 :                         rc = sfc_mae_indir_action_update(sa, handle,
    2878                 :            :                                                          update, error);
    2879                 :            :                 } else {
    2880                 :            :                         SFC_ASSERT(B_FALSE);
    2881                 :            :                 }
    2882                 :            : 
    2883                 :          0 :                 goto exit;
    2884                 :            :         }
    2885                 :            : 
    2886                 :          0 :         rc = rte_flow_error_set(error, ENOENT,
    2887                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2888                 :            :                                 "indirect action handle not found");
    2889                 :            : 
    2890                 :          0 : exit:
    2891                 :            :         sfc_adapter_unlock(sa);
    2892                 :          0 :         return rc;
    2893                 :            : }
    2894                 :            : 
    2895                 :            : static int
    2896                 :          0 : sfc_flow_action_handle_query(struct rte_eth_dev *dev,
    2897                 :            :                              const struct rte_flow_action_handle *handle,
    2898                 :            :                              void *data, struct rte_flow_error *error)
    2899                 :            : {
    2900                 :            :         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
    2901                 :            :         struct rte_flow_action_handle *entry;
    2902                 :            :         int rc = EINVAL;
    2903                 :            : 
    2904                 :          0 :         sfc_adapter_lock(sa);
    2905                 :            : 
    2906         [ #  # ]:          0 :         TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) {
    2907         [ #  # ]:          0 :                 if (entry != handle)
    2908                 :            :                         continue;
    2909                 :            : 
    2910         [ #  # ]:          0 :                 if (entry->transfer) {
    2911                 :          0 :                         rc = sfc_mae_indir_action_query(sa, handle,
    2912                 :            :                                                         data, error);
    2913                 :            :                 } else {
    2914                 :            :                         SFC_ASSERT(B_FALSE);
    2915                 :            :                 }
    2916                 :            : 
    2917                 :          0 :                 goto exit;
    2918                 :            :         }
    2919                 :            : 
    2920                 :          0 :         rc = rte_flow_error_set(error, ENOENT,
    2921                 :            :                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    2922                 :            :                                 "indirect action handle not found");
    2923                 :            : 
    2924                 :          0 : exit:
    2925                 :            :         sfc_adapter_unlock(sa);
    2926                 :          0 :         return rc;
    2927                 :            : }
    2928                 :            : 
    2929                 :            : const struct rte_flow_ops sfc_flow_ops = {
    2930                 :            :         .validate = sfc_flow_validate,
    2931                 :            :         .create = sfc_flow_create,
    2932                 :            :         .destroy = sfc_flow_destroy,
    2933                 :            :         .flush = sfc_flow_flush,
    2934                 :            :         .query = sfc_flow_query,
    2935                 :            :         .isolate = sfc_flow_isolate,
    2936                 :            :         .action_handle_create = sfc_flow_action_handle_create,
    2937                 :            :         .action_handle_destroy = sfc_flow_action_handle_destroy,
    2938                 :            :         .action_handle_update = sfc_flow_action_handle_update,
    2939                 :            :         .action_handle_query = sfc_flow_action_handle_query,
    2940                 :            :         .tunnel_decap_set = sfc_ft_decap_set,
    2941                 :            :         .tunnel_match = sfc_ft_match,
    2942                 :            :         .tunnel_action_decap_release = sfc_ft_action_decap_release,
    2943                 :            :         .tunnel_item_release = sfc_ft_item_release,
    2944                 :            :         .get_restore_info = sfc_ft_get_restore_info,
    2945                 :            :         .pick_transfer_proxy = sfc_flow_pick_transfer_proxy,
    2946                 :            : };
    2947                 :            : 
    2948                 :            : void
    2949                 :          0 : sfc_flow_init(struct sfc_adapter *sa)
    2950                 :            : {
    2951                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    2952                 :            : 
    2953                 :          0 :         TAILQ_INIT(&sa->flow_indir_actions);
    2954                 :          0 :         TAILQ_INIT(&sa->flow_list);
    2955                 :          0 : }
    2956                 :            : 
    2957                 :            : void
    2958                 :          0 : sfc_flow_fini(struct sfc_adapter *sa)
    2959                 :            : {
    2960                 :            :         struct rte_flow *flow;
    2961                 :            :         void *tmp;
    2962                 :            : 
    2963                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    2964                 :            : 
    2965         [ #  # ]:          0 :         RTE_TAILQ_FOREACH_SAFE(flow, &sa->flow_list, entries, tmp) {
    2966         [ #  # ]:          0 :                 if (flow->internal)
    2967                 :          0 :                         continue;
    2968                 :            : 
    2969         [ #  # ]:          0 :                 TAILQ_REMOVE(&sa->flow_list, flow, entries);
    2970                 :          0 :                 sfc_flow_free(sa, flow);
    2971                 :            :         }
    2972                 :          0 : }
    2973                 :            : 
    2974                 :            : void
    2975                 :          0 : sfc_flow_stop(struct sfc_adapter *sa)
    2976                 :            : {
    2977                 :            :         struct rte_flow *flow;
    2978                 :            : 
    2979                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    2980                 :            : 
    2981         [ #  # ]:          0 :         TAILQ_FOREACH(flow, &sa->flow_list, entries) {
    2982         [ #  # ]:          0 :                 if (!flow->internal)
    2983                 :          0 :                         sfc_flow_remove(sa, flow, NULL);
    2984                 :            :         }
    2985                 :            : 
    2986                 :            :         /*
    2987                 :            :          * MAE counter service is not stopped on flow rule remove to avoid
    2988                 :            :          * extra work. Make sure that it is stopped here.
    2989                 :            :          */
    2990                 :          0 :         sfc_mae_counter_stop(sa);
    2991                 :          0 : }
    2992                 :            : 
    2993                 :            : int
    2994                 :          0 : sfc_flow_start(struct sfc_adapter *sa)
    2995                 :            : {
    2996                 :            :         struct rte_flow *flow;
    2997                 :            :         int rc = 0;
    2998                 :            : 
    2999                 :          0 :         sfc_log_init(sa, "entry");
    3000                 :            : 
    3001                 :            :         SFC_ASSERT(sfc_adapter_is_locked(sa));
    3002                 :            : 
    3003                 :          0 :         sfc_ft_counters_reset(sa);
    3004                 :            : 
    3005         [ #  # ]:          0 :         TAILQ_FOREACH(flow, &sa->flow_list, entries) {
    3006         [ #  # ]:          0 :                 if (flow->internal)
    3007                 :          0 :                         continue;
    3008                 :            : 
    3009                 :          0 :                 rc = sfc_flow_insert(sa, flow, NULL);
    3010         [ #  # ]:          0 :                 if (rc != 0)
    3011                 :          0 :                         goto fail_bad_flow;
    3012                 :            :         }
    3013                 :            : 
    3014                 :          0 :         sfc_log_init(sa, "done");
    3015                 :            : 
    3016                 :          0 : fail_bad_flow:
    3017                 :          0 :         return rc;
    3018                 :            : }
    3019                 :            : 
    3020                 :            : static void
    3021                 :          0 : sfc_flow_cleanup(struct sfc_adapter *sa, struct rte_flow *flow)
    3022                 :            : {
    3023         [ #  # ]:          0 :         if (flow == NULL)
    3024                 :            :                 return;
    3025                 :            : 
    3026                 :          0 :         sfc_flow_rss_ctx_del(sa, flow->spec.filter.rss_ctx);
    3027                 :            : }

Generated by: LCOV version 1.14