LCOV - code coverage report
Current view: top level - drivers/net/enic - enic_flow.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 549 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 34 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 331 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <errno.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <rte_log.h>
       8                 :            : #include <ethdev_driver.h>
       9                 :            : #include <rte_flow_driver.h>
      10                 :            : #include <rte_ether.h>
      11                 :            : #include <rte_ip.h>
      12                 :            : #include <rte_udp.h>
      13                 :            : 
      14                 :            : #include "enic_compat.h"
      15                 :            : #include "enic.h"
      16                 :            : #include "vnic_dev.h"
      17                 :            : #include "vnic_nic.h"
      18                 :            : 
      19                 :            : /*
      20                 :            :  * Common arguments passed to copy_item functions. Use this structure
      21                 :            :  * so we can easily add new arguments.
      22                 :            :  * item: Item specification.
      23                 :            :  * filter: Partially filled in NIC filter structure.
      24                 :            :  * inner_ofst: If zero, this is an outer header. If non-zero, this is
      25                 :            :  *   the offset into L5 where the header begins.
      26                 :            :  * l2_proto_off: offset to EtherType eth or vlan header.
      27                 :            :  * l3_proto_off: offset to next protocol field in IPv4 or 6 header.
      28                 :            :  */
      29                 :            : struct copy_item_args {
      30                 :            :         const struct rte_flow_item *item;
      31                 :            :         struct filter_v2 *filter;
      32                 :            :         uint8_t *inner_ofst;
      33                 :            :         uint8_t l2_proto_off;
      34                 :            :         uint8_t l3_proto_off;
      35                 :            :         struct enic *enic;
      36                 :            : };
      37                 :            : 
      38                 :            : /* functions for copying items into enic filters */
      39                 :            : typedef int (enic_copy_item_fn)(struct copy_item_args *arg);
      40                 :            : 
      41                 :            : /** Info about how to copy items into enic filters. */
      42                 :            : struct enic_items {
      43                 :            :         /** Function for copying and validating an item. */
      44                 :            :         enic_copy_item_fn *copy_item;
      45                 :            :         /** List of valid previous items. */
      46                 :            :         const enum rte_flow_item_type * const prev_items;
      47                 :            :         /** True if it's OK for this item to be the first item. For some NIC
      48                 :            :          * versions, it's invalid to start the stack above layer 3.
      49                 :            :          */
      50                 :            :         const uint8_t valid_start_item;
      51                 :            :         /* Inner packet version of copy_item. */
      52                 :            :         enic_copy_item_fn *inner_copy_item;
      53                 :            : };
      54                 :            : 
      55                 :            : /** Filtering capabilities for various NIC and firmware versions. */
      56                 :            : struct enic_filter_cap {
      57                 :            :         /** list of valid items and their handlers and attributes. */
      58                 :            :         const struct enic_items *item_info;
      59                 :            :         /* Max type in the above list, used to detect unsupported types */
      60                 :            :         enum rte_flow_item_type max_item_type;
      61                 :            : };
      62                 :            : 
      63                 :            : /* functions for copying flow actions into enic actions */
      64                 :            : typedef int (copy_action_fn)(struct enic *enic,
      65                 :            :                              const struct rte_flow_action actions[],
      66                 :            :                              struct filter_action_v2 *enic_action);
      67                 :            : 
      68                 :            : /** Action capabilities for various NICs. */
      69                 :            : struct enic_action_cap {
      70                 :            :         /** list of valid actions */
      71                 :            :         const enum rte_flow_action_type *actions;
      72                 :            :         /** copy function for a particular NIC */
      73                 :            :         copy_action_fn *copy_fn;
      74                 :            : };
      75                 :            : 
      76                 :            : /* Forward declarations */
      77                 :            : static enic_copy_item_fn enic_copy_item_ipv4_v1;
      78                 :            : static enic_copy_item_fn enic_copy_item_udp_v1;
      79                 :            : static enic_copy_item_fn enic_copy_item_tcp_v1;
      80                 :            : static enic_copy_item_fn enic_copy_item_raw_v2;
      81                 :            : static enic_copy_item_fn enic_copy_item_eth_v2;
      82                 :            : static enic_copy_item_fn enic_copy_item_vlan_v2;
      83                 :            : static enic_copy_item_fn enic_copy_item_ipv4_v2;
      84                 :            : static enic_copy_item_fn enic_copy_item_ipv6_v2;
      85                 :            : static enic_copy_item_fn enic_copy_item_udp_v2;
      86                 :            : static enic_copy_item_fn enic_copy_item_tcp_v2;
      87                 :            : static enic_copy_item_fn enic_copy_item_sctp_v2;
      88                 :            : static enic_copy_item_fn enic_copy_item_vxlan_v2;
      89                 :            : static enic_copy_item_fn enic_copy_item_inner_eth_v2;
      90                 :            : static enic_copy_item_fn enic_copy_item_inner_vlan_v2;
      91                 :            : static enic_copy_item_fn enic_copy_item_inner_ipv4_v2;
      92                 :            : static enic_copy_item_fn enic_copy_item_inner_ipv6_v2;
      93                 :            : static enic_copy_item_fn enic_copy_item_inner_udp_v2;
      94                 :            : static enic_copy_item_fn enic_copy_item_inner_tcp_v2;
      95                 :            : static copy_action_fn enic_copy_action_v1;
      96                 :            : static copy_action_fn enic_copy_action_v2;
      97                 :            : 
      98                 :            : /**
      99                 :            :  * Legacy NICs or NICs with outdated firmware. Only 5-tuple perfect match
     100                 :            :  * is supported.
     101                 :            :  */
     102                 :            : static const struct enic_items enic_items_v1[] = {
     103                 :            :         [RTE_FLOW_ITEM_TYPE_IPV4] = {
     104                 :            :                 .copy_item = enic_copy_item_ipv4_v1,
     105                 :            :                 .valid_start_item = 1,
     106                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     107                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     108                 :            :                 },
     109                 :            :                 .inner_copy_item = NULL,
     110                 :            :         },
     111                 :            :         [RTE_FLOW_ITEM_TYPE_UDP] = {
     112                 :            :                 .copy_item = enic_copy_item_udp_v1,
     113                 :            :                 .valid_start_item = 0,
     114                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     115                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     116                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     117                 :            :                 },
     118                 :            :                 .inner_copy_item = NULL,
     119                 :            :         },
     120                 :            :         [RTE_FLOW_ITEM_TYPE_TCP] = {
     121                 :            :                 .copy_item = enic_copy_item_tcp_v1,
     122                 :            :                 .valid_start_item = 0,
     123                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     124                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     125                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     126                 :            :                 },
     127                 :            :                 .inner_copy_item = NULL,
     128                 :            :         },
     129                 :            : };
     130                 :            : 
     131                 :            : /**
     132                 :            :  * NICs have Advanced Filters capability but they are disabled. This means
     133                 :            :  * that layer 3 must be specified.
     134                 :            :  */
     135                 :            : static const struct enic_items enic_items_v2[] = {
     136                 :            :         [RTE_FLOW_ITEM_TYPE_RAW] = {
     137                 :            :                 .copy_item = enic_copy_item_raw_v2,
     138                 :            :                 .valid_start_item = 0,
     139                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     140                 :            :                                RTE_FLOW_ITEM_TYPE_UDP,
     141                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     142                 :            :                 },
     143                 :            :                 .inner_copy_item = NULL,
     144                 :            :         },
     145                 :            :         [RTE_FLOW_ITEM_TYPE_ETH] = {
     146                 :            :                 .copy_item = enic_copy_item_eth_v2,
     147                 :            :                 .valid_start_item = 1,
     148                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     149                 :            :                                RTE_FLOW_ITEM_TYPE_VXLAN,
     150                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     151                 :            :                 },
     152                 :            :                 .inner_copy_item = enic_copy_item_inner_eth_v2,
     153                 :            :         },
     154                 :            :         [RTE_FLOW_ITEM_TYPE_VLAN] = {
     155                 :            :                 .copy_item = enic_copy_item_vlan_v2,
     156                 :            :                 .valid_start_item = 1,
     157                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     158                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     159                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     160                 :            :                 },
     161                 :            :                 .inner_copy_item = enic_copy_item_inner_vlan_v2,
     162                 :            :         },
     163                 :            :         [RTE_FLOW_ITEM_TYPE_IPV4] = {
     164                 :            :                 .copy_item = enic_copy_item_ipv4_v2,
     165                 :            :                 .valid_start_item = 1,
     166                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     167                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     168                 :            :                                RTE_FLOW_ITEM_TYPE_VLAN,
     169                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     170                 :            :                 },
     171                 :            :                 .inner_copy_item = enic_copy_item_inner_ipv4_v2,
     172                 :            :         },
     173                 :            :         [RTE_FLOW_ITEM_TYPE_IPV6] = {
     174                 :            :                 .copy_item = enic_copy_item_ipv6_v2,
     175                 :            :                 .valid_start_item = 1,
     176                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     177                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     178                 :            :                                RTE_FLOW_ITEM_TYPE_VLAN,
     179                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     180                 :            :                 },
     181                 :            :                 .inner_copy_item = enic_copy_item_inner_ipv6_v2,
     182                 :            :         },
     183                 :            :         [RTE_FLOW_ITEM_TYPE_UDP] = {
     184                 :            :                 .copy_item = enic_copy_item_udp_v2,
     185                 :            :                 .valid_start_item = 0,
     186                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     187                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     188                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     189                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     190                 :            :                 },
     191                 :            :                 .inner_copy_item = enic_copy_item_inner_udp_v2,
     192                 :            :         },
     193                 :            :         [RTE_FLOW_ITEM_TYPE_TCP] = {
     194                 :            :                 .copy_item = enic_copy_item_tcp_v2,
     195                 :            :                 .valid_start_item = 0,
     196                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     197                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     198                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     199                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     200                 :            :                 },
     201                 :            :                 .inner_copy_item = enic_copy_item_inner_tcp_v2,
     202                 :            :         },
     203                 :            :         [RTE_FLOW_ITEM_TYPE_SCTP] = {
     204                 :            :                 .copy_item = enic_copy_item_sctp_v2,
     205                 :            :                 .valid_start_item = 0,
     206                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     207                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     208                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     209                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     210                 :            :                 },
     211                 :            :                 .inner_copy_item = NULL,
     212                 :            :         },
     213                 :            :         [RTE_FLOW_ITEM_TYPE_VXLAN] = {
     214                 :            :                 .copy_item = enic_copy_item_vxlan_v2,
     215                 :            :                 .valid_start_item = 0,
     216                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     217                 :            :                                RTE_FLOW_ITEM_TYPE_UDP,
     218                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     219                 :            :                 },
     220                 :            :                 .inner_copy_item = NULL,
     221                 :            :         },
     222                 :            : };
     223                 :            : 
     224                 :            : /** NICs with Advanced filters enabled */
     225                 :            : static const struct enic_items enic_items_v3[] = {
     226                 :            :         [RTE_FLOW_ITEM_TYPE_RAW] = {
     227                 :            :                 .copy_item = enic_copy_item_raw_v2,
     228                 :            :                 .valid_start_item = 0,
     229                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     230                 :            :                                RTE_FLOW_ITEM_TYPE_UDP,
     231                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     232                 :            :                 },
     233                 :            :                 .inner_copy_item = NULL,
     234                 :            :         },
     235                 :            :         [RTE_FLOW_ITEM_TYPE_ETH] = {
     236                 :            :                 .copy_item = enic_copy_item_eth_v2,
     237                 :            :                 .valid_start_item = 1,
     238                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     239                 :            :                                RTE_FLOW_ITEM_TYPE_VXLAN,
     240                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     241                 :            :                 },
     242                 :            :                 .inner_copy_item = enic_copy_item_inner_eth_v2,
     243                 :            :         },
     244                 :            :         [RTE_FLOW_ITEM_TYPE_VLAN] = {
     245                 :            :                 .copy_item = enic_copy_item_vlan_v2,
     246                 :            :                 .valid_start_item = 1,
     247                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     248                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     249                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     250                 :            :                 },
     251                 :            :                 .inner_copy_item = enic_copy_item_inner_vlan_v2,
     252                 :            :         },
     253                 :            :         [RTE_FLOW_ITEM_TYPE_IPV4] = {
     254                 :            :                 .copy_item = enic_copy_item_ipv4_v2,
     255                 :            :                 .valid_start_item = 1,
     256                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     257                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     258                 :            :                                RTE_FLOW_ITEM_TYPE_VLAN,
     259                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     260                 :            :                 },
     261                 :            :                 .inner_copy_item = enic_copy_item_inner_ipv4_v2,
     262                 :            :         },
     263                 :            :         [RTE_FLOW_ITEM_TYPE_IPV6] = {
     264                 :            :                 .copy_item = enic_copy_item_ipv6_v2,
     265                 :            :                 .valid_start_item = 1,
     266                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     267                 :            :                                RTE_FLOW_ITEM_TYPE_ETH,
     268                 :            :                                RTE_FLOW_ITEM_TYPE_VLAN,
     269                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     270                 :            :                 },
     271                 :            :                 .inner_copy_item = enic_copy_item_inner_ipv6_v2,
     272                 :            :         },
     273                 :            :         [RTE_FLOW_ITEM_TYPE_UDP] = {
     274                 :            :                 .copy_item = enic_copy_item_udp_v2,
     275                 :            :                 .valid_start_item = 1,
     276                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     277                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     278                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     279                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     280                 :            :                 },
     281                 :            :                 .inner_copy_item = enic_copy_item_inner_udp_v2,
     282                 :            :         },
     283                 :            :         [RTE_FLOW_ITEM_TYPE_TCP] = {
     284                 :            :                 .copy_item = enic_copy_item_tcp_v2,
     285                 :            :                 .valid_start_item = 1,
     286                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     287                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     288                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     289                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     290                 :            :                 },
     291                 :            :                 .inner_copy_item = enic_copy_item_inner_tcp_v2,
     292                 :            :         },
     293                 :            :         [RTE_FLOW_ITEM_TYPE_SCTP] = {
     294                 :            :                 .copy_item = enic_copy_item_sctp_v2,
     295                 :            :                 .valid_start_item = 0,
     296                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     297                 :            :                                RTE_FLOW_ITEM_TYPE_IPV4,
     298                 :            :                                RTE_FLOW_ITEM_TYPE_IPV6,
     299                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     300                 :            :                 },
     301                 :            :                 .inner_copy_item = NULL,
     302                 :            :         },
     303                 :            :         [RTE_FLOW_ITEM_TYPE_VXLAN] = {
     304                 :            :                 .copy_item = enic_copy_item_vxlan_v2,
     305                 :            :                 .valid_start_item = 1,
     306                 :            :                 .prev_items = (const enum rte_flow_item_type[]) {
     307                 :            :                                RTE_FLOW_ITEM_TYPE_UDP,
     308                 :            :                                RTE_FLOW_ITEM_TYPE_END,
     309                 :            :                 },
     310                 :            :                 .inner_copy_item = NULL,
     311                 :            :         },
     312                 :            : };
     313                 :            : 
     314                 :            : /** Filtering capabilities indexed this NICs supported filter type. */
     315                 :            : static const struct enic_filter_cap enic_filter_cap[] = {
     316                 :            :         [FILTER_IPV4_5TUPLE] = {
     317                 :            :                 .item_info = enic_items_v1,
     318                 :            :                 .max_item_type = RTE_FLOW_ITEM_TYPE_TCP,
     319                 :            :         },
     320                 :            :         [FILTER_USNIC_IP] = {
     321                 :            :                 .item_info = enic_items_v2,
     322                 :            :                 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN,
     323                 :            :         },
     324                 :            :         [FILTER_DPDK_1] = {
     325                 :            :                 .item_info = enic_items_v3,
     326                 :            :                 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN,
     327                 :            :         },
     328                 :            : };
     329                 :            : 
     330                 :            : /** Supported actions for older NICs */
     331                 :            : static const enum rte_flow_action_type enic_supported_actions_v1[] = {
     332                 :            :         RTE_FLOW_ACTION_TYPE_QUEUE,
     333                 :            :         RTE_FLOW_ACTION_TYPE_END,
     334                 :            : };
     335                 :            : 
     336                 :            : /** Supported actions for newer NICs */
     337                 :            : static const enum rte_flow_action_type enic_supported_actions_v2_id[] = {
     338                 :            :         RTE_FLOW_ACTION_TYPE_QUEUE,
     339                 :            :         RTE_FLOW_ACTION_TYPE_MARK,
     340                 :            :         RTE_FLOW_ACTION_TYPE_FLAG,
     341                 :            :         RTE_FLOW_ACTION_TYPE_RSS,
     342                 :            :         RTE_FLOW_ACTION_TYPE_PASSTHRU,
     343                 :            :         RTE_FLOW_ACTION_TYPE_END,
     344                 :            : };
     345                 :            : 
     346                 :            : static const enum rte_flow_action_type enic_supported_actions_v2_drop[] = {
     347                 :            :         RTE_FLOW_ACTION_TYPE_QUEUE,
     348                 :            :         RTE_FLOW_ACTION_TYPE_MARK,
     349                 :            :         RTE_FLOW_ACTION_TYPE_FLAG,
     350                 :            :         RTE_FLOW_ACTION_TYPE_DROP,
     351                 :            :         RTE_FLOW_ACTION_TYPE_RSS,
     352                 :            :         RTE_FLOW_ACTION_TYPE_PASSTHRU,
     353                 :            :         RTE_FLOW_ACTION_TYPE_END,
     354                 :            : };
     355                 :            : 
     356                 :            : /** Action capabilities indexed by NIC version information */
     357                 :            : static const struct enic_action_cap enic_action_cap[] = {
     358                 :            :         [FILTER_ACTION_RQ_STEERING_FLAG] = {
     359                 :            :                 .actions = enic_supported_actions_v1,
     360                 :            :                 .copy_fn = enic_copy_action_v1,
     361                 :            :         },
     362                 :            :         [FILTER_ACTION_FILTER_ID_FLAG] = {
     363                 :            :                 .actions = enic_supported_actions_v2_id,
     364                 :            :                 .copy_fn = enic_copy_action_v2,
     365                 :            :         },
     366                 :            :         [FILTER_ACTION_DROP_FLAG] = {
     367                 :            :                 .actions = enic_supported_actions_v2_drop,
     368                 :            :                 .copy_fn = enic_copy_action_v2,
     369                 :            :         },
     370                 :            : };
     371                 :            : 
     372                 :            : static int
     373                 :            : mask_exact_match(const uint8_t *supported, const uint8_t *supplied,
     374                 :            :                  unsigned int size)
     375                 :            : {
     376                 :            :         unsigned int i;
     377   [ #  #  #  #  :          0 :         for (i = 0; i < size; i++) {
                   #  # ]
     378   [ #  #  #  #  :          0 :                 if (supported[i] != supplied[i])
                   #  # ]
     379                 :            :                         return 0;
     380                 :            :         }
     381                 :            :         return 1;
     382                 :            : }
     383                 :            : 
     384                 :            : static int
     385                 :          0 : enic_copy_item_ipv4_v1(struct copy_item_args *arg)
     386                 :            : {
     387                 :          0 :         const struct rte_flow_item *item = arg->item;
     388                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     389                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
     390                 :            :         const struct rte_flow_item_ipv4 *mask = item->mask;
     391                 :            :         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
     392                 :          0 :         struct rte_ipv4_hdr supported_mask = {
     393                 :            :                 .src_addr = 0xffffffff,
     394                 :            :                 .dst_addr = 0xffffffff,
     395                 :            :         };
     396                 :            : 
     397                 :          0 :         ENICPMD_FUNC_TRACE();
     398                 :            : 
     399                 :            :         if (!mask)
     400                 :            :                 mask = &rte_flow_item_ipv4_mask;
     401                 :            : 
     402                 :            :         /* This is an exact match filter, both fields must be set */
     403   [ #  #  #  #  :          0 :         if (!spec || !spec->hdr.src_addr || !spec->hdr.dst_addr) {
                   #  # ]
     404                 :          0 :                 ENICPMD_LOG(ERR, "IPv4 exact match src/dst addr");
     405                 :          0 :                 return ENOTSUP;
     406                 :            :         }
     407                 :            : 
     408                 :            :         /* check that the supplied mask exactly matches capability */
     409         [ #  # ]:          0 :         if (!mask_exact_match((const uint8_t *)&supported_mask,
     410                 :          0 :                               (const uint8_t *)item->mask, sizeof(*mask))) {
     411                 :          0 :                 ENICPMD_LOG(ERR, "IPv4 exact match mask");
     412                 :          0 :                 return ENOTSUP;
     413                 :            :         }
     414                 :            : 
     415                 :          0 :         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
     416                 :          0 :         enic_5tup->src_addr = spec->hdr.src_addr;
     417                 :          0 :         enic_5tup->dst_addr = spec->hdr.dst_addr;
     418                 :            : 
     419                 :          0 :         return 0;
     420                 :            : }
     421                 :            : 
     422                 :            : static int
     423                 :          0 : enic_copy_item_udp_v1(struct copy_item_args *arg)
     424                 :            : {
     425                 :          0 :         const struct rte_flow_item *item = arg->item;
     426                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     427                 :          0 :         const struct rte_flow_item_udp *spec = item->spec;
     428                 :            :         const struct rte_flow_item_udp *mask = item->mask;
     429                 :            :         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
     430                 :          0 :         struct rte_udp_hdr supported_mask = {
     431                 :            :                 .src_port = 0xffff,
     432                 :            :                 .dst_port = 0xffff,
     433                 :            :         };
     434                 :            : 
     435                 :          0 :         ENICPMD_FUNC_TRACE();
     436                 :            : 
     437                 :            :         if (!mask)
     438                 :            :                 mask = &rte_flow_item_udp_mask;
     439                 :            : 
     440                 :            :         /* This is an exact match filter, both ports must be set */
     441   [ #  #  #  #  :          0 :         if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) {
                   #  # ]
     442                 :          0 :                 ENICPMD_LOG(ERR, "UDP exact match src/dst addr");
     443                 :          0 :                 return ENOTSUP;
     444                 :            :         }
     445                 :            : 
     446                 :            :         /* check that the supplied mask exactly matches capability */
     447         [ #  # ]:          0 :         if (!mask_exact_match((const uint8_t *)&supported_mask,
     448                 :          0 :                               (const uint8_t *)item->mask, sizeof(*mask))) {
     449                 :          0 :                 ENICPMD_LOG(ERR, "UDP exact match mask");
     450                 :          0 :                 return ENOTSUP;
     451                 :            :         }
     452                 :            : 
     453                 :          0 :         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
     454                 :          0 :         enic_5tup->src_port = spec->hdr.src_port;
     455                 :          0 :         enic_5tup->dst_port = spec->hdr.dst_port;
     456                 :          0 :         enic_5tup->protocol = PROTO_UDP;
     457                 :            : 
     458                 :          0 :         return 0;
     459                 :            : }
     460                 :            : 
     461                 :            : static int
     462                 :          0 : enic_copy_item_tcp_v1(struct copy_item_args *arg)
     463                 :            : {
     464                 :          0 :         const struct rte_flow_item *item = arg->item;
     465                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     466                 :          0 :         const struct rte_flow_item_tcp *spec = item->spec;
     467                 :            :         const struct rte_flow_item_tcp *mask = item->mask;
     468                 :            :         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
     469                 :          0 :         struct rte_tcp_hdr supported_mask = {
     470                 :            :                 .src_port = 0xffff,
     471                 :            :                 .dst_port = 0xffff,
     472                 :            :         };
     473                 :            : 
     474                 :          0 :         ENICPMD_FUNC_TRACE();
     475                 :            : 
     476                 :            :         if (!mask)
     477                 :            :                 mask = &rte_flow_item_tcp_mask;
     478                 :            : 
     479                 :            :         /* This is an exact match filter, both ports must be set */
     480   [ #  #  #  #  :          0 :         if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) {
                   #  # ]
     481                 :          0 :                 ENICPMD_LOG(ERR, "TCPIPv4 exact match src/dst addr");
     482                 :          0 :                 return ENOTSUP;
     483                 :            :         }
     484                 :            : 
     485                 :            :         /* check that the supplied mask exactly matches capability */
     486         [ #  # ]:          0 :         if (!mask_exact_match((const uint8_t *)&supported_mask,
     487                 :          0 :                              (const uint8_t *)item->mask, sizeof(*mask))) {
     488                 :          0 :                 ENICPMD_LOG(ERR, "TCP exact match mask");
     489                 :          0 :                 return ENOTSUP;
     490                 :            :         }
     491                 :            : 
     492                 :          0 :         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
     493                 :          0 :         enic_5tup->src_port = spec->hdr.src_port;
     494                 :          0 :         enic_5tup->dst_port = spec->hdr.dst_port;
     495                 :          0 :         enic_5tup->protocol = PROTO_TCP;
     496                 :            : 
     497                 :          0 :         return 0;
     498                 :            : }
     499                 :            : 
     500                 :            : /*
     501                 :            :  * The common 'copy' function for all inner packet patterns. Patterns are
     502                 :            :  * first appended to the L5 pattern buffer. Then, since the NIC filter
     503                 :            :  * API has no special support for inner packet matching at the moment,
     504                 :            :  * we set EtherType and IP proto as necessary.
     505                 :            :  */
     506                 :            : static int
     507                 :          0 : copy_inner_common(struct filter_generic_1 *gp, uint8_t *inner_ofst,
     508                 :            :                   const void *val, const void *mask, uint8_t val_size,
     509                 :            :                   uint8_t proto_off, uint16_t proto_val, uint8_t proto_size)
     510                 :            : {
     511                 :            :         uint8_t *l5_mask, *l5_val;
     512                 :            :         uint8_t start_off;
     513                 :            : 
     514                 :            :         /* No space left in the L5 pattern buffer. */
     515                 :          0 :         start_off = *inner_ofst;
     516         [ #  # ]:          0 :         if ((start_off + val_size) > FILTER_GENERIC_1_KEY_LEN)
     517                 :            :                 return ENOTSUP;
     518                 :          0 :         l5_mask = gp->layer[FILTER_GENERIC_1_L5].mask;
     519                 :          0 :         l5_val = gp->layer[FILTER_GENERIC_1_L5].val;
     520                 :            :         /* Copy the pattern into the L5 buffer. */
     521         [ #  # ]:          0 :         if (val) {
     522                 :          0 :                 memcpy(l5_mask + start_off, mask, val_size);
     523                 :          0 :                 memcpy(l5_val + start_off, val, val_size);
     524                 :            :         }
     525                 :            :         /* Set the protocol field in the previous header. */
     526         [ #  # ]:          0 :         if (proto_off) {
     527                 :            :                 void *m, *v;
     528                 :            : 
     529                 :          0 :                 m = l5_mask + proto_off;
     530                 :          0 :                 v = l5_val + proto_off;
     531         [ #  # ]:          0 :                 if (proto_size == 1) {
     532                 :          0 :                         *(uint8_t *)m = 0xff;
     533                 :          0 :                         *(uint8_t *)v = (uint8_t)proto_val;
     534         [ #  # ]:          0 :                 } else if (proto_size == 2) {
     535                 :          0 :                         *(uint16_t *)m = 0xffff;
     536                 :          0 :                         *(uint16_t *)v = proto_val;
     537                 :            :                 }
     538                 :            :         }
     539                 :            :         /* All inner headers land in L5 buffer even if their spec is null. */
     540                 :          0 :         *inner_ofst += val_size;
     541                 :          0 :         return 0;
     542                 :            : }
     543                 :            : 
     544                 :            : static int
     545                 :          0 : enic_copy_item_inner_eth_v2(struct copy_item_args *arg)
     546                 :            : {
     547                 :          0 :         const void *mask = arg->item->mask;
     548                 :          0 :         uint8_t *off = arg->inner_ofst;
     549                 :            : 
     550                 :          0 :         ENICPMD_FUNC_TRACE();
     551         [ #  # ]:          0 :         if (!mask)
     552                 :            :                 mask = &rte_flow_item_eth_mask;
     553                 :          0 :         arg->l2_proto_off = *off + offsetof(struct rte_ether_hdr, ether_type);
     554                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     555                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_ether_hdr),
     556                 :            :                 0 /* no previous protocol */, 0, 0);
     557                 :            : }
     558                 :            : 
     559                 :            : static int
     560                 :          0 : enic_copy_item_inner_vlan_v2(struct copy_item_args *arg)
     561                 :            : {
     562                 :          0 :         const void *mask = arg->item->mask;
     563                 :          0 :         uint8_t *off = arg->inner_ofst;
     564                 :            :         uint8_t eth_type_off;
     565                 :            : 
     566                 :          0 :         ENICPMD_FUNC_TRACE();
     567         [ #  # ]:          0 :         if (!mask)
     568                 :            :                 mask = &rte_flow_item_vlan_mask;
     569                 :            :         /* Append vlan header to L5 and set ether type = TPID */
     570                 :          0 :         eth_type_off = arg->l2_proto_off;
     571                 :          0 :         arg->l2_proto_off = *off + offsetof(struct rte_vlan_hdr, eth_proto);
     572                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     573                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_vlan_hdr),
     574                 :            :                 eth_type_off, rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN), 2);
     575                 :            : }
     576                 :            : 
     577                 :            : static int
     578                 :          0 : enic_copy_item_inner_ipv4_v2(struct copy_item_args *arg)
     579                 :            : {
     580                 :          0 :         const void *mask = arg->item->mask;
     581                 :          0 :         uint8_t *off = arg->inner_ofst;
     582                 :            : 
     583                 :          0 :         ENICPMD_FUNC_TRACE();
     584         [ #  # ]:          0 :         if (!mask)
     585                 :            :                 mask = &rte_flow_item_ipv4_mask;
     586                 :            :         /* Append ipv4 header to L5 and set ether type = ipv4 */
     587                 :          0 :         arg->l3_proto_off = *off + offsetof(struct rte_ipv4_hdr, next_proto_id);
     588                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     589                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_ipv4_hdr),
     590                 :          0 :                 arg->l2_proto_off, rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4), 2);
     591                 :            : }
     592                 :            : 
     593                 :            : static int
     594                 :          0 : enic_copy_item_inner_ipv6_v2(struct copy_item_args *arg)
     595                 :            : {
     596                 :          0 :         const void *mask = arg->item->mask;
     597                 :          0 :         uint8_t *off = arg->inner_ofst;
     598                 :            : 
     599                 :          0 :         ENICPMD_FUNC_TRACE();
     600         [ #  # ]:          0 :         if (!mask)
     601                 :            :                 mask = &rte_flow_item_ipv6_mask;
     602                 :            :         /* Append ipv6 header to L5 and set ether type = ipv6 */
     603                 :          0 :         arg->l3_proto_off = *off + offsetof(struct rte_ipv6_hdr, proto);
     604                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     605                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_ipv6_hdr),
     606                 :          0 :                 arg->l2_proto_off, rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6), 2);
     607                 :            : }
     608                 :            : 
     609                 :            : static int
     610                 :          0 : enic_copy_item_inner_udp_v2(struct copy_item_args *arg)
     611                 :            : {
     612                 :          0 :         const void *mask = arg->item->mask;
     613                 :          0 :         uint8_t *off = arg->inner_ofst;
     614                 :            : 
     615                 :          0 :         ENICPMD_FUNC_TRACE();
     616         [ #  # ]:          0 :         if (!mask)
     617                 :            :                 mask = &rte_flow_item_udp_mask;
     618                 :            :         /* Append udp header to L5 and set ip proto = udp */
     619                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     620                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_udp_hdr),
     621                 :          0 :                 arg->l3_proto_off, IPPROTO_UDP, 1);
     622                 :            : }
     623                 :            : 
     624                 :            : static int
     625                 :          0 : enic_copy_item_inner_tcp_v2(struct copy_item_args *arg)
     626                 :            : {
     627                 :          0 :         const void *mask = arg->item->mask;
     628                 :          0 :         uint8_t *off = arg->inner_ofst;
     629                 :            : 
     630                 :          0 :         ENICPMD_FUNC_TRACE();
     631         [ #  # ]:          0 :         if (!mask)
     632                 :            :                 mask = &rte_flow_item_tcp_mask;
     633                 :            :         /* Append tcp header to L5 and set ip proto = tcp */
     634                 :          0 :         return copy_inner_common(&arg->filter->u.generic_1, off,
     635                 :          0 :                 arg->item->spec, mask, sizeof(struct rte_tcp_hdr),
     636                 :          0 :                 arg->l3_proto_off, IPPROTO_TCP, 1);
     637                 :            : }
     638                 :            : 
     639                 :            : static int
     640                 :          0 : enic_copy_item_eth_v2(struct copy_item_args *arg)
     641                 :            : {
     642                 :          0 :         const struct rte_flow_item *item = arg->item;
     643                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     644                 :            :         struct rte_ether_hdr enic_spec;
     645                 :            :         struct rte_ether_hdr enic_mask;
     646                 :          0 :         const struct rte_flow_item_eth *spec = item->spec;
     647                 :          0 :         const struct rte_flow_item_eth *mask = item->mask;
     648                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     649                 :            : 
     650                 :          0 :         ENICPMD_FUNC_TRACE();
     651                 :            : 
     652                 :            :         /* Match all if no spec */
     653         [ #  # ]:          0 :         if (!spec)
     654                 :            :                 return 0;
     655                 :            : 
     656         [ #  # ]:          0 :         if (!mask)
     657                 :            :                 mask = &rte_flow_item_eth_mask;
     658                 :            : 
     659                 :            :         memcpy(enic_spec.dst_addr.addr_bytes, spec->hdr.dst_addr.addr_bytes,
     660                 :            :                RTE_ETHER_ADDR_LEN);
     661                 :            :         memcpy(enic_spec.src_addr.addr_bytes, spec->hdr.src_addr.addr_bytes,
     662                 :            :                RTE_ETHER_ADDR_LEN);
     663                 :            : 
     664                 :            :         memcpy(enic_mask.dst_addr.addr_bytes, mask->hdr.dst_addr.addr_bytes,
     665                 :            :                RTE_ETHER_ADDR_LEN);
     666                 :            :         memcpy(enic_mask.src_addr.addr_bytes, mask->hdr.src_addr.addr_bytes,
     667                 :            :                RTE_ETHER_ADDR_LEN);
     668                 :          0 :         enic_spec.ether_type = spec->hdr.ether_type;
     669                 :          0 :         enic_mask.ether_type = mask->hdr.ether_type;
     670                 :            : 
     671                 :            :         /* outer header */
     672                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask,
     673                 :            :                sizeof(struct rte_ether_hdr));
     674                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec,
     675                 :            :                sizeof(struct rte_ether_hdr));
     676                 :          0 :         return 0;
     677                 :            : }
     678                 :            : 
     679                 :            : static int
     680                 :          0 : enic_copy_item_vlan_v2(struct copy_item_args *arg)
     681                 :            : {
     682                 :          0 :         const struct rte_flow_item *item = arg->item;
     683                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     684                 :          0 :         const struct rte_flow_item_vlan *spec = item->spec;
     685                 :          0 :         const struct rte_flow_item_vlan *mask = item->mask;
     686                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     687                 :            :         struct rte_ether_hdr *eth_mask;
     688                 :            :         struct rte_ether_hdr *eth_val;
     689                 :            : 
     690                 :          0 :         ENICPMD_FUNC_TRACE();
     691                 :            : 
     692                 :            :         /* Match all if no spec */
     693         [ #  # ]:          0 :         if (!spec)
     694                 :            :                 return 0;
     695                 :            : 
     696         [ #  # ]:          0 :         if (!mask)
     697                 :            :                 mask = &rte_flow_item_vlan_mask;
     698                 :            : 
     699                 :            :         eth_mask = (void *)gp->layer[FILTER_GENERIC_1_L2].mask;
     700                 :            :         eth_val = (void *)gp->layer[FILTER_GENERIC_1_L2].val;
     701                 :            :         /* Outer TPID cannot be matched */
     702         [ #  # ]:          0 :         if (eth_mask->ether_type)
     703                 :            :                 return ENOTSUP;
     704                 :            :         /*
     705                 :            :          * For recent models:
     706                 :            :          * When packet matching, the VIC always compares vlan-stripped
     707                 :            :          * L2, regardless of vlan stripping settings. So, the inner type
     708                 :            :          * from vlan becomes the ether type of the eth header.
     709                 :            :          *
     710                 :            :          * Older models w/o hardware vxlan parser have a different
     711                 :            :          * behavior when vlan stripping is disabled. In this case,
     712                 :            :          * vlan tag remains in the L2 buffer.
     713                 :            :          */
     714   [ #  #  #  # ]:          0 :         if (!arg->enic->vxlan && !arg->enic->ig_vlan_strip_en) {
     715                 :            :                 struct rte_vlan_hdr *vlan;
     716                 :            : 
     717                 :            :                 vlan = (struct rte_vlan_hdr *)(eth_mask + 1);
     718                 :          0 :                 vlan->eth_proto = mask->hdr.eth_proto;
     719                 :            :                 vlan = (struct rte_vlan_hdr *)(eth_val + 1);
     720                 :          0 :                 vlan->eth_proto = spec->hdr.eth_proto;
     721                 :            :         } else {
     722                 :          0 :                 eth_mask->ether_type = mask->hdr.eth_proto;
     723                 :          0 :                 eth_val->ether_type = spec->hdr.eth_proto;
     724                 :            :         }
     725                 :            :         /* For TCI, use the vlan mask/val fields (little endian). */
     726         [ #  # ]:          0 :         gp->mask_vlan = rte_be_to_cpu_16(mask->hdr.vlan_tci);
     727         [ #  # ]:          0 :         gp->val_vlan = rte_be_to_cpu_16(spec->hdr.vlan_tci);
     728                 :          0 :         return 0;
     729                 :            : }
     730                 :            : 
     731                 :            : static int
     732                 :          0 : enic_copy_item_ipv4_v2(struct copy_item_args *arg)
     733                 :            : {
     734                 :          0 :         const struct rte_flow_item *item = arg->item;
     735                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     736                 :          0 :         const struct rte_flow_item_ipv4 *spec = item->spec;
     737                 :          0 :         const struct rte_flow_item_ipv4 *mask = item->mask;
     738                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     739                 :            : 
     740                 :          0 :         ENICPMD_FUNC_TRACE();
     741                 :            : 
     742                 :            :         /* Match IPv4 */
     743                 :          0 :         gp->mask_flags |= FILTER_GENERIC_1_IPV4;
     744                 :          0 :         gp->val_flags |= FILTER_GENERIC_1_IPV4;
     745                 :            : 
     746                 :            :         /* Match all if no spec */
     747         [ #  # ]:          0 :         if (!spec)
     748                 :            :                 return 0;
     749                 :            : 
     750         [ #  # ]:          0 :         if (!mask)
     751                 :            :                 mask = &rte_flow_item_ipv4_mask;
     752                 :            : 
     753                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,
     754                 :            :                sizeof(struct rte_ipv4_hdr));
     755                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,
     756                 :            :                sizeof(struct rte_ipv4_hdr));
     757                 :          0 :         return 0;
     758                 :            : }
     759                 :            : 
     760                 :            : static int
     761                 :          0 : enic_copy_item_ipv6_v2(struct copy_item_args *arg)
     762                 :            : {
     763                 :          0 :         const struct rte_flow_item *item = arg->item;
     764                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     765                 :          0 :         const struct rte_flow_item_ipv6 *spec = item->spec;
     766                 :          0 :         const struct rte_flow_item_ipv6 *mask = item->mask;
     767                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     768                 :            : 
     769                 :          0 :         ENICPMD_FUNC_TRACE();
     770                 :            : 
     771                 :            :         /* Match IPv6 */
     772                 :          0 :         gp->mask_flags |= FILTER_GENERIC_1_IPV6;
     773                 :          0 :         gp->val_flags |= FILTER_GENERIC_1_IPV6;
     774                 :            : 
     775                 :            :         /* Match all if no spec */
     776         [ #  # ]:          0 :         if (!spec)
     777                 :            :                 return 0;
     778                 :            : 
     779         [ #  # ]:          0 :         if (!mask)
     780                 :            :                 mask = &rte_flow_item_ipv6_mask;
     781                 :            : 
     782                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,
     783                 :            :                sizeof(struct rte_ipv6_hdr));
     784                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,
     785                 :            :                sizeof(struct rte_ipv6_hdr));
     786                 :          0 :         return 0;
     787                 :            : }
     788                 :            : 
     789                 :            : static int
     790                 :          0 : enic_copy_item_udp_v2(struct copy_item_args *arg)
     791                 :            : {
     792                 :          0 :         const struct rte_flow_item *item = arg->item;
     793                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     794                 :          0 :         const struct rte_flow_item_udp *spec = item->spec;
     795                 :          0 :         const struct rte_flow_item_udp *mask = item->mask;
     796                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     797                 :            : 
     798                 :          0 :         ENICPMD_FUNC_TRACE();
     799                 :            : 
     800                 :            :         /* Match UDP */
     801                 :          0 :         gp->mask_flags |= FILTER_GENERIC_1_UDP;
     802                 :          0 :         gp->val_flags |= FILTER_GENERIC_1_UDP;
     803                 :            : 
     804                 :            :         /* Match all if no spec */
     805         [ #  # ]:          0 :         if (!spec)
     806                 :            :                 return 0;
     807                 :            : 
     808         [ #  # ]:          0 :         if (!mask)
     809                 :            :                 mask = &rte_flow_item_udp_mask;
     810                 :            : 
     811                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
     812                 :            :                sizeof(struct rte_udp_hdr));
     813                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
     814                 :            :                sizeof(struct rte_udp_hdr));
     815                 :          0 :         return 0;
     816                 :            : }
     817                 :            : 
     818                 :            : static int
     819                 :          0 : enic_copy_item_tcp_v2(struct copy_item_args *arg)
     820                 :            : {
     821                 :          0 :         const struct rte_flow_item *item = arg->item;
     822                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     823                 :          0 :         const struct rte_flow_item_tcp *spec = item->spec;
     824                 :          0 :         const struct rte_flow_item_tcp *mask = item->mask;
     825                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     826                 :            : 
     827                 :          0 :         ENICPMD_FUNC_TRACE();
     828                 :            : 
     829                 :            :         /* Match TCP */
     830                 :          0 :         gp->mask_flags |= FILTER_GENERIC_1_TCP;
     831                 :          0 :         gp->val_flags |= FILTER_GENERIC_1_TCP;
     832                 :            : 
     833                 :            :         /* Match all if no spec */
     834         [ #  # ]:          0 :         if (!spec)
     835                 :            :                 return 0;
     836                 :            : 
     837         [ #  # ]:          0 :         if (!mask)
     838                 :            :                 return ENOTSUP;
     839                 :            : 
     840                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
     841                 :            :                sizeof(struct rte_tcp_hdr));
     842                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
     843                 :            :                sizeof(struct rte_tcp_hdr));
     844                 :          0 :         return 0;
     845                 :            : }
     846                 :            : 
     847                 :            : static int
     848                 :          0 : enic_copy_item_sctp_v2(struct copy_item_args *arg)
     849                 :            : {
     850                 :          0 :         const struct rte_flow_item *item = arg->item;
     851                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     852                 :          0 :         const struct rte_flow_item_sctp *spec = item->spec;
     853                 :          0 :         const struct rte_flow_item_sctp *mask = item->mask;
     854                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     855                 :            :         uint8_t *ip_proto_mask = NULL;
     856                 :            :         uint8_t *ip_proto = NULL;
     857                 :            : 
     858                 :          0 :         ENICPMD_FUNC_TRACE();
     859                 :            : 
     860                 :            :         /*
     861                 :            :          * The NIC filter API has no flags for "match sctp", so explicitly set
     862                 :            :          * the protocol number in the IP pattern.
     863                 :            :          */
     864         [ #  # ]:          0 :         if (gp->val_flags & FILTER_GENERIC_1_IPV4) {
     865                 :            :                 struct rte_ipv4_hdr *ip;
     866                 :            :                 ip = (struct rte_ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask;
     867                 :          0 :                 ip_proto_mask = &ip->next_proto_id;
     868                 :            :                 ip = (struct rte_ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].val;
     869                 :          0 :                 ip_proto = &ip->next_proto_id;
     870         [ #  # ]:          0 :         } else if (gp->val_flags & FILTER_GENERIC_1_IPV6) {
     871                 :            :                 struct rte_ipv6_hdr *ip;
     872                 :            :                 ip = (struct rte_ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask;
     873                 :          0 :                 ip_proto_mask = &ip->proto;
     874                 :            :                 ip = (struct rte_ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].val;
     875                 :          0 :                 ip_proto = &ip->proto;
     876                 :            :         } else {
     877                 :            :                 /* Need IPv4/IPv6 pattern first */
     878                 :            :                 return EINVAL;
     879                 :            :         }
     880                 :          0 :         *ip_proto = IPPROTO_SCTP;
     881                 :          0 :         *ip_proto_mask = 0xff;
     882                 :            : 
     883                 :            :         /* Match all if no spec */
     884         [ #  # ]:          0 :         if (!spec)
     885                 :            :                 return 0;
     886                 :            : 
     887         [ #  # ]:          0 :         if (!mask)
     888                 :            :                 mask = &rte_flow_item_sctp_mask;
     889                 :            : 
     890                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
     891                 :            :                sizeof(struct rte_sctp_hdr));
     892                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
     893                 :            :                sizeof(struct rte_sctp_hdr));
     894                 :          0 :         return 0;
     895                 :            : }
     896                 :            : 
     897                 :            : static int
     898                 :          0 : enic_copy_item_vxlan_v2(struct copy_item_args *arg)
     899                 :            : {
     900                 :          0 :         const struct rte_flow_item *item = arg->item;
     901                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     902                 :          0 :         uint8_t *inner_ofst = arg->inner_ofst;
     903                 :          0 :         const struct rte_flow_item_vxlan *spec = item->spec;
     904                 :          0 :         const struct rte_flow_item_vxlan *mask = item->mask;
     905                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     906                 :            :         struct rte_udp_hdr *udp;
     907                 :            : 
     908                 :          0 :         ENICPMD_FUNC_TRACE();
     909                 :            : 
     910                 :            :         /*
     911                 :            :          * The NIC filter API has no flags for "match vxlan". Set UDP port to
     912                 :            :          * avoid false positives.
     913                 :            :          */
     914                 :          0 :         gp->mask_flags |= FILTER_GENERIC_1_UDP;
     915                 :          0 :         gp->val_flags |= FILTER_GENERIC_1_UDP;
     916                 :            :         udp = (struct rte_udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].mask;
     917                 :          0 :         udp->dst_port = 0xffff;
     918                 :            :         udp = (struct rte_udp_hdr *)gp->layer[FILTER_GENERIC_1_L4].val;
     919                 :          0 :         udp->dst_port = RTE_BE16(4789);
     920                 :            :         /* Match all if no spec */
     921         [ #  # ]:          0 :         if (!spec)
     922                 :            :                 return 0;
     923                 :            : 
     924         [ #  # ]:          0 :         if (!mask)
     925                 :            :                 mask = &rte_flow_item_vxlan_mask;
     926                 :            : 
     927                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, mask,
     928                 :            :                sizeof(struct rte_vxlan_hdr));
     929                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L5].val, spec,
     930                 :            :                sizeof(struct rte_vxlan_hdr));
     931                 :            : 
     932                 :          0 :         *inner_ofst = sizeof(struct rte_vxlan_hdr);
     933                 :          0 :         return 0;
     934                 :            : }
     935                 :            : 
     936                 :            : /*
     937                 :            :  * Copy raw item into version 2 NIC filter. Currently, raw pattern match is
     938                 :            :  * very limited. It is intended for matching UDP tunnel header (e.g. vxlan
     939                 :            :  * or geneve).
     940                 :            :  */
     941                 :            : static int
     942                 :          0 : enic_copy_item_raw_v2(struct copy_item_args *arg)
     943                 :            : {
     944                 :          0 :         const struct rte_flow_item *item = arg->item;
     945                 :          0 :         struct filter_v2 *enic_filter = arg->filter;
     946                 :          0 :         uint8_t *inner_ofst = arg->inner_ofst;
     947                 :          0 :         const struct rte_flow_item_raw *spec = item->spec;
     948                 :          0 :         const struct rte_flow_item_raw *mask = item->mask;
     949                 :            :         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
     950                 :            : 
     951                 :          0 :         ENICPMD_FUNC_TRACE();
     952                 :            : 
     953                 :            :         /* Cannot be used for inner packet */
     954         [ #  # ]:          0 :         if (*inner_ofst)
     955                 :            :                 return EINVAL;
     956                 :            :         /* Need both spec and mask */
     957         [ #  # ]:          0 :         if (!spec || !mask)
     958                 :            :                 return EINVAL;
     959                 :            :         /* Only supports relative with offset 0 */
     960   [ #  #  #  # ]:          0 :         if (!spec->relative || spec->offset != 0 || spec->search || spec->limit)
     961                 :            :                 return EINVAL;
     962                 :            :         /* Need non-null pattern that fits within the NIC's filter pattern */
     963         [ #  # ]:          0 :         if (spec->length == 0 ||
     964         [ #  # ]:          0 :             spec->length + sizeof(struct rte_udp_hdr) > FILTER_GENERIC_1_KEY_LEN ||
     965   [ #  #  #  # ]:          0 :             !spec->pattern || !mask->pattern)
     966                 :            :                 return EINVAL;
     967                 :            :         /*
     968                 :            :          * Mask fields, including length, are often set to zero. Assume that
     969                 :            :          * means "same as spec" to avoid breaking existing apps. If length
     970                 :            :          * is not zero, then it should be >= spec length.
     971                 :            :          *
     972                 :            :          * No more pattern follows this, so append to the L4 layer instead of
     973                 :            :          * L5 to work with both recent and older VICs.
     974                 :            :          */
     975   [ #  #  #  # ]:          0 :         if (mask->length != 0 && mask->length < spec->length)
     976                 :            :                 return EINVAL;
     977                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask + sizeof(struct rte_udp_hdr),
     978                 :            :                mask->pattern, spec->length);
     979                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].val + sizeof(struct rte_udp_hdr),
     980                 :          0 :                spec->pattern, spec->length);
     981                 :            : 
     982                 :          0 :         return 0;
     983                 :            : }
     984                 :            : 
     985                 :            : /**
     986                 :            :  * Return 1 if current item is valid on top of the previous one.
     987                 :            :  *
     988                 :            :  * @param prev_item[in]
     989                 :            :  *   The item before this one in the pattern or RTE_FLOW_ITEM_TYPE_END if this
     990                 :            :  *   is the first item.
     991                 :            :  * @param item_info[in]
     992                 :            :  *   Info about this item, like valid previous items.
     993                 :            :  * @param is_first[in]
     994                 :            :  *   True if this the first item in the pattern.
     995                 :            :  */
     996                 :            : static int
     997                 :          0 : item_stacking_valid(enum rte_flow_item_type prev_item,
     998                 :            :                     const struct enic_items *item_info, uint8_t is_first_item)
     999                 :            : {
    1000                 :          0 :         enum rte_flow_item_type const *allowed_items = item_info->prev_items;
    1001                 :            : 
    1002                 :          0 :         ENICPMD_FUNC_TRACE();
    1003                 :            : 
    1004         [ #  # ]:          0 :         for (; *allowed_items != RTE_FLOW_ITEM_TYPE_END; allowed_items++) {
    1005         [ #  # ]:          0 :                 if (prev_item == *allowed_items)
    1006                 :            :                         return 1;
    1007                 :            :         }
    1008                 :            : 
    1009                 :            :         /* This is the first item in the stack. Check if that's cool */
    1010   [ #  #  #  # ]:          0 :         if (is_first_item && item_info->valid_start_item)
    1011                 :          0 :                 return 1;
    1012                 :            : 
    1013                 :            :         return 0;
    1014                 :            : }
    1015                 :            : 
    1016                 :            : /*
    1017                 :            :  * Fix up the L5 layer.. HW vxlan parsing removes vxlan header from L5.
    1018                 :            :  * Instead it is in L4 following the UDP header. Append the vxlan
    1019                 :            :  * pattern to L4 (udp) and shift any inner packet pattern in L5.
    1020                 :            :  */
    1021                 :            : static void
    1022                 :          0 : fixup_l5_layer(struct enic *enic, struct filter_generic_1 *gp,
    1023                 :            :                uint8_t inner_ofst)
    1024                 :            : {
    1025                 :            :         uint8_t layer[FILTER_GENERIC_1_KEY_LEN];
    1026                 :            :         uint8_t inner;
    1027                 :            :         uint8_t vxlan;
    1028                 :            : 
    1029   [ #  #  #  # ]:          0 :         if (!(inner_ofst > 0 && enic->vxlan))
    1030                 :          0 :                 return;
    1031                 :          0 :         ENICPMD_FUNC_TRACE();
    1032                 :            :         vxlan = sizeof(struct rte_vxlan_hdr);
    1033                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask + sizeof(struct rte_udp_hdr),
    1034                 :          0 :                gp->layer[FILTER_GENERIC_1_L5].mask, vxlan);
    1035                 :          0 :         memcpy(gp->layer[FILTER_GENERIC_1_L4].val + sizeof(struct rte_udp_hdr),
    1036                 :          0 :                gp->layer[FILTER_GENERIC_1_L5].val, vxlan);
    1037                 :          0 :         inner = inner_ofst - vxlan;
    1038                 :            :         memset(layer, 0, sizeof(layer));
    1039                 :          0 :         memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].mask + vxlan, inner);
    1040                 :            :         memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, layer, sizeof(layer));
    1041                 :            :         memset(layer, 0, sizeof(layer));
    1042                 :          0 :         memcpy(layer, gp->layer[FILTER_GENERIC_1_L5].val + vxlan, inner);
    1043                 :            :         memcpy(gp->layer[FILTER_GENERIC_1_L5].val, layer, sizeof(layer));
    1044                 :            : }
    1045                 :            : 
    1046                 :            : /**
    1047                 :            :  * Build the internal enic filter structure from the provided pattern. The
    1048                 :            :  * pattern is validated as the items are copied.
    1049                 :            :  *
    1050                 :            :  * @param pattern[in]
    1051                 :            :  * @param items_info[in]
    1052                 :            :  *   Info about this NICs item support, like valid previous items.
    1053                 :            :  * @param enic_filter[out]
    1054                 :            :  *   NIC specific filters derived from the pattern.
    1055                 :            :  * @param error[out]
    1056                 :            :  */
    1057                 :            : static int
    1058                 :          0 : enic_copy_filter(const struct rte_flow_item pattern[],
    1059                 :            :                  const struct enic_filter_cap *cap,
    1060                 :            :                  struct enic *enic,
    1061                 :            :                  struct filter_v2 *enic_filter,
    1062                 :            :                  struct rte_flow_error *error)
    1063                 :            : {
    1064                 :            :         int ret;
    1065                 :            :         const struct rte_flow_item *item = pattern;
    1066                 :          0 :         uint8_t inner_ofst = 0; /* If encapsulated, ofst into L5 */
    1067                 :            :         enum rte_flow_item_type prev_item;
    1068                 :            :         const struct enic_items *item_info;
    1069                 :            :         struct copy_item_args args;
    1070                 :            :         enic_copy_item_fn *copy_fn;
    1071                 :            :         uint8_t is_first_item = 1;
    1072                 :            : 
    1073                 :          0 :         ENICPMD_FUNC_TRACE();
    1074                 :            : 
    1075                 :            :         prev_item = 0;
    1076                 :            : 
    1077                 :          0 :         args.filter = enic_filter;
    1078                 :          0 :         args.inner_ofst = &inner_ofst;
    1079                 :          0 :         args.enic = enic;
    1080         [ #  # ]:          0 :         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
    1081                 :            :                 /* Get info about how to validate and copy the item. If NULL
    1082                 :            :                  * is returned the nic does not support the item.
    1083                 :            :                  */
    1084         [ #  # ]:          0 :                 if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
    1085                 :          0 :                         continue;
    1086                 :            : 
    1087                 :          0 :                 item_info = &cap->item_info[item->type];
    1088         [ #  # ]:          0 :                 if (item->type > cap->max_item_type ||
    1089         [ #  # ]:          0 :                     item_info->copy_item == NULL ||
    1090   [ #  #  #  # ]:          0 :                     (inner_ofst > 0 && item_info->inner_copy_item == NULL)) {
    1091                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1092                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM,
    1093                 :            :                                 NULL, "Unsupported item.");
    1094                 :          0 :                         return -rte_errno;
    1095                 :            :                 }
    1096                 :            : 
    1097                 :            :                 /* check to see if item stacking is valid */
    1098         [ #  # ]:          0 :                 if (!item_stacking_valid(prev_item, item_info, is_first_item))
    1099                 :          0 :                         goto stacking_error;
    1100                 :            : 
    1101                 :          0 :                 args.item = item;
    1102         [ #  # ]:          0 :                 copy_fn = inner_ofst > 0 ? item_info->inner_copy_item :
    1103                 :            :                         item_info->copy_item;
    1104                 :          0 :                 ret = copy_fn(&args);
    1105         [ #  # ]:          0 :                 if (ret)
    1106                 :          0 :                         goto item_not_supported;
    1107                 :          0 :                 prev_item = item->type;
    1108                 :            :                 is_first_item = 0;
    1109                 :            :         }
    1110                 :          0 :         fixup_l5_layer(enic, &enic_filter->u.generic_1, inner_ofst);
    1111                 :            : 
    1112                 :          0 :         return 0;
    1113                 :            : 
    1114                 :            : item_not_supported:
    1115                 :          0 :         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_ITEM,
    1116                 :            :                            NULL, "enic type error");
    1117                 :          0 :         return -rte_errno;
    1118                 :            : 
    1119                 :            : stacking_error:
    1120                 :          0 :         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
    1121                 :            :                            item, "stacking error");
    1122                 :          0 :         return -rte_errno;
    1123                 :            : }
    1124                 :            : 
    1125                 :            : /**
    1126                 :            :  * Build the internal version 1 NIC action structure from the provided pattern.
    1127                 :            :  * The pattern is validated as the items are copied.
    1128                 :            :  *
    1129                 :            :  * @param actions[in]
    1130                 :            :  * @param enic_action[out]
    1131                 :            :  *   NIC specific actions derived from the actions.
    1132                 :            :  * @param error[out]
    1133                 :            :  */
    1134                 :            : static int
    1135                 :          0 : enic_copy_action_v1(__rte_unused struct enic *enic,
    1136                 :            :                     const struct rte_flow_action actions[],
    1137                 :            :                     struct filter_action_v2 *enic_action)
    1138                 :            : {
    1139                 :            :         enum { FATE = 1, };
    1140                 :            :         uint32_t overlap = 0;
    1141                 :            : 
    1142                 :          0 :         ENICPMD_FUNC_TRACE();
    1143                 :            : 
    1144         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    1145         [ #  # ]:          0 :                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID)
    1146                 :          0 :                         continue;
    1147                 :            : 
    1148         [ #  # ]:          0 :                 switch (actions->type) {
    1149                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE: {
    1150                 :          0 :                         const struct rte_flow_action_queue *queue =
    1151                 :            :                                 (const struct rte_flow_action_queue *)
    1152                 :            :                                 actions->conf;
    1153                 :            : 
    1154         [ #  # ]:          0 :                         if (overlap & FATE)
    1155                 :            :                                 return ENOTSUP;
    1156                 :            :                         overlap |= FATE;
    1157                 :          0 :                         enic_action->rq_idx =
    1158                 :          0 :                                 enic_rte_rq_idx_to_sop_idx(queue->index);
    1159                 :          0 :                         break;
    1160                 :            :                 }
    1161                 :            :                 default:
    1162                 :            :                         RTE_ASSERT(0);
    1163                 :            :                         break;
    1164                 :            :                 }
    1165                 :            :         }
    1166         [ #  # ]:          0 :         if (!(overlap & FATE))
    1167                 :            :                 return ENOTSUP;
    1168                 :          0 :         enic_action->type = FILTER_ACTION_RQ_STEERING;
    1169                 :          0 :         return 0;
    1170                 :            : }
    1171                 :            : 
    1172                 :            : /**
    1173                 :            :  * Build the internal version 2 NIC action structure from the provided pattern.
    1174                 :            :  * The pattern is validated as the items are copied.
    1175                 :            :  *
    1176                 :            :  * @param actions[in]
    1177                 :            :  * @param enic_action[out]
    1178                 :            :  *   NIC specific actions derived from the actions.
    1179                 :            :  * @param error[out]
    1180                 :            :  */
    1181                 :            : static int
    1182                 :          0 : enic_copy_action_v2(struct enic *enic,
    1183                 :            :                     const struct rte_flow_action actions[],
    1184                 :            :                     struct filter_action_v2 *enic_action)
    1185                 :            : {
    1186                 :            :         enum { FATE = 1, MARK = 2, };
    1187                 :            :         uint32_t overlap = 0;
    1188                 :            :         bool passthru = false;
    1189                 :            : 
    1190                 :          0 :         ENICPMD_FUNC_TRACE();
    1191                 :            : 
    1192         [ #  # ]:          0 :         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
    1193   [ #  #  #  #  :          0 :                 switch (actions->type) {
             #  #  #  # ]
    1194                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE: {
    1195                 :          0 :                         const struct rte_flow_action_queue *queue =
    1196                 :            :                                 (const struct rte_flow_action_queue *)
    1197                 :            :                                 actions->conf;
    1198                 :            : 
    1199         [ #  # ]:          0 :                         if (overlap & FATE)
    1200                 :            :                                 return ENOTSUP;
    1201                 :          0 :                         overlap |= FATE;
    1202                 :          0 :                         enic_action->rq_idx =
    1203                 :          0 :                                 enic_rte_rq_idx_to_sop_idx(queue->index);
    1204                 :          0 :                         enic_action->flags |= FILTER_ACTION_RQ_STEERING_FLAG;
    1205                 :          0 :                         break;
    1206                 :            :                 }
    1207                 :          0 :                 case RTE_FLOW_ACTION_TYPE_MARK: {
    1208                 :          0 :                         const struct rte_flow_action_mark *mark =
    1209                 :            :                                 (const struct rte_flow_action_mark *)
    1210                 :            :                                 actions->conf;
    1211         [ #  # ]:          0 :                         if (enic->use_noscatter_vec_rx_handler)
    1212                 :            :                                 return ENOTSUP;
    1213         [ #  # ]:          0 :                         if (overlap & MARK)
    1214                 :            :                                 return ENOTSUP;
    1215                 :          0 :                         overlap |= MARK;
    1216                 :            :                         /*
    1217                 :            :                          * Map mark ID (32-bit) to filter ID (16-bit):
    1218                 :            :                          * - Reject values > 16 bits
    1219                 :            :                          * - Filter ID 0 is reserved for filters that steer
    1220                 :            :                          *   but not mark. So add 1 to the mark ID to avoid
    1221                 :            :                          *   using 0.
    1222                 :            :                          * - Filter ID (ENIC_MAGIC_FILTER_ID = 0xffff) is
    1223                 :            :                          *   reserved for the "flag" action below.
    1224                 :            :                          */
    1225         [ #  # ]:          0 :                         if (mark->id >= ENIC_MAGIC_FILTER_ID - 1)
    1226                 :            :                                 return EINVAL;
    1227                 :          0 :                         enic_action->filter_id = mark->id + 1;
    1228                 :          0 :                         enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG;
    1229                 :          0 :                         break;
    1230                 :            :                 }
    1231                 :          0 :                 case RTE_FLOW_ACTION_TYPE_FLAG: {
    1232         [ #  # ]:          0 :                         if (enic->use_noscatter_vec_rx_handler)
    1233                 :            :                                 return ENOTSUP;
    1234         [ #  # ]:          0 :                         if (overlap & MARK)
    1235                 :            :                                 return ENOTSUP;
    1236                 :          0 :                         overlap |= MARK;
    1237                 :            :                         /* ENIC_MAGIC_FILTER_ID is reserved for flagging */
    1238                 :          0 :                         enic_action->filter_id = ENIC_MAGIC_FILTER_ID;
    1239                 :          0 :                         enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG;
    1240                 :          0 :                         break;
    1241                 :            :                 }
    1242                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP: {
    1243         [ #  # ]:          0 :                         if (overlap & FATE)
    1244                 :            :                                 return ENOTSUP;
    1245                 :          0 :                         overlap |= FATE;
    1246                 :          0 :                         enic_action->flags |= FILTER_ACTION_DROP_FLAG;
    1247                 :          0 :                         break;
    1248                 :            :                 }
    1249                 :          0 :                 case RTE_FLOW_ACTION_TYPE_RSS: {
    1250                 :          0 :                         const struct rte_flow_action_rss *rss =
    1251                 :            :                                 (const struct rte_flow_action_rss *)
    1252                 :            :                                 actions->conf;
    1253                 :            :                         bool allow;
    1254                 :            :                         uint16_t i;
    1255                 :            : 
    1256                 :            :                         /*
    1257                 :            :                          * Hardware does not support general RSS actions, but
    1258                 :            :                          * we can still support the dummy one that is used to
    1259                 :            :                          * "receive normally".
    1260                 :            :                          */
    1261                 :          0 :                         allow = rss->func == RTE_ETH_HASH_FUNCTION_DEFAULT &&
    1262                 :          0 :                                 rss->level == 0 &&
    1263         [ #  # ]:          0 :                                 (rss->types == 0 ||
    1264         [ #  # ]:          0 :                                  rss->types == enic->rss_hf) &&
    1265   [ #  #  #  # ]:          0 :                                 rss->queue_num == enic->rq_count &&
    1266         [ #  # ]:          0 :                                 rss->key_len == 0;
    1267                 :            :                         /* Identity queue map is ok */
    1268         [ #  # ]:          0 :                         for (i = 0; i < rss->queue_num; i++)
    1269   [ #  #  #  # ]:          0 :                                 allow = allow && (i == rss->queue[i]);
    1270         [ #  # ]:          0 :                         if (!allow)
    1271                 :            :                                 return ENOTSUP;
    1272         [ #  # ]:          0 :                         if (overlap & FATE)
    1273                 :            :                                 return ENOTSUP;
    1274                 :            :                         /* Need MARK or FLAG */
    1275         [ #  # ]:          0 :                         if (!(overlap & MARK))
    1276                 :            :                                 return ENOTSUP;
    1277                 :          0 :                         overlap |= FATE;
    1278                 :          0 :                         break;
    1279                 :            :                 }
    1280                 :          0 :                 case RTE_FLOW_ACTION_TYPE_PASSTHRU: {
    1281                 :            :                         /*
    1282                 :            :                          * Like RSS above, PASSTHRU + MARK may be used to
    1283                 :            :                          * "mark and then receive normally". MARK usually comes
    1284                 :            :                          * after PASSTHRU, so remember we have seen passthru
    1285                 :            :                          * and check for mark later.
    1286                 :            :                          */
    1287         [ #  # ]:          0 :                         if (overlap & FATE)
    1288                 :            :                                 return ENOTSUP;
    1289                 :          0 :                         overlap |= FATE;
    1290                 :            :                         passthru = true;
    1291                 :          0 :                         break;
    1292                 :            :                 }
    1293                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VOID:
    1294                 :          0 :                         continue;
    1295                 :            :                 default:
    1296                 :            :                         RTE_ASSERT(0);
    1297                 :            :                         break;
    1298                 :            :                 }
    1299                 :            :         }
    1300                 :            :         /* Only PASSTHRU + MARK is allowed */
    1301   [ #  #  #  # ]:          0 :         if (passthru && !(overlap & MARK))
    1302                 :            :                 return ENOTSUP;
    1303         [ #  # ]:          0 :         if (!(overlap & FATE))
    1304                 :            :                 return ENOTSUP;
    1305                 :          0 :         enic_action->type = FILTER_ACTION_V2;
    1306                 :          0 :         return 0;
    1307                 :            : }
    1308                 :            : 
    1309                 :            : /** Check if the action is supported */
    1310                 :            : static int
    1311                 :            : enic_match_action(const struct rte_flow_action *action,
    1312                 :            :                   const enum rte_flow_action_type *supported_actions)
    1313                 :            : {
    1314         [ #  # ]:          0 :         for (; *supported_actions != RTE_FLOW_ACTION_TYPE_END;
    1315                 :          0 :              supported_actions++) {
    1316         [ #  # ]:          0 :                 if (action->type == *supported_actions)
    1317                 :            :                         return 1;
    1318                 :            :         }
    1319                 :            :         return 0;
    1320                 :            : }
    1321                 :            : 
    1322                 :            : /** Get the NIC filter capabilties structure */
    1323                 :            : static const struct enic_filter_cap *
    1324                 :            : enic_get_filter_cap(struct enic *enic)
    1325                 :            : {
    1326         [ #  # ]:          0 :         if (enic->flow_filter_mode)
    1327                 :          0 :                 return &enic_filter_cap[enic->flow_filter_mode];
    1328                 :            : 
    1329                 :            :         return NULL;
    1330                 :            : }
    1331                 :            : 
    1332                 :            : /** Get the actions for this NIC version. */
    1333                 :            : static const struct enic_action_cap *
    1334                 :            : enic_get_action_cap(struct enic *enic)
    1335                 :            : {
    1336                 :            :         const struct enic_action_cap *ea;
    1337                 :            :         uint8_t actions;
    1338                 :            : 
    1339                 :          0 :         actions = enic->filter_actions;
    1340         [ #  # ]:          0 :         if (actions & FILTER_ACTION_DROP_FLAG)
    1341                 :            :                 ea = &enic_action_cap[FILTER_ACTION_DROP_FLAG];
    1342         [ #  # ]:          0 :         else if (actions & FILTER_ACTION_FILTER_ID_FLAG)
    1343                 :            :                 ea = &enic_action_cap[FILTER_ACTION_FILTER_ID_FLAG];
    1344                 :            :         else
    1345                 :            :                 ea = &enic_action_cap[FILTER_ACTION_RQ_STEERING_FLAG];
    1346                 :            :         return ea;
    1347                 :            : }
    1348                 :            : 
    1349                 :            : /* Debug function to dump internal NIC action structure. */
    1350                 :            : static void
    1351                 :          0 : enic_dump_actions(const struct filter_action_v2 *ea)
    1352                 :            : {
    1353         [ #  # ]:          0 :         if (ea->type == FILTER_ACTION_RQ_STEERING) {
    1354                 :          0 :                 ENICPMD_LOG(INFO, "Action(V1), queue: %u", ea->rq_idx);
    1355         [ #  # ]:          0 :         } else if (ea->type == FILTER_ACTION_V2) {
    1356                 :          0 :                 ENICPMD_LOG(INFO, "Actions(V2)");
    1357         [ #  # ]:          0 :                 if (ea->flags & FILTER_ACTION_RQ_STEERING_FLAG)
    1358                 :          0 :                         ENICPMD_LOG(INFO, "\tqueue: %u",
    1359                 :            :                                enic_sop_rq_idx_to_rte_idx(ea->rq_idx));
    1360         [ #  # ]:          0 :                 if (ea->flags & FILTER_ACTION_FILTER_ID_FLAG)
    1361                 :          0 :                         ENICPMD_LOG(INFO, "\tfilter_id: %u", ea->filter_id);
    1362                 :            :         }
    1363                 :          0 : }
    1364                 :            : 
    1365                 :            : /* Debug function to dump internal NIC filter structure. */
    1366                 :            : static void
    1367                 :          0 : enic_dump_filter(const struct filter_v2 *filt)
    1368                 :            : {
    1369                 :            :         const struct filter_generic_1 *gp;
    1370                 :            :         int i, j, mbyte;
    1371                 :            :         char buf[128], *bp;
    1372                 :            :         char ip4[16], ip6[16], udp[16], tcp[16], tcpudp[16], ip4csum[16];
    1373                 :            :         char l4csum[16], ipfrag[16];
    1374                 :            : 
    1375      [ #  #  # ]:          0 :         switch (filt->type) {
    1376                 :          0 :         case FILTER_IPV4_5TUPLE:
    1377                 :          0 :                 ENICPMD_LOG(INFO, "FILTER_IPV4_5TUPLE");
    1378                 :          0 :                 break;
    1379                 :          0 :         case FILTER_USNIC_IP:
    1380                 :            :         case FILTER_DPDK_1:
    1381                 :            :                 /* FIXME: this should be a loop */
    1382                 :            :                 gp = &filt->u.generic_1;
    1383                 :          0 :                 ENICPMD_LOG(INFO, "Filter: vlan: 0x%04x, mask: 0x%04x",
    1384                 :            :                        gp->val_vlan, gp->mask_vlan);
    1385                 :            : 
    1386         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_IPV4)
    1387                 :          0 :                         sprintf(ip4, "%s ",
    1388         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_IPV4)
    1389                 :            :                                  ? "ip4(y)" : "ip4(n)");
    1390                 :            :                 else
    1391                 :            :                         sprintf(ip4, "%s ", "ip4(x)");
    1392                 :            : 
    1393         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_IPV6)
    1394                 :          0 :                         sprintf(ip6, "%s ",
    1395         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_IPV6)
    1396                 :            :                                  ? "ip6(y)" : "ip6(n)");
    1397                 :            :                 else
    1398                 :            :                         sprintf(ip6, "%s ", "ip6(x)");
    1399                 :            : 
    1400         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_UDP)
    1401                 :          0 :                         sprintf(udp, "%s ",
    1402         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_UDP)
    1403                 :            :                                  ? "udp(y)" : "udp(n)");
    1404                 :            :                 else
    1405                 :            :                         sprintf(udp, "%s ", "udp(x)");
    1406                 :            : 
    1407         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_TCP)
    1408                 :          0 :                         sprintf(tcp, "%s ",
    1409         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_TCP)
    1410                 :            :                                  ? "tcp(y)" : "tcp(n)");
    1411                 :            :                 else
    1412                 :            :                         sprintf(tcp, "%s ", "tcp(x)");
    1413                 :            : 
    1414         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_TCP_OR_UDP)
    1415                 :          0 :                         sprintf(tcpudp, "%s ",
    1416         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_TCP_OR_UDP)
    1417                 :            :                                  ? "tcpudp(y)" : "tcpudp(n)");
    1418                 :            :                 else
    1419                 :            :                         sprintf(tcpudp, "%s ", "tcpudp(x)");
    1420                 :            : 
    1421         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_IP4SUM_OK)
    1422                 :          0 :                         sprintf(ip4csum, "%s ",
    1423         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_IP4SUM_OK)
    1424                 :            :                                  ? "ip4csum(y)" : "ip4csum(n)");
    1425                 :            :                 else
    1426                 :            :                         sprintf(ip4csum, "%s ", "ip4csum(x)");
    1427                 :            : 
    1428         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_L4SUM_OK)
    1429                 :          0 :                         sprintf(l4csum, "%s ",
    1430         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_L4SUM_OK)
    1431                 :            :                                  ? "l4csum(y)" : "l4csum(n)");
    1432                 :            :                 else
    1433                 :            :                         sprintf(l4csum, "%s ", "l4csum(x)");
    1434                 :            : 
    1435         [ #  # ]:          0 :                 if (gp->mask_flags & FILTER_GENERIC_1_IPFRAG)
    1436                 :          0 :                         sprintf(ipfrag, "%s ",
    1437         [ #  # ]:          0 :                                 (gp->val_flags & FILTER_GENERIC_1_IPFRAG)
    1438                 :            :                                  ? "ipfrag(y)" : "ipfrag(n)");
    1439                 :            :                 else
    1440                 :            :                         sprintf(ipfrag, "%s ", "ipfrag(x)");
    1441                 :          0 :                 ENICPMD_LOG(INFO, "\tFlags: %s%s%s%s%s%s%s%s", ip4, ip6, udp,
    1442                 :            :                          tcp, tcpudp, ip4csum, l4csum, ipfrag);
    1443                 :            : 
    1444         [ #  # ]:          0 :                 for (i = 0; i < FILTER_GENERIC_1_NUM_LAYERS; i++) {
    1445                 :            :                         mbyte = FILTER_GENERIC_1_KEY_LEN - 1;
    1446   [ #  #  #  # ]:          0 :                         while (mbyte && !gp->layer[i].mask[mbyte])
    1447                 :          0 :                                 mbyte--;
    1448         [ #  # ]:          0 :                         if (mbyte == 0)
    1449                 :          0 :                                 continue;
    1450                 :            : 
    1451                 :            :                         bp = buf;
    1452         [ #  # ]:          0 :                         for (j = 0; j <= mbyte; j++) {
    1453                 :          0 :                                 sprintf(bp, "%02x",
    1454                 :          0 :                                         gp->layer[i].mask[j]);
    1455                 :          0 :                                 bp += 2;
    1456                 :            :                         }
    1457                 :          0 :                         *bp = '\0';
    1458                 :          0 :                         ENICPMD_LOG(INFO, "\tL%u mask: %s", i + 2, buf);
    1459                 :            :                         bp = buf;
    1460         [ #  # ]:          0 :                         for (j = 0; j <= mbyte; j++) {
    1461                 :          0 :                                 sprintf(bp, "%02x",
    1462                 :          0 :                                         gp->layer[i].val[j]);
    1463                 :          0 :                                 bp += 2;
    1464                 :            :                         }
    1465                 :          0 :                         *bp = '\0';
    1466                 :          0 :                         ENICPMD_LOG(INFO, "\tL%u  val: %s", i + 2, buf);
    1467                 :            :                 }
    1468                 :            :                 break;
    1469                 :          0 :         default:
    1470                 :          0 :                 ENICPMD_LOG(INFO, "FILTER UNKNOWN");
    1471                 :          0 :                 break;
    1472                 :            :         }
    1473                 :          0 : }
    1474                 :            : 
    1475                 :            : /* Debug function to dump internal NIC flow structures. */
    1476                 :            : static void
    1477                 :          0 : enic_dump_flow(const struct filter_action_v2 *ea, const struct filter_v2 *filt)
    1478                 :            : {
    1479                 :          0 :         enic_dump_filter(filt);
    1480                 :          0 :         enic_dump_actions(ea);
    1481                 :          0 : }
    1482                 :            : 
    1483                 :            : 
    1484                 :            : /**
    1485                 :            :  * Internal flow parse/validate function.
    1486                 :            :  *
    1487                 :            :  * @param dev[in]
    1488                 :            :  *   This device pointer.
    1489                 :            :  * @param pattern[in]
    1490                 :            :  * @param actions[in]
    1491                 :            :  * @param error[out]
    1492                 :            :  * @param enic_filter[out]
    1493                 :            :  *   Internal NIC filter structure pointer.
    1494                 :            :  * @param enic_action[out]
    1495                 :            :  *   Internal NIC action structure pointer.
    1496                 :            :  */
    1497                 :            : static int
    1498                 :          0 : enic_flow_parse(struct rte_eth_dev *dev,
    1499                 :            :                 const struct rte_flow_attr *attrs,
    1500                 :            :                 const struct rte_flow_item pattern[],
    1501                 :            :                 const struct rte_flow_action actions[],
    1502                 :            :                 struct rte_flow_error *error,
    1503                 :            :                 struct filter_v2 *enic_filter,
    1504                 :            :                 struct filter_action_v2 *enic_action)
    1505                 :            : {
    1506                 :            :         unsigned int ret = 0;
    1507                 :            :         struct enic *enic = pmd_priv(dev);
    1508                 :            :         const struct enic_filter_cap *enic_filter_cap;
    1509                 :            :         const struct enic_action_cap *enic_action_cap;
    1510                 :            :         const struct rte_flow_action *action;
    1511                 :            : 
    1512                 :          0 :         ENICPMD_FUNC_TRACE();
    1513                 :            : 
    1514                 :            :         memset(enic_filter, 0, sizeof(*enic_filter));
    1515                 :            :         memset(enic_action, 0, sizeof(*enic_action));
    1516                 :            : 
    1517         [ #  # ]:          0 :         if (!pattern) {
    1518                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
    1519                 :            :                                    NULL, "No pattern specified");
    1520                 :          0 :                 return -rte_errno;
    1521                 :            :         }
    1522                 :            : 
    1523         [ #  # ]:          0 :         if (!actions) {
    1524                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1525                 :            :                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM,
    1526                 :            :                                    NULL, "No action specified");
    1527                 :          0 :                 return -rte_errno;
    1528                 :            :         }
    1529                 :            : 
    1530         [ #  # ]:          0 :         if (attrs) {
    1531         [ #  # ]:          0 :                 if (attrs->group) {
    1532                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1533                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
    1534                 :            :                                            NULL,
    1535                 :            :                                            "priority groups are not supported");
    1536                 :          0 :                         return -rte_errno;
    1537         [ #  # ]:          0 :                 } else if (attrs->priority) {
    1538                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1539                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
    1540                 :            :                                            NULL,
    1541                 :            :                                            "priorities are not supported");
    1542                 :          0 :                         return -rte_errno;
    1543         [ #  # ]:          0 :                 } else if (attrs->egress) {
    1544                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1545                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
    1546                 :            :                                            NULL,
    1547                 :            :                                            "egress is not supported");
    1548                 :          0 :                         return -rte_errno;
    1549         [ #  # ]:          0 :                 } else if (attrs->transfer) {
    1550                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1551                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
    1552                 :            :                                            NULL,
    1553                 :            :                                            "transfer is not supported");
    1554                 :          0 :                         return -rte_errno;
    1555         [ #  # ]:          0 :                 } else if (!attrs->ingress) {
    1556                 :          0 :                         rte_flow_error_set(error, ENOTSUP,
    1557                 :            :                                            RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
    1558                 :            :                                            NULL,
    1559                 :            :                                            "only ingress is supported");
    1560                 :          0 :                         return -rte_errno;
    1561                 :            :                 }
    1562                 :            : 
    1563                 :            :         } else {
    1564                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1565                 :            :                                    RTE_FLOW_ERROR_TYPE_ATTR,
    1566                 :            :                                    NULL, "No attribute specified");
    1567                 :          0 :                 return -rte_errno;
    1568                 :            :         }
    1569                 :            : 
    1570                 :            :         /* Verify Actions. */
    1571                 :            :         enic_action_cap =  enic_get_action_cap(enic);
    1572         [ #  # ]:          0 :         for (action = &actions[0]; action->type != RTE_FLOW_ACTION_TYPE_END;
    1573                 :          0 :              action++) {
    1574         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
    1575                 :          0 :                         continue;
    1576         [ #  # ]:          0 :                 else if (!enic_match_action(action, enic_action_cap->actions))
    1577                 :            :                         break;
    1578                 :            :         }
    1579         [ #  # ]:          0 :         if (action->type != RTE_FLOW_ACTION_TYPE_END) {
    1580                 :          0 :                 rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_ACTION,
    1581                 :            :                                    action, "Invalid action.");
    1582                 :          0 :                 return -rte_errno;
    1583                 :            :         }
    1584                 :          0 :         ret = enic_action_cap->copy_fn(enic, actions, enic_action);
    1585         [ #  # ]:          0 :         if (ret) {
    1586                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
    1587                 :            :                            NULL, "Unsupported action.");
    1588                 :          0 :                 return -rte_errno;
    1589                 :            :         }
    1590                 :            : 
    1591                 :            :         /* Verify Flow items. If copying the filter from flow format to enic
    1592                 :            :          * format fails, the flow is not supported
    1593                 :            :          */
    1594                 :            :         enic_filter_cap =  enic_get_filter_cap(enic);
    1595                 :            :         if (enic_filter_cap == NULL) {
    1596                 :          0 :                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
    1597                 :            :                            NULL, "Flow API not available");
    1598                 :          0 :                 return -rte_errno;
    1599                 :            :         }
    1600                 :          0 :         enic_filter->type = enic->flow_filter_mode;
    1601         [ #  # ]:          0 :         if (enic->adv_filters)
    1602                 :          0 :                 enic_filter->type = FILTER_DPDK_1;
    1603                 :          0 :         ret = enic_copy_filter(pattern, enic_filter_cap, enic,
    1604                 :            :                                        enic_filter, error);
    1605                 :          0 :         return ret;
    1606                 :            : }
    1607                 :            : 
    1608                 :            : /**
    1609                 :            :  * Push filter/action to the NIC.
    1610                 :            :  *
    1611                 :            :  * @param enic[in]
    1612                 :            :  *   Device structure pointer.
    1613                 :            :  * @param enic_filter[in]
    1614                 :            :  *   Internal NIC filter structure pointer.
    1615                 :            :  * @param enic_action[in]
    1616                 :            :  *   Internal NIC action structure pointer.
    1617                 :            :  * @param error[out]
    1618                 :            :  */
    1619                 :            : static struct rte_flow *
    1620                 :          0 : enic_flow_add_filter(struct enic *enic, struct filter_v2 *enic_filter,
    1621                 :            :                    struct filter_action_v2 *enic_action,
    1622                 :            :                    struct rte_flow_error *error)
    1623                 :            : {
    1624                 :            :         struct rte_flow *flow;
    1625                 :            :         int err;
    1626                 :            :         uint16_t entry;
    1627                 :            : 
    1628                 :          0 :         ENICPMD_FUNC_TRACE();
    1629                 :            : 
    1630                 :          0 :         flow = rte_calloc(__func__, 1, sizeof(*flow), 0);
    1631         [ #  # ]:          0 :         if (!flow) {
    1632                 :          0 :                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
    1633                 :            :                                    NULL, "cannot allocate flow memory");
    1634                 :          0 :                 return NULL;
    1635                 :            :         }
    1636                 :            : 
    1637                 :            :         /* entry[in] is the queue id, entry[out] is the filter Id for delete */
    1638                 :          0 :         entry = enic_action->rq_idx;
    1639                 :          0 :         err = vnic_dev_classifier(enic->vdev, CLSF_ADD, &entry, enic_filter,
    1640                 :            :                                   enic_action);
    1641         [ #  # ]:          0 :         if (err) {
    1642                 :          0 :                 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE,
    1643                 :            :                                    NULL, "vnic_dev_classifier error");
    1644                 :          0 :                 rte_free(flow);
    1645                 :          0 :                 return NULL;
    1646                 :            :         }
    1647                 :            : 
    1648                 :          0 :         flow->enic_filter_id = entry;
    1649                 :          0 :         flow->enic_filter = *enic_filter;
    1650                 :          0 :         return flow;
    1651                 :            : }
    1652                 :            : 
    1653                 :            : /**
    1654                 :            :  * Remove filter/action from the NIC.
    1655                 :            :  *
    1656                 :            :  * @param enic[in]
    1657                 :            :  *   Device structure pointer.
    1658                 :            :  * @param filter_id[in]
    1659                 :            :  *   Id of NIC filter.
    1660                 :            :  * @param enic_action[in]
    1661                 :            :  *   Internal NIC action structure pointer.
    1662                 :            :  * @param error[out]
    1663                 :            :  */
    1664                 :            : static int
    1665                 :          0 : enic_flow_del_filter(struct enic *enic, struct rte_flow *flow,
    1666                 :            :                    struct rte_flow_error *error)
    1667                 :            : {
    1668                 :            :         uint16_t filter_id;
    1669                 :            :         int err;
    1670                 :            : 
    1671                 :          0 :         ENICPMD_FUNC_TRACE();
    1672                 :            : 
    1673                 :          0 :         filter_id = flow->enic_filter_id;
    1674                 :          0 :         err = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL, NULL);
    1675         [ #  # ]:          0 :         if (err) {
    1676                 :          0 :                 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE,
    1677                 :            :                                    NULL, "vnic_dev_classifier failed");
    1678                 :          0 :                 return -err;
    1679                 :            :         }
    1680                 :            :         return 0;
    1681                 :            : }
    1682                 :            : 
    1683                 :            : /*
    1684                 :            :  * The following functions are callbacks for Generic flow API.
    1685                 :            :  */
    1686                 :            : 
    1687                 :            : /**
    1688                 :            :  * Validate a flow supported by the NIC.
    1689                 :            :  *
    1690                 :            :  * @see rte_flow_validate()
    1691                 :            :  * @see rte_flow_ops
    1692                 :            :  */
    1693                 :            : static int
    1694                 :          0 : enic_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attrs,
    1695                 :            :                    const struct rte_flow_item pattern[],
    1696                 :            :                    const struct rte_flow_action actions[],
    1697                 :            :                    struct rte_flow_error *error)
    1698                 :            : {
    1699                 :            :         struct filter_v2 enic_filter;
    1700                 :            :         struct filter_action_v2 enic_action;
    1701                 :            :         int ret;
    1702                 :            : 
    1703                 :          0 :         ENICPMD_FUNC_TRACE();
    1704                 :            : 
    1705                 :          0 :         ret = enic_flow_parse(dev, attrs, pattern, actions, error,
    1706                 :            :                                &enic_filter, &enic_action);
    1707         [ #  # ]:          0 :         if (!ret)
    1708                 :          0 :                 enic_dump_flow(&enic_action, &enic_filter);
    1709                 :          0 :         return ret;
    1710                 :            : }
    1711                 :            : 
    1712                 :            : /**
    1713                 :            :  * Create a flow supported by the NIC.
    1714                 :            :  *
    1715                 :            :  * @see rte_flow_create()
    1716                 :            :  * @see rte_flow_ops
    1717                 :            :  */
    1718                 :            : static struct rte_flow *
    1719                 :          0 : enic_flow_create(struct rte_eth_dev *dev,
    1720                 :            :                  const struct rte_flow_attr *attrs,
    1721                 :            :                  const struct rte_flow_item pattern[],
    1722                 :            :                  const struct rte_flow_action actions[],
    1723                 :            :                  struct rte_flow_error *error)
    1724                 :            : {
    1725                 :            :         int ret;
    1726                 :            :         struct filter_v2 enic_filter;
    1727                 :            :         struct filter_action_v2 enic_action;
    1728                 :            :         struct rte_flow *flow;
    1729                 :            :         struct enic *enic = pmd_priv(dev);
    1730                 :            : 
    1731                 :          0 :         ENICPMD_FUNC_TRACE();
    1732                 :            : 
    1733                 :          0 :         ret = enic_flow_parse(dev, attrs, pattern, actions, error, &enic_filter,
    1734                 :            :                               &enic_action);
    1735         [ #  # ]:          0 :         if (ret < 0)
    1736                 :            :                 return NULL;
    1737                 :            : 
    1738                 :          0 :         flow = enic_flow_add_filter(enic, &enic_filter, &enic_action,
    1739                 :            :                                     error);
    1740         [ #  # ]:          0 :         if (flow)
    1741         [ #  # ]:          0 :                 LIST_INSERT_HEAD(&enic->flows, flow, next);
    1742                 :            : 
    1743                 :            :         return flow;
    1744                 :            : }
    1745                 :            : 
    1746                 :            : /**
    1747                 :            :  * Destroy a flow supported by the NIC.
    1748                 :            :  *
    1749                 :            :  * @see rte_flow_destroy()
    1750                 :            :  * @see rte_flow_ops
    1751                 :            :  */
    1752                 :            : static int
    1753                 :          0 : enic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
    1754                 :            :                   __rte_unused struct rte_flow_error *error)
    1755                 :            : {
    1756                 :            :         struct enic *enic = pmd_priv(dev);
    1757                 :            : 
    1758                 :          0 :         ENICPMD_FUNC_TRACE();
    1759                 :            : 
    1760                 :          0 :         enic_flow_del_filter(enic, flow, error);
    1761         [ #  # ]:          0 :         LIST_REMOVE(flow, next);
    1762                 :          0 :         rte_free(flow);
    1763                 :          0 :         return 0;
    1764                 :            : }
    1765                 :            : 
    1766                 :            : /**
    1767                 :            :  * Flush all flows on the device.
    1768                 :            :  *
    1769                 :            :  * @see rte_flow_flush()
    1770                 :            :  * @see rte_flow_ops
    1771                 :            :  */
    1772                 :            : static int
    1773                 :          0 : enic_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
    1774                 :            : {
    1775                 :            :         struct rte_flow *flow;
    1776                 :            :         struct enic *enic = pmd_priv(dev);
    1777                 :            : 
    1778                 :          0 :         ENICPMD_FUNC_TRACE();
    1779                 :            : 
    1780                 :            : 
    1781         [ #  # ]:          0 :         while (!LIST_EMPTY(&enic->flows)) {
    1782                 :            :                 flow = LIST_FIRST(&enic->flows);
    1783                 :          0 :                 enic_flow_del_filter(enic, flow, error);
    1784         [ #  # ]:          0 :                 LIST_REMOVE(flow, next);
    1785                 :          0 :                 rte_free(flow);
    1786                 :            :         }
    1787                 :          0 :         return 0;
    1788                 :            : }
    1789                 :            : 
    1790                 :            : /**
    1791                 :            :  * Flow callback registration.
    1792                 :            :  *
    1793                 :            :  * @see rte_flow_ops
    1794                 :            :  */
    1795                 :            : const struct rte_flow_ops enic_flow_ops = {
    1796                 :            :         .validate = enic_flow_validate,
    1797                 :            :         .create = enic_flow_create,
    1798                 :            :         .destroy = enic_flow_destroy,
    1799                 :            :         .flush = enic_flow_flush,
    1800                 :            : };

Generated by: LCOV version 1.14