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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Chelsio Communications.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : #include "base/common.h"
       6                 :            : #include "cxgbe_flow.h"
       7                 :            : 
       8                 :            : #define __CXGBE_FILL_FS(__v, __m, fs, elem, e) \
       9                 :            : do { \
      10                 :            :         if ((fs)->mask.elem && ((fs)->val.elem != (__v))) \
      11                 :            :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, \
      12                 :            :                                           NULL, "Redefined match item with" \
      13                 :            :                                           " different values found"); \
      14                 :            :         (fs)->val.elem = (__v); \
      15                 :            :         (fs)->mask.elem = (__m); \
      16                 :            : } while (0)
      17                 :            : 
      18                 :            : #define __CXGBE_FILL_FS_MEMCPY(__v, __m, fs, elem) \
      19                 :            : do { \
      20                 :            :         memcpy(&(fs)->val.elem, &(__v), sizeof(__v)); \
      21                 :            :         memcpy(&(fs)->mask.elem, &(__m), sizeof(__m)); \
      22                 :            : } while (0)
      23                 :            : 
      24                 :            : #define CXGBE_FILL_FS(v, m, elem) \
      25                 :            :         __CXGBE_FILL_FS(v, m, fs, elem, e)
      26                 :            : 
      27                 :            : #define CXGBE_FILL_FS_MEMCPY(v, m, elem) \
      28                 :            :         __CXGBE_FILL_FS_MEMCPY(v, m, fs, elem)
      29                 :            : 
      30                 :            : static int
      31                 :          0 : cxgbe_validate_item(const struct rte_flow_item *i, struct rte_flow_error *e)
      32                 :            : {
      33                 :            :         /* rte_flow specification does not allow it. */
      34   [ #  #  #  #  :          0 :         if (!i->spec && (i->mask ||  i->last))
                   #  # ]
      35                 :          0 :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
      36                 :            :                                    i, "last or mask given without spec");
      37                 :            :         /*
      38                 :            :          * We don't support it.
      39                 :            :          * Although, we can support values in last as 0's or last == spec.
      40                 :            :          * But this will not provide user with any additional functionality
      41                 :            :          * and will only increase the complexity for us.
      42                 :            :          */
      43         [ #  # ]:          0 :         if (i->last)
      44                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
      45                 :            :                                    i, "last is not supported by chelsio pmd");
      46                 :            :         return 0;
      47                 :            : }
      48                 :            : 
      49                 :            : /**
      50                 :            :  * Apart from the 4-tuple IPv4/IPv6 - TCP/UDP information,
      51                 :            :  * there's only 40-bits available to store match fields.
      52                 :            :  * So, to save space, optimize filter spec for some common
      53                 :            :  * known fields that hardware can parse against incoming
      54                 :            :  * packets automatically.
      55                 :            :  */
      56                 :            : static void
      57                 :          0 : cxgbe_tweak_filter_spec(struct adapter *adap,
      58                 :            :                         struct ch_filter_specification *fs)
      59                 :            : {
      60                 :            :         /* Save 16-bit ethertype field space, by setting corresponding
      61                 :            :          * 1-bit flags in the filter spec for common known ethertypes.
      62                 :            :          * When hardware sees these flags, it automatically infers and
      63                 :            :          * matches incoming packets against the corresponding ethertype.
      64                 :            :          */
      65         [ #  # ]:          0 :         if (fs->mask.ethtype == 0xffff) {
      66   [ #  #  #  #  :          0 :                 switch (fs->val.ethtype) {
                      # ]
      67                 :          0 :                 case RTE_ETHER_TYPE_IPV4:
      68         [ #  # ]:          0 :                         if (adap->params.tp.ethertype_shift < 0) {
      69                 :          0 :                                 fs->type = FILTER_TYPE_IPV4;
      70                 :          0 :                                 fs->val.ethtype = 0;
      71                 :          0 :                                 fs->mask.ethtype = 0;
      72                 :            :                         }
      73                 :            :                         break;
      74                 :          0 :                 case RTE_ETHER_TYPE_IPV6:
      75         [ #  # ]:          0 :                         if (adap->params.tp.ethertype_shift < 0) {
      76                 :          0 :                                 fs->type = FILTER_TYPE_IPV6;
      77                 :          0 :                                 fs->val.ethtype = 0;
      78                 :          0 :                                 fs->mask.ethtype = 0;
      79                 :            :                         }
      80                 :            :                         break;
      81                 :          0 :                 case RTE_ETHER_TYPE_VLAN:
      82         [ #  # ]:          0 :                         if (adap->params.tp.ethertype_shift < 0 &&
      83         [ #  # ]:          0 :                             adap->params.tp.vlan_shift >= 0) {
      84                 :          0 :                                 fs->val.ivlan_vld = 1;
      85                 :          0 :                                 fs->mask.ivlan_vld = 1;
      86                 :          0 :                                 fs->val.ethtype = 0;
      87                 :          0 :                                 fs->mask.ethtype = 0;
      88                 :            :                         }
      89                 :            :                         break;
      90                 :          0 :                 case RTE_ETHER_TYPE_QINQ:
      91         [ #  # ]:          0 :                         if (adap->params.tp.ethertype_shift < 0 &&
      92         [ #  # ]:          0 :                             adap->params.tp.vnic_shift >= 0) {
      93                 :          0 :                                 fs->val.ovlan_vld = 1;
      94                 :          0 :                                 fs->mask.ovlan_vld = 1;
      95                 :          0 :                                 fs->val.ethtype = 0;
      96                 :          0 :                                 fs->mask.ethtype = 0;
      97                 :            :                         }
      98                 :            :                         break;
      99                 :            :                 default:
     100                 :            :                         break;
     101                 :            :                 }
     102                 :            :         }
     103                 :          0 : }
     104                 :            : 
     105                 :            : static void
     106                 :          0 : cxgbe_fill_filter_region(struct adapter *adap,
     107                 :            :                          struct ch_filter_specification *fs)
     108                 :            : {
     109                 :            :         struct tp_params *tp = &adap->params.tp;
     110                 :          0 :         u64 hash_filter_mask = tp->hash_filter_mask;
     111                 :            :         u64 ntuple_mask = 0;
     112                 :            : 
     113         [ #  # ]:          0 :         fs->cap = 0;
     114                 :            : 
     115         [ #  # ]:          0 :         if (!is_hashfilter(adap))
     116                 :            :                 return;
     117                 :            : 
     118         [ #  # ]:          0 :         if (fs->type) {
     119                 :          0 :                 uint8_t biton[16] = {0xff, 0xff, 0xff, 0xff,
     120                 :            :                                      0xff, 0xff, 0xff, 0xff,
     121                 :            :                                      0xff, 0xff, 0xff, 0xff,
     122                 :            :                                      0xff, 0xff, 0xff, 0xff};
     123                 :          0 :                 uint8_t bitoff[16] = {0};
     124                 :            : 
     125         [ #  # ]:          0 :                 if (!memcmp(fs->val.lip, bitoff, sizeof(bitoff)) ||
     126         [ #  # ]:          0 :                     !memcmp(fs->val.fip, bitoff, sizeof(bitoff)) ||
     127         [ #  # ]:          0 :                     memcmp(fs->mask.lip, biton, sizeof(biton)) ||
     128         [ #  # ]:          0 :                     memcmp(fs->mask.fip, biton, sizeof(biton)))
     129                 :          0 :                         return;
     130                 :            :         } else {
     131                 :          0 :                 uint32_t biton  = 0xffffffff;
     132                 :          0 :                 uint32_t bitoff = 0x0U;
     133                 :            : 
     134         [ #  # ]:          0 :                 if (!memcmp(fs->val.lip, &bitoff, sizeof(bitoff)) ||
     135         [ #  # ]:          0 :                     !memcmp(fs->val.fip, &bitoff, sizeof(bitoff)) ||
     136         [ #  # ]:          0 :                     memcmp(fs->mask.lip, &biton, sizeof(biton)) ||
     137         [ #  # ]:          0 :                     memcmp(fs->mask.fip, &biton, sizeof(biton)))
     138                 :          0 :                         return;
     139                 :            :         }
     140                 :            : 
     141   [ #  #  #  # ]:          0 :         if (!fs->val.lport || fs->mask.lport != 0xffff)
     142                 :            :                 return;
     143   [ #  #  #  # ]:          0 :         if (!fs->val.fport || fs->mask.fport != 0xffff)
     144                 :            :                 return;
     145                 :            : 
     146         [ #  # ]:          0 :         if (tp->protocol_shift >= 0)
     147                 :          0 :                 ntuple_mask |= (u64)fs->mask.proto << tp->protocol_shift;
     148         [ #  # ]:          0 :         if (tp->ethertype_shift >= 0)
     149                 :          0 :                 ntuple_mask |= (u64)fs->mask.ethtype << tp->ethertype_shift;
     150         [ #  # ]:          0 :         if (tp->port_shift >= 0)
     151                 :          0 :                 ntuple_mask |= (u64)fs->mask.iport << tp->port_shift;
     152         [ #  # ]:          0 :         if (tp->macmatch_shift >= 0)
     153                 :          0 :                 ntuple_mask |= (u64)fs->mask.macidx << tp->macmatch_shift;
     154   [ #  #  #  # ]:          0 :         if (tp->vlan_shift >= 0 && fs->mask.ivlan_vld)
     155                 :          0 :                 ntuple_mask |= (u64)(F_FT_VLAN_VLD | fs->mask.ivlan) <<
     156                 :            :                                tp->vlan_shift;
     157         [ #  # ]:          0 :         if (tp->vnic_shift >= 0) {
     158         [ #  # ]:          0 :                 if (fs->mask.ovlan_vld)
     159                 :          0 :                         ntuple_mask |= (u64)(fs->val.ovlan_vld << 16 |
     160                 :          0 :                                              fs->mask.ovlan) << tp->vnic_shift;
     161         [ #  # ]:          0 :                 else if (fs->mask.pfvf_vld)
     162                 :          0 :                         ntuple_mask |= (u64)(fs->mask.pfvf_vld << 16 |
     163                 :          0 :                                              fs->mask.pf << 13 |
     164                 :          0 :                                              fs->mask.vf) << tp->vnic_shift;
     165                 :            :         }
     166         [ #  # ]:          0 :         if (tp->tos_shift >= 0)
     167                 :          0 :                 ntuple_mask |= (u64)fs->mask.tos << tp->tos_shift;
     168                 :            : 
     169         [ #  # ]:          0 :         if (ntuple_mask != hash_filter_mask)
     170                 :            :                 return;
     171                 :            : 
     172                 :          0 :         fs->cap = 1; /* use hash region */
     173                 :            : }
     174                 :            : 
     175                 :            : static int
     176                 :          0 : ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
     177                 :            :                      struct ch_filter_specification *fs,
     178                 :            :                      struct rte_flow_error *e)
     179                 :            : {
     180                 :          0 :         const struct rte_flow_item_eth *spec = item->spec;
     181                 :          0 :         const struct rte_flow_item_eth *umask = item->mask;
     182                 :            :         const struct rte_flow_item_eth *mask;
     183                 :            : 
     184                 :            :         /* If user has not given any mask, then use chelsio supported mask. */
     185         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_eth *)dmask;
     186                 :            : 
     187         [ #  # ]:          0 :         if (!spec)
     188                 :            :                 return 0;
     189                 :            : 
     190                 :            :         /* we don't support SRC_MAC filtering*/
     191   [ #  #  #  # ]:          0 :         if (!rte_is_zero_ether_addr(&spec->hdr.src_addr) ||
     192         [ #  # ]:          0 :             (umask && !rte_is_zero_ether_addr(&umask->hdr.src_addr)))
     193                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
     194                 :            :                                           item,
     195                 :            :                                           "src mac filtering not supported");
     196                 :            : 
     197   [ #  #  #  # ]:          0 :         if (!rte_is_zero_ether_addr(&spec->hdr.dst_addr) ||
     198         [ #  # ]:          0 :             (umask && !rte_is_zero_ether_addr(&umask->hdr.dst_addr))) {
     199   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(0, 0x1ff, macidx);
     200                 :          0 :                 CXGBE_FILL_FS_MEMCPY(spec->hdr.dst_addr.addr_bytes, mask->hdr.dst_addr.addr_bytes,
     201                 :            :                                      dmac);
     202                 :            :         }
     203                 :            : 
     204   [ #  #  #  #  :          0 :         if (spec->hdr.ether_type || (umask && umask->hdr.ether_type))
                   #  # ]
     205   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(spec->hdr.ether_type),
          #  #  #  #  #  
                      # ]
     206                 :            :                               be16_to_cpu(mask->hdr.ether_type), ethtype);
     207                 :            : 
     208                 :            :         return 0;
     209                 :            : }
     210                 :            : 
     211                 :            : static int
     212                 :          0 : ch_rte_parsetype_vlan(const void *dmask, const struct rte_flow_item *item,
     213                 :            :                       struct ch_filter_specification *fs,
     214                 :            :                       struct rte_flow_error *e)
     215                 :            : {
     216                 :          0 :         const struct rte_flow_item_vlan *spec = item->spec;
     217                 :          0 :         const struct rte_flow_item_vlan *umask = item->mask;
     218                 :            :         const struct rte_flow_item_vlan *mask;
     219                 :            : 
     220                 :            :         /* If user has not given any mask, then use chelsio supported mask. */
     221         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_vlan *)dmask;
     222                 :            : 
     223                 :            :         /* If ethertype is already set and is not VLAN (0x8100) or
     224                 :            :          * QINQ(0x88A8), then don't proceed further. Otherwise,
     225                 :            :          * reset the outer ethertype, so that it can be replaced by
     226                 :            :          * innermost ethertype. Note that hardware will automatically
     227                 :            :          * match against VLAN or QINQ packets, based on 'ivlan_vld' or
     228                 :            :          * 'ovlan_vld' bit set in Chelsio filter spec, respectively.
     229                 :            :          */
     230         [ #  # ]:          0 :         if (fs->mask.ethtype) {
     231         [ #  # ]:          0 :                 if (fs->val.ethtype != RTE_ETHER_TYPE_VLAN &&
     232                 :            :                     fs->val.ethtype != RTE_ETHER_TYPE_QINQ)
     233                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     234                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
     235                 :            :                                                   item,
     236                 :            :                                                   "Ethertype must be 0x8100 or 0x88a8");
     237                 :            :         }
     238                 :            : 
     239         [ #  # ]:          0 :         if (fs->val.ethtype == RTE_ETHER_TYPE_QINQ) {
     240   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(1, 1, ovlan_vld);
     241         [ #  # ]:          0 :                 if (spec) {
     242   [ #  #  #  #  :          0 :                         if (spec->hdr.vlan_tci || (umask && umask->hdr.vlan_tci))
                   #  # ]
     243   [ #  #  #  #  :          0 :                                 CXGBE_FILL_FS(be16_to_cpu(spec->hdr.vlan_tci),
          #  #  #  #  #  
                      # ]
     244                 :            :                                               be16_to_cpu(mask->hdr.vlan_tci), ovlan);
     245                 :          0 :                         fs->mask.ethtype = 0;
     246                 :          0 :                         fs->val.ethtype = 0;
     247                 :            :                 }
     248                 :            :         } else {
     249   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(1, 1, ivlan_vld);
     250         [ #  # ]:          0 :                 if (spec) {
     251   [ #  #  #  #  :          0 :                         if (spec->hdr.vlan_tci || (umask && umask->hdr.vlan_tci))
                   #  # ]
     252   [ #  #  #  #  :          0 :                                 CXGBE_FILL_FS(be16_to_cpu(spec->hdr.vlan_tci),
          #  #  #  #  #  
                      # ]
     253                 :            :                                               be16_to_cpu(mask->hdr.vlan_tci), ivlan);
     254                 :          0 :                         fs->mask.ethtype = 0;
     255                 :          0 :                         fs->val.ethtype = 0;
     256                 :            :                 }
     257                 :            :         }
     258                 :            : 
     259   [ #  #  #  #  :          0 :         if (spec && (spec->hdr.eth_proto || (umask && umask->hdr.eth_proto)))
             #  #  #  # ]
     260   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(spec->hdr.eth_proto),
          #  #  #  #  #  
                      # ]
     261                 :            :                               be16_to_cpu(mask->hdr.eth_proto), ethtype);
     262                 :            : 
     263                 :            :         return 0;
     264                 :            : }
     265                 :            : 
     266                 :            : static int
     267                 :          0 : ch_rte_parsetype_udp(const void *dmask, const struct rte_flow_item *item,
     268                 :            :                      struct ch_filter_specification *fs,
     269                 :            :                      struct rte_flow_error *e)
     270                 :            : {
     271                 :          0 :         const struct rte_flow_item_udp *val = item->spec;
     272                 :          0 :         const struct rte_flow_item_udp *umask = item->mask;
     273                 :            :         const struct rte_flow_item_udp *mask;
     274                 :            : 
     275         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_udp *)dmask;
     276                 :            : 
     277   [ #  #  #  # ]:          0 :         if (mask->hdr.dgram_len || mask->hdr.dgram_cksum)
     278                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
     279                 :            :                                           item,
     280                 :            :                                           "udp: only src/dst port supported");
     281                 :            : 
     282   [ #  #  #  # ]:          0 :         CXGBE_FILL_FS(IPPROTO_UDP, 0xff, proto);
     283         [ #  # ]:          0 :         if (!val)
     284                 :            :                 return 0;
     285                 :            : 
     286   [ #  #  #  #  :          0 :         if (val->hdr.src_port || (umask && umask->hdr.src_port))
                   #  # ]
     287   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(val->hdr.src_port),
          #  #  #  #  #  
                      # ]
     288                 :            :                               be16_to_cpu(mask->hdr.src_port), fport);
     289                 :            : 
     290   [ #  #  #  #  :          0 :         if (val->hdr.dst_port || (umask && umask->hdr.dst_port))
                   #  # ]
     291   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(val->hdr.dst_port),
          #  #  #  #  #  
                      # ]
     292                 :            :                               be16_to_cpu(mask->hdr.dst_port), lport);
     293                 :            : 
     294                 :            :         return 0;
     295                 :            : }
     296                 :            : 
     297                 :            : static int
     298                 :          0 : ch_rte_parsetype_tcp(const void *dmask, const struct rte_flow_item *item,
     299                 :            :                      struct ch_filter_specification *fs,
     300                 :            :                      struct rte_flow_error *e)
     301                 :            : {
     302                 :          0 :         const struct rte_flow_item_tcp *val = item->spec;
     303                 :          0 :         const struct rte_flow_item_tcp *umask = item->mask;
     304                 :            :         const struct rte_flow_item_tcp *mask;
     305                 :            : 
     306         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_tcp *)dmask;
     307                 :            : 
     308   [ #  #  #  #  :          0 :         if (mask->hdr.sent_seq || mask->hdr.recv_ack || mask->hdr.data_off ||
                   #  # ]
     309   [ #  #  #  #  :          0 :             mask->hdr.tcp_flags || mask->hdr.rx_win || mask->hdr.cksum ||
                   #  # ]
     310         [ #  # ]:          0 :             mask->hdr.tcp_urp)
     311                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
     312                 :            :                                           item,
     313                 :            :                                           "tcp: only src/dst port supported");
     314                 :            : 
     315   [ #  #  #  # ]:          0 :         CXGBE_FILL_FS(IPPROTO_TCP, 0xff, proto);
     316         [ #  # ]:          0 :         if (!val)
     317                 :            :                 return 0;
     318                 :            : 
     319   [ #  #  #  #  :          0 :         if (val->hdr.src_port || (umask && umask->hdr.src_port))
                   #  # ]
     320   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(val->hdr.src_port),
          #  #  #  #  #  
                      # ]
     321                 :            :                               be16_to_cpu(mask->hdr.src_port), fport);
     322                 :            : 
     323   [ #  #  #  #  :          0 :         if (val->hdr.dst_port || (umask && umask->hdr.dst_port))
                   #  # ]
     324   [ #  #  #  #  :          0 :                 CXGBE_FILL_FS(be16_to_cpu(val->hdr.dst_port),
          #  #  #  #  #  
                      # ]
     325                 :            :                               be16_to_cpu(mask->hdr.dst_port), lport);
     326                 :            : 
     327                 :            :         return 0;
     328                 :            : }
     329                 :            : 
     330                 :            : static int
     331                 :          0 : ch_rte_parsetype_ipv4(const void *dmask, const struct rte_flow_item *item,
     332                 :            :                       struct ch_filter_specification *fs,
     333                 :            :                       struct rte_flow_error *e)
     334                 :            : {
     335                 :          0 :         const struct rte_flow_item_ipv4 *val = item->spec;
     336                 :          0 :         const struct rte_flow_item_ipv4 *umask = item->mask;
     337                 :            :         const struct rte_flow_item_ipv4 *mask;
     338                 :            : 
     339         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_ipv4 *)dmask;
     340                 :            : 
     341         [ #  # ]:          0 :         if (mask->hdr.time_to_live)
     342                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
     343                 :            :                                           item, "ttl is not supported");
     344                 :            : 
     345         [ #  # ]:          0 :         if (fs->mask.ethtype &&
     346         [ #  # ]:          0 :             (fs->val.ethtype != RTE_ETHER_TYPE_IPV4))
     347                 :          0 :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     348                 :            :                                           item,
     349                 :            :                                           "Couldn't find IPv4 ethertype");
     350                 :          0 :         fs->type = FILTER_TYPE_IPV4;
     351         [ #  # ]:          0 :         if (!val)
     352                 :            :                 return 0; /* ipv4 wild card */
     353                 :            : 
     354   [ #  #  #  #  :          0 :         if (val->hdr.next_proto_id || (umask && umask->hdr.next_proto_id))
                   #  # ]
     355   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(val->hdr.next_proto_id, mask->hdr.next_proto_id,
     356                 :            :                               proto);
     357                 :            : 
     358   [ #  #  #  #  :          0 :         if (val->hdr.dst_addr || (umask && umask->hdr.dst_addr))
                   #  # ]
     359                 :          0 :                 CXGBE_FILL_FS_MEMCPY(val->hdr.dst_addr, mask->hdr.dst_addr,
     360                 :            :                                      lip);
     361                 :            : 
     362   [ #  #  #  #  :          0 :         if (val->hdr.src_addr || (umask && umask->hdr.src_addr))
                   #  # ]
     363                 :          0 :                 CXGBE_FILL_FS_MEMCPY(val->hdr.src_addr, mask->hdr.src_addr,
     364                 :            :                                      fip);
     365                 :            : 
     366   [ #  #  #  #  :          0 :         if (val->hdr.type_of_service || (umask && umask->hdr.type_of_service))
                   #  # ]
     367   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(val->hdr.type_of_service,
     368                 :            :                               mask->hdr.type_of_service, tos);
     369                 :            : 
     370                 :            :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :            : static int
     374                 :          0 : ch_rte_parsetype_ipv6(const void *dmask, const struct rte_flow_item *item,
     375                 :            :                       struct ch_filter_specification *fs,
     376                 :            :                       struct rte_flow_error *e)
     377                 :            : {
     378                 :          0 :         const struct rte_flow_item_ipv6 *val = item->spec;
     379                 :          0 :         const struct rte_flow_item_ipv6 *umask = item->mask;
     380                 :            :         const struct rte_flow_item_ipv6 *mask;
     381                 :            :         u32 vtc_flow, vtc_flow_mask;
     382                 :          0 :         u8 z[16] = { 0 };
     383                 :            : 
     384         [ #  # ]:          0 :         mask = umask ? umask : (const struct rte_flow_item_ipv6 *)dmask;
     385                 :            : 
     386         [ #  # ]:          0 :         vtc_flow_mask = be32_to_cpu(mask->hdr.vtc_flow);
     387                 :            : 
     388         [ #  # ]:          0 :         if (vtc_flow_mask & RTE_IPV6_HDR_FL_MASK ||
     389         [ #  # ]:          0 :             mask->hdr.payload_len || mask->hdr.hop_limits)
     390                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
     391                 :            :                                           item,
     392                 :            :                                           "flow/hop are not supported");
     393                 :            : 
     394         [ #  # ]:          0 :         if (fs->mask.ethtype &&
     395         [ #  # ]:          0 :             (fs->val.ethtype != RTE_ETHER_TYPE_IPV6))
     396                 :          0 :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     397                 :            :                                           item,
     398                 :            :                                           "Couldn't find IPv6 ethertype");
     399                 :          0 :         fs->type = FILTER_TYPE_IPV6;
     400         [ #  # ]:          0 :         if (!val)
     401                 :            :                 return 0; /* ipv6 wild card */
     402                 :            : 
     403   [ #  #  #  #  :          0 :         if (val->hdr.proto || (umask && umask->hdr.proto))
                   #  # ]
     404   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS(val->hdr.proto, mask->hdr.proto, proto);
     405                 :            : 
     406         [ #  # ]:          0 :         vtc_flow = be32_to_cpu(val->hdr.vtc_flow);
     407   [ #  #  #  #  :          0 :         if (val->hdr.vtc_flow || (umask && umask->hdr.vtc_flow))
                   #  # ]
     408   [ #  #  #  # ]:          0 :                 CXGBE_FILL_FS((vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
     409                 :            :                               RTE_IPV6_HDR_TC_SHIFT,
     410                 :            :                               (vtc_flow_mask & RTE_IPV6_HDR_TC_MASK) >>
     411                 :            :                               RTE_IPV6_HDR_TC_SHIFT,
     412                 :            :                               tos);
     413                 :            : 
     414   [ #  #  #  # ]:          0 :         if (memcmp(&val->hdr.dst_addr, z, sizeof(val->hdr.dst_addr)) ||
     415                 :          0 :             (umask &&
     416         [ #  # ]:          0 :              memcmp(&umask->hdr.dst_addr, z, sizeof(umask->hdr.dst_addr))))
     417                 :          0 :                 CXGBE_FILL_FS_MEMCPY(val->hdr.dst_addr, mask->hdr.dst_addr,
     418                 :            :                                      lip);
     419                 :            : 
     420   [ #  #  #  # ]:          0 :         if (memcmp(&val->hdr.src_addr, z, sizeof(val->hdr.src_addr)) ||
     421                 :          0 :             (umask &&
     422         [ #  # ]:          0 :              memcmp(&umask->hdr.src_addr, z, sizeof(umask->hdr.src_addr))))
     423                 :          0 :                 CXGBE_FILL_FS_MEMCPY(val->hdr.src_addr, mask->hdr.src_addr,
     424                 :            :                                      fip);
     425                 :            : 
     426                 :            :         return 0;
     427                 :            : }
     428                 :            : 
     429                 :            : static int
     430                 :          0 : cxgbe_rtef_parse_attr(struct rte_flow *flow, const struct rte_flow_attr *attr,
     431                 :            :                       struct rte_flow_error *e)
     432                 :            : {
     433         [ #  # ]:          0 :         if (attr->egress)
     434                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR,
     435                 :            :                                           attr, "attribute:<egress> is"
     436                 :            :                                           " not supported !");
     437         [ #  # ]:          0 :         if (attr->group > 0)
     438                 :          0 :                 return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR,
     439                 :            :                                           attr, "group parameter is"
     440                 :            :                                           " not supported.");
     441                 :            : 
     442         [ #  # ]:          0 :         flow->fidx = attr->priority ? attr->priority - 1 : FILTER_ID_MAX;
     443                 :            : 
     444                 :          0 :         return 0;
     445                 :            : }
     446                 :            : 
     447                 :            : static inline int check_rxq(struct rte_eth_dev *dev, uint16_t rxq)
     448                 :            : {
     449                 :            :         struct port_info *pi = ethdev2pinfo(dev);
     450                 :            : 
     451         [ #  # ]:          0 :         if (rxq > pi->n_rx_qsets)
     452                 :            :                 return -EINVAL;
     453                 :            :         return 0;
     454                 :            : }
     455                 :            : 
     456                 :          0 : static int cxgbe_validate_fidxondel(struct filter_entry *f, unsigned int fidx)
     457                 :            : {
     458         [ #  # ]:          0 :         struct adapter *adap = ethdev2adap(f->dev);
     459                 :          0 :         struct ch_filter_specification fs = f->fs;
     460                 :            :         u8 nentries;
     461                 :            : 
     462         [ #  # ]:          0 :         if (fidx >= adap->tids.nftids) {
     463                 :          0 :                 dev_err(adap, "invalid flow index %d.\n", fidx);
     464                 :          0 :                 return -EINVAL;
     465                 :            :         }
     466                 :            : 
     467                 :          0 :         nentries = cxgbe_filter_slots(adap, fs.type);
     468         [ #  # ]:          0 :         if (!cxgbe_is_filter_set(&adap->tids, fidx, nentries)) {
     469                 :          0 :                 dev_err(adap, "Already free fidx:%d f:%p\n", fidx, f);
     470                 :          0 :                 return -EINVAL;
     471                 :            :         }
     472                 :            : 
     473                 :            :         return 0;
     474                 :            : }
     475                 :            : 
     476                 :            : static int
     477                 :          0 : cxgbe_validate_fidxonadd(struct ch_filter_specification *fs,
     478                 :            :                          struct adapter *adap, unsigned int fidx)
     479                 :            : {
     480                 :            :         u8 nentries;
     481                 :            : 
     482                 :          0 :         nentries = cxgbe_filter_slots(adap, fs->type);
     483         [ #  # ]:          0 :         if (cxgbe_is_filter_set(&adap->tids, fidx, nentries)) {
     484                 :          0 :                 dev_err(adap, "filter index: %d is busy.\n", fidx);
     485                 :          0 :                 return -EBUSY;
     486                 :            :         }
     487                 :            : 
     488         [ #  # ]:          0 :         if (fidx >= adap->tids.nftids) {
     489                 :          0 :                 dev_err(adap, "filter index (%u) >= max(%u)\n",
     490                 :            :                         fidx, adap->tids.nftids);
     491                 :          0 :                 return -ERANGE;
     492                 :            :         }
     493                 :            : 
     494                 :            :         return 0;
     495                 :            : }
     496                 :            : 
     497                 :            : static int
     498                 :          0 : cxgbe_verify_fidx(struct rte_flow *flow, unsigned int fidx, uint8_t del)
     499                 :            : {
     500         [ #  # ]:          0 :         if (flow->fs.cap)
     501                 :            :                 return 0; /* Hash filters */
     502         [ #  # ]:          0 :         return del ? cxgbe_validate_fidxondel(flow->f, fidx) :
     503                 :          0 :                 cxgbe_validate_fidxonadd(&flow->fs,
     504                 :          0 :                                          ethdev2adap(flow->dev), fidx);
     505                 :            : }
     506                 :            : 
     507                 :          0 : static int cxgbe_get_fidx(struct rte_flow *flow, unsigned int *fidx)
     508                 :            : {
     509                 :            :         struct ch_filter_specification *fs = &flow->fs;
     510         [ #  # ]:          0 :         struct adapter *adap = ethdev2adap(flow->dev);
     511                 :            : 
     512                 :            :         /* For tcam get the next available slot, if default value specified */
     513         [ #  # ]:          0 :         if (flow->fidx == FILTER_ID_MAX) {
     514                 :            :                 u8 nentries;
     515                 :            :                 int idx;
     516                 :            : 
     517                 :          0 :                 nentries = cxgbe_filter_slots(adap, fs->type);
     518                 :          0 :                 idx = cxgbe_alloc_ftid(adap, nentries);
     519         [ #  # ]:          0 :                 if (idx < 0) {
     520                 :          0 :                         dev_err(adap, "unable to get a filter index in tcam\n");
     521                 :          0 :                         return -ENOMEM;
     522                 :            :                 }
     523                 :          0 :                 *fidx = (unsigned int)idx;
     524                 :            :         } else {
     525                 :          0 :                 *fidx = flow->fidx;
     526                 :            :         }
     527                 :            : 
     528                 :            :         return 0;
     529                 :            : }
     530                 :            : 
     531                 :            : static int
     532                 :            : cxgbe_get_flow_item_index(const struct rte_flow_item items[], u32 type)
     533                 :            : {
     534                 :            :         const struct rte_flow_item *i;
     535                 :            :         int j, index = -ENOENT;
     536                 :            : 
     537   [ #  #  #  #  :          0 :         for (i = items, j = 0; i->type != RTE_FLOW_ITEM_TYPE_END; i++, j++) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     538   [ #  #  #  #  :          0 :                 if (i->type == type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     539                 :            :                         index = j;
     540                 :            :                         break;
     541                 :            :                 }
     542                 :            :         }
     543                 :            : 
     544                 :            :         return index;
     545                 :            : }
     546                 :            : 
     547                 :            : static int
     548                 :          0 : ch_rte_parse_nat(uint8_t nmode, struct ch_filter_specification *fs)
     549                 :            : {
     550                 :            :         /* nmode:
     551                 :            :          * BIT_0 = [src_ip],   BIT_1 = [dst_ip]
     552                 :            :          * BIT_2 = [src_port], BIT_3 = [dst_port]
     553                 :            :          *
     554                 :            :          * Only below cases are supported as per our spec.
     555                 :            :          */
     556   [ #  #  #  #  :          0 :         switch (nmode) {
             #  #  #  #  
                      # ]
     557                 :          0 :         case 0:  /* 0000b */
     558                 :          0 :                 fs->nat_mode = NAT_MODE_NONE;
     559                 :          0 :                 break;
     560                 :          0 :         case 2:  /* 0010b */
     561                 :          0 :                 fs->nat_mode = NAT_MODE_DIP;
     562                 :          0 :                 break;
     563                 :          0 :         case 5:  /* 0101b */
     564                 :          0 :                 fs->nat_mode = NAT_MODE_SIP_SP;
     565                 :          0 :                 break;
     566                 :          0 :         case 7:  /* 0111b */
     567                 :          0 :                 fs->nat_mode = NAT_MODE_DIP_SIP_SP;
     568                 :          0 :                 break;
     569                 :          0 :         case 10: /* 1010b */
     570                 :          0 :                 fs->nat_mode = NAT_MODE_DIP_DP;
     571                 :          0 :                 break;
     572                 :          0 :         case 11: /* 1011b */
     573                 :          0 :                 fs->nat_mode = NAT_MODE_DIP_DP_SIP;
     574                 :          0 :                 break;
     575                 :          0 :         case 14: /* 1110b */
     576                 :          0 :                 fs->nat_mode = NAT_MODE_DIP_DP_SP;
     577                 :          0 :                 break;
     578                 :          0 :         case 15: /* 1111b */
     579                 :          0 :                 fs->nat_mode = NAT_MODE_ALL;
     580                 :          0 :                 break;
     581                 :            :         default:
     582                 :            :                 return -EINVAL;
     583                 :            :         }
     584                 :            : 
     585                 :            :         return 0;
     586                 :            : }
     587                 :            : 
     588                 :            : static int
     589                 :          0 : ch_rte_parse_atype_switch(const struct rte_flow_action *a,
     590                 :            :                           const struct rte_flow_item items[],
     591                 :            :                           uint8_t *nmode,
     592                 :            :                           struct ch_filter_specification *fs,
     593                 :            :                           struct rte_flow_error *e)
     594                 :            : {
     595                 :            :         const struct rte_flow_action_of_set_vlan_vid *vlanid;
     596                 :            :         const struct rte_flow_action_of_set_vlan_pcp *vlanpcp;
     597                 :            :         const struct rte_flow_action_of_push_vlan *pushvlan;
     598                 :            :         const struct rte_flow_action_set_ipv4 *ipv4;
     599                 :            :         const struct rte_flow_action_set_ipv6 *ipv6;
     600                 :            :         const struct rte_flow_action_set_tp *tp_port;
     601                 :            :         const struct rte_flow_action_set_mac *mac;
     602                 :            :         int item_index;
     603                 :            :         u16 tmp_vlan;
     604                 :            : 
     605   [ #  #  #  #  :          0 :         switch (a->type) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     606                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
     607                 :          0 :                 vlanid = (const struct rte_flow_action_of_set_vlan_vid *)
     608                 :            :                           a->conf;
     609                 :            :                 /* If explicitly asked to push a new VLAN header,
     610                 :            :                  * then don't set rewrite mode. Otherwise, the
     611                 :            :                  * incoming VLAN packets will get their VLAN fields
     612                 :            :                  * rewritten, instead of adding an additional outer
     613                 :            :                  * VLAN header.
     614                 :            :                  */
     615         [ #  # ]:          0 :                 if (fs->newvlan != VLAN_INSERT)
     616                 :          0 :                         fs->newvlan = VLAN_REWRITE;
     617                 :          0 :                 tmp_vlan = fs->vlan & 0xe000;
     618         [ #  # ]:          0 :                 fs->vlan = (be16_to_cpu(vlanid->vlan_vid) & 0xfff) | tmp_vlan;
     619                 :          0 :                 break;
     620                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
     621                 :          0 :                 vlanpcp = (const struct rte_flow_action_of_set_vlan_pcp *)
     622                 :            :                           a->conf;
     623                 :            :                 /* If explicitly asked to push a new VLAN header,
     624                 :            :                  * then don't set rewrite mode. Otherwise, the
     625                 :            :                  * incoming VLAN packets will get their VLAN fields
     626                 :            :                  * rewritten, instead of adding an additional outer
     627                 :            :                  * VLAN header.
     628                 :            :                  */
     629         [ #  # ]:          0 :                 if (fs->newvlan != VLAN_INSERT)
     630                 :          0 :                         fs->newvlan = VLAN_REWRITE;
     631                 :          0 :                 tmp_vlan = fs->vlan & 0xfff;
     632                 :          0 :                 fs->vlan = (vlanpcp->vlan_pcp << 13) | tmp_vlan;
     633                 :          0 :                 break;
     634                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
     635                 :          0 :                 pushvlan = (const struct rte_flow_action_of_push_vlan *)
     636                 :            :                             a->conf;
     637   [ #  #  #  # ]:          0 :                 if (be16_to_cpu(pushvlan->ethertype) != RTE_ETHER_TYPE_VLAN)
     638                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     639                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     640                 :            :                                                   "only ethertype 0x8100 "
     641                 :            :                                                   "supported for push vlan.");
     642                 :          0 :                 fs->newvlan = VLAN_INSERT;
     643                 :          0 :                 break;
     644                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
     645                 :          0 :                 fs->newvlan = VLAN_REMOVE;
     646                 :          0 :                 break;
     647                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
     648                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     649                 :            :                                                        RTE_FLOW_ITEM_TYPE_IPV4);
     650         [ #  # ]:          0 :                 if (item_index < 0)
     651                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     652                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     653                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_IPV4 "
     654                 :            :                                                   "found.");
     655                 :            : 
     656                 :          0 :                 ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
     657                 :          0 :                 memcpy(fs->nat_fip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
     658                 :          0 :                 *nmode |= 1 << 0;
     659                 :          0 :                 break;
     660                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
     661                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     662                 :            :                                                        RTE_FLOW_ITEM_TYPE_IPV4);
     663         [ #  # ]:          0 :                 if (item_index < 0)
     664                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     665                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     666                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_IPV4 "
     667                 :            :                                                   "found.");
     668                 :            : 
     669                 :          0 :                 ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
     670                 :          0 :                 memcpy(fs->nat_lip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
     671                 :          0 :                 *nmode |= 1 << 1;
     672                 :          0 :                 break;
     673                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
     674                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     675                 :            :                                                        RTE_FLOW_ITEM_TYPE_IPV6);
     676         [ #  # ]:          0 :                 if (item_index < 0)
     677                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     678                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     679                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_IPV6 "
     680                 :            :                                                   "found.");
     681                 :            : 
     682                 :          0 :                 ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
     683                 :          0 :                 memcpy(fs->nat_fip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
     684                 :          0 :                 *nmode |= 1 << 0;
     685                 :          0 :                 break;
     686                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
     687                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     688                 :            :                                                        RTE_FLOW_ITEM_TYPE_IPV6);
     689         [ #  # ]:          0 :                 if (item_index < 0)
     690                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     691                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     692                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_IPV6 "
     693                 :            :                                                   "found.");
     694                 :            : 
     695                 :          0 :                 ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
     696                 :          0 :                 memcpy(fs->nat_lip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
     697                 :          0 :                 *nmode |= 1 << 1;
     698                 :          0 :                 break;
     699                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
     700                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     701                 :            :                                                        RTE_FLOW_ITEM_TYPE_TCP);
     702         [ #  # ]:          0 :                 if (item_index < 0) {
     703                 :            :                         item_index =
     704                 :            :                                 cxgbe_get_flow_item_index(items,
     705                 :            :                                                 RTE_FLOW_ITEM_TYPE_UDP);
     706         [ #  # ]:          0 :                         if (item_index < 0)
     707                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     708                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
     709                 :            :                                                 "No RTE_FLOW_ITEM_TYPE_TCP or "
     710                 :            :                                                 "RTE_FLOW_ITEM_TYPE_UDP found");
     711                 :            :                 }
     712                 :            : 
     713                 :          0 :                 tp_port = (const struct rte_flow_action_set_tp *)a->conf;
     714         [ #  # ]:          0 :                 fs->nat_fport = be16_to_cpu(tp_port->port);
     715                 :          0 :                 *nmode |= 1 << 2;
     716                 :          0 :                 break;
     717                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
     718                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     719                 :            :                                                        RTE_FLOW_ITEM_TYPE_TCP);
     720         [ #  # ]:          0 :                 if (item_index < 0) {
     721                 :            :                         item_index =
     722                 :            :                                 cxgbe_get_flow_item_index(items,
     723                 :            :                                                 RTE_FLOW_ITEM_TYPE_UDP);
     724         [ #  # ]:          0 :                         if (item_index < 0)
     725                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     726                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
     727                 :            :                                                 "No RTE_FLOW_ITEM_TYPE_TCP or "
     728                 :            :                                                 "RTE_FLOW_ITEM_TYPE_UDP found");
     729                 :            :                 }
     730                 :            : 
     731                 :          0 :                 tp_port = (const struct rte_flow_action_set_tp *)a->conf;
     732         [ #  # ]:          0 :                 fs->nat_lport = be16_to_cpu(tp_port->port);
     733                 :          0 :                 *nmode |= 1 << 3;
     734                 :          0 :                 break;
     735                 :            :         case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
     736                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     737                 :            :                                                        RTE_FLOW_ITEM_TYPE_ETH);
     738         [ #  # ]:          0 :                 if (item_index < 0)
     739                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     740                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     741                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_ETH "
     742                 :            :                                                   "found");
     743                 :          0 :                 fs->swapmac = 1;
     744                 :          0 :                 break;
     745                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
     746                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     747                 :            :                                                        RTE_FLOW_ITEM_TYPE_ETH);
     748         [ #  # ]:          0 :                 if (item_index < 0)
     749                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     750                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     751                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_ETH "
     752                 :            :                                                   "found");
     753                 :          0 :                 mac = (const struct rte_flow_action_set_mac *)a->conf;
     754                 :            : 
     755                 :          0 :                 fs->newsmac = 1;
     756                 :          0 :                 memcpy(fs->smac, mac->mac_addr, sizeof(fs->smac));
     757                 :            :                 break;
     758                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
     759                 :            :                 item_index = cxgbe_get_flow_item_index(items,
     760                 :            :                                                        RTE_FLOW_ITEM_TYPE_ETH);
     761         [ #  # ]:          0 :                 if (item_index < 0)
     762                 :          0 :                         return rte_flow_error_set(e, EINVAL,
     763                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION, a,
     764                 :            :                                                   "No RTE_FLOW_ITEM_TYPE_ETH found");
     765                 :          0 :                 mac = (const struct rte_flow_action_set_mac *)a->conf;
     766                 :            : 
     767                 :          0 :                 fs->newdmac = 1;
     768                 :          0 :                 memcpy(fs->dmac, mac->mac_addr, sizeof(fs->dmac));
     769                 :            :                 break;
     770                 :          0 :         default:
     771                 :            :                 /* We are not supposed to come here */
     772                 :          0 :                 return rte_flow_error_set(e, EINVAL,
     773                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, a,
     774                 :            :                                           "Action not supported");
     775                 :            :         }
     776                 :            : 
     777                 :            :         return 0;
     778                 :            : }
     779                 :            : 
     780                 :            : static int
     781                 :          0 : cxgbe_rtef_parse_actions(struct rte_flow *flow,
     782                 :            :                          const struct rte_flow_item items[],
     783                 :            :                          const struct rte_flow_action action[],
     784                 :            :                          struct rte_flow_error *e)
     785                 :            : {
     786                 :          0 :         struct ch_filter_specification *fs = &flow->fs;
     787                 :          0 :         uint8_t nmode = 0, nat_ipv4 = 0, nat_ipv6 = 0;
     788                 :            :         uint8_t vlan_set_vid = 0, vlan_set_pcp = 0;
     789                 :            :         const struct rte_flow_action_queue *q;
     790                 :            :         const struct rte_flow_action *a;
     791                 :            :         char abit = 0;
     792                 :            :         int ret;
     793                 :            : 
     794         [ #  # ]:          0 :         for (a = action; a->type != RTE_FLOW_ACTION_TYPE_END; a++) {
     795   [ #  #  #  #  :          0 :                 switch (a->type) {
          #  #  #  #  #  
                      # ]
     796                 :          0 :                 case RTE_FLOW_ACTION_TYPE_VOID:
     797                 :          0 :                         continue;
     798                 :          0 :                 case RTE_FLOW_ACTION_TYPE_DROP:
     799         [ #  # ]:          0 :                         if (abit++)
     800                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     801                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
     802                 :            :                                                 "specify only 1 pass/drop");
     803                 :          0 :                         fs->action = FILTER_DROP;
     804                 :          0 :                         break;
     805                 :          0 :                 case RTE_FLOW_ACTION_TYPE_QUEUE:
     806                 :          0 :                         q = (const struct rte_flow_action_queue *)a->conf;
     807         [ #  # ]:          0 :                         if (!q)
     808                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     809                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, q,
     810                 :            :                                                 "specify rx queue index");
     811         [ #  # ]:          0 :                         if (check_rxq(flow->dev, q->index))
     812                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     813                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, q,
     814                 :            :                                                 "Invalid rx queue");
     815         [ #  # ]:          0 :                         if (abit++)
     816                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     817                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
     818                 :            :                                                 "specify only 1 pass/drop");
     819                 :          0 :                         fs->action = FILTER_PASS;
     820                 :          0 :                         fs->dirsteer = 1;
     821                 :          0 :                         fs->iq = q->index;
     822                 :          0 :                         break;
     823                 :          0 :                 case RTE_FLOW_ACTION_TYPE_COUNT:
     824                 :          0 :                         fs->hitcnts = 1;
     825                 :          0 :                         break;
     826                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
     827                 :          0 :                         vlan_set_vid++;
     828                 :          0 :                         goto action_switch;
     829                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
     830                 :          0 :                         vlan_set_pcp++;
     831                 :          0 :                         goto action_switch;
     832                 :          0 :                 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
     833                 :            :                 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
     834                 :            :                 case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
     835                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
     836                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
     837                 :          0 :                         nat_ipv4++;
     838                 :          0 :                         goto action_switch;
     839                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
     840                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
     841                 :          0 :                         nat_ipv6++;
     842                 :          0 :                         goto action_switch;
     843                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
     844                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
     845                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
     846                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
     847                 :          0 : action_switch:
     848                 :            :                         /* We allow multiple switch actions, but switch is
     849                 :            :                          * not compatible with either queue or drop
     850                 :            :                          */
     851   [ #  #  #  # ]:          0 :                         if (abit++ && fs->action != FILTER_SWITCH)
     852                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     853                 :            :                                                 RTE_FLOW_ERROR_TYPE_ACTION, a,
     854                 :            :                                                 "overlapping action specified");
     855         [ #  # ]:          0 :                         if (nat_ipv4 && nat_ipv6)
     856                 :          0 :                                 return rte_flow_error_set(e, EINVAL,
     857                 :            :                                         RTE_FLOW_ERROR_TYPE_ACTION, a,
     858                 :            :                                         "Can't have one address ipv4 and the"
     859                 :            :                                         " other ipv6");
     860                 :            : 
     861                 :          0 :                         ret = ch_rte_parse_atype_switch(a, items, &nmode, fs,
     862                 :            :                                                         e);
     863         [ #  # ]:          0 :                         if (ret)
     864                 :          0 :                                 return ret;
     865                 :          0 :                         fs->action = FILTER_SWITCH;
     866                 :          0 :                         break;
     867                 :          0 :                 default:
     868                 :            :                         /* Not supported action : return error */
     869                 :          0 :                         return rte_flow_error_set(e, ENOTSUP,
     870                 :            :                                                   RTE_FLOW_ERROR_TYPE_ACTION,
     871                 :            :                                                   a, "Action not supported");
     872                 :            :                 }
     873                 :            :         }
     874                 :            : 
     875   [ #  #  #  # ]:          0 :         if (fs->newvlan == VLAN_REWRITE && (!vlan_set_vid || !vlan_set_pcp))
     876                 :          0 :                 return rte_flow_error_set(e, EINVAL,
     877                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, a,
     878                 :            :                                           "Both OF_SET_VLAN_VID and "
     879                 :            :                                           "OF_SET_VLAN_PCP must be specified");
     880                 :            : 
     881         [ #  # ]:          0 :         if (ch_rte_parse_nat(nmode, fs))
     882                 :          0 :                 return rte_flow_error_set(e, EINVAL,
     883                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, a,
     884                 :            :                                           "invalid settings for swich action");
     885                 :            :         return 0;
     886                 :            : }
     887                 :            : 
     888                 :            : static struct chrte_fparse parseitem[] = {
     889                 :            :         [RTE_FLOW_ITEM_TYPE_ETH] = {
     890                 :            :                 .fptr  = ch_rte_parsetype_eth,
     891                 :            :                 .dmask = &(const struct rte_flow_item_eth){
     892                 :            :                         .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
     893                 :            :                         .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
     894                 :            :                         .hdr.ether_type = 0xffff,
     895                 :            :                 }
     896                 :            :         },
     897                 :            : 
     898                 :            :         [RTE_FLOW_ITEM_TYPE_VLAN] = {
     899                 :            :                 .fptr = ch_rte_parsetype_vlan,
     900                 :            :                 .dmask = &(const struct rte_flow_item_vlan){
     901                 :            :                         .hdr.vlan_tci = 0xffff,
     902                 :            :                         .hdr.eth_proto = 0xffff,
     903                 :            :                 }
     904                 :            :         },
     905                 :            : 
     906                 :            :         [RTE_FLOW_ITEM_TYPE_IPV4] = {
     907                 :            :                 .fptr  = ch_rte_parsetype_ipv4,
     908                 :            :                 .dmask = &(const struct rte_flow_item_ipv4) {
     909                 :            :                         .hdr = {
     910                 :            :                                 .src_addr = RTE_BE32(0xffffffff),
     911                 :            :                                 .dst_addr = RTE_BE32(0xffffffff),
     912                 :            :                                 .type_of_service = 0xff,
     913                 :            :                         },
     914                 :            :                 },
     915                 :            :         },
     916                 :            : 
     917                 :            :         [RTE_FLOW_ITEM_TYPE_IPV6] = {
     918                 :            :                 .fptr  = ch_rte_parsetype_ipv6,
     919                 :            :                 .dmask = &(const struct rte_flow_item_ipv6) {
     920                 :            :                         .hdr = {
     921                 :            :                                 .src_addr = RTE_IPV6_MASK_FULL,
     922                 :            :                                 .dst_addr = RTE_IPV6_MASK_FULL,
     923                 :            :                                 .vtc_flow = RTE_BE32(0xff000000),
     924                 :            :                         },
     925                 :            :                 },
     926                 :            :         },
     927                 :            : 
     928                 :            :         [RTE_FLOW_ITEM_TYPE_UDP] = {
     929                 :            :                 .fptr  = ch_rte_parsetype_udp,
     930                 :            :                 .dmask = &rte_flow_item_udp_mask,
     931                 :            :         },
     932                 :            : 
     933                 :            :         [RTE_FLOW_ITEM_TYPE_TCP] = {
     934                 :            :                 .fptr  = ch_rte_parsetype_tcp,
     935                 :            :                 .dmask = &rte_flow_item_tcp_mask,
     936                 :            :         },
     937                 :            : };
     938                 :            : 
     939                 :            : static int
     940                 :          0 : cxgbe_rtef_parse_items(struct rte_flow *flow,
     941                 :            :                        const struct rte_flow_item items[],
     942                 :            :                        struct rte_flow_error *e)
     943                 :            : {
     944                 :          0 :         struct adapter *adap = ethdev2adap(flow->dev);
     945                 :            :         const struct rte_flow_item *i;
     946                 :          0 :         char repeat[ARRAY_SIZE(parseitem)] = {0};
     947                 :            : 
     948         [ #  # ]:          0 :         for (i = items; i->type != RTE_FLOW_ITEM_TYPE_END; i++) {
     949                 :            :                 struct chrte_fparse *idx;
     950                 :            :                 int ret;
     951                 :            : 
     952         [ #  # ]:          0 :                 if (i->type >= ARRAY_SIZE(parseitem))
     953                 :          0 :                         return rte_flow_error_set(e, ENOTSUP,
     954                 :            :                                                   RTE_FLOW_ERROR_TYPE_ITEM,
     955                 :            :                                                   i, "Item not supported");
     956                 :            : 
     957         [ #  # ]:          0 :                 switch (i->type) {
     958                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VOID:
     959                 :          0 :                         continue;
     960                 :          0 :                 default:
     961                 :            :                         /* check if item is repeated */
     962   [ #  #  #  # ]:          0 :                         if (repeat[i->type] &&
     963                 :            :                             i->type != RTE_FLOW_ITEM_TYPE_VLAN)
     964                 :          0 :                                 return rte_flow_error_set(e, ENOTSUP,
     965                 :            :                                                 RTE_FLOW_ERROR_TYPE_ITEM, i,
     966                 :            :                                                 "parse items cannot be repeated(except void/vlan)");
     967                 :            : 
     968                 :          0 :                         repeat[i->type] = 1;
     969                 :            : 
     970                 :            :                         /* validate the item */
     971                 :          0 :                         ret = cxgbe_validate_item(i, e);
     972         [ #  # ]:          0 :                         if (ret)
     973                 :          0 :                                 return ret;
     974                 :            : 
     975                 :          0 :                         idx = &flow->item_parser[i->type];
     976   [ #  #  #  # ]:          0 :                         if (!idx || !idx->fptr) {
     977                 :          0 :                                 return rte_flow_error_set(e, ENOTSUP,
     978                 :            :                                                 RTE_FLOW_ERROR_TYPE_ITEM, i,
     979                 :            :                                                 "Item not supported");
     980                 :            :                         } else {
     981                 :          0 :                                 ret = idx->fptr(idx->dmask, i, &flow->fs, e);
     982         [ #  # ]:          0 :                                 if (ret)
     983                 :          0 :                                         return ret;
     984                 :            :                         }
     985                 :            :                 }
     986                 :            :         }
     987                 :            : 
     988                 :          0 :         cxgbe_tweak_filter_spec(adap, &flow->fs);
     989                 :          0 :         cxgbe_fill_filter_region(adap, &flow->fs);
     990                 :            : 
     991                 :          0 :         return 0;
     992                 :            : }
     993                 :            : 
     994                 :            : static int
     995                 :          0 : cxgbe_flow_parse(struct rte_flow *flow,
     996                 :            :                  const struct rte_flow_attr *attr,
     997                 :            :                  const struct rte_flow_item item[],
     998                 :            :                  const struct rte_flow_action action[],
     999                 :            :                  struct rte_flow_error *e)
    1000                 :            : {
    1001                 :            :         int ret;
    1002                 :            :         /* parse user request into ch_filter_specification */
    1003                 :          0 :         ret = cxgbe_rtef_parse_attr(flow, attr, e);
    1004         [ #  # ]:          0 :         if (ret)
    1005                 :            :                 return ret;
    1006                 :          0 :         ret = cxgbe_rtef_parse_items(flow, item, e);
    1007         [ #  # ]:          0 :         if (ret)
    1008                 :            :                 return ret;
    1009                 :          0 :         return cxgbe_rtef_parse_actions(flow, item, action, e);
    1010                 :            : }
    1011                 :            : 
    1012                 :          0 : static int __cxgbe_flow_create(struct rte_eth_dev *dev, struct rte_flow *flow)
    1013                 :            : {
    1014                 :          0 :         struct ch_filter_specification *fs = &flow->fs;
    1015                 :            :         struct adapter *adap = ethdev2adap(dev);
    1016                 :            :         struct tid_info *t = &adap->tids;
    1017                 :            :         struct filter_ctx ctx;
    1018                 :            :         unsigned int fidx;
    1019                 :            :         int err;
    1020                 :            : 
    1021         [ #  # ]:          0 :         if (cxgbe_get_fidx(flow, &fidx))
    1022                 :            :                 return -ENOMEM;
    1023         [ #  # ]:          0 :         if (cxgbe_verify_fidx(flow, fidx, 0))
    1024                 :            :                 return -1;
    1025                 :            : 
    1026                 :            :         t4_init_completion(&ctx.completion);
    1027                 :            :         /* go create the filter */
    1028                 :          0 :         err = cxgbe_set_filter(dev, fidx, fs, &ctx);
    1029         [ #  # ]:          0 :         if (err) {
    1030                 :          0 :                 dev_err(adap, "Error %d while creating filter.\n", err);
    1031                 :          0 :                 return err;
    1032                 :            :         }
    1033                 :            : 
    1034                 :            :         /* Poll the FW for reply */
    1035                 :          0 :         err = cxgbe_poll_for_completion(&adap->sge.fw_evtq,
    1036                 :            :                                         CXGBE_FLOW_POLL_MS,
    1037                 :            :                                         CXGBE_FLOW_POLL_CNT,
    1038                 :            :                                         &ctx.completion);
    1039         [ #  # ]:          0 :         if (err) {
    1040                 :          0 :                 dev_err(adap, "Filter set operation timed out (%d)\n", err);
    1041                 :          0 :                 return err;
    1042                 :            :         }
    1043         [ #  # ]:          0 :         if (ctx.result) {
    1044                 :          0 :                 dev_err(adap, "Hardware error %d while creating the filter.\n",
    1045                 :            :                         ctx.result);
    1046                 :          0 :                 return ctx.result;
    1047                 :            :         }
    1048                 :            : 
    1049         [ #  # ]:          0 :         if (fs->cap) { /* to destroy the filter */
    1050         [ #  # ]:          0 :                 flow->fidx = ctx.tid;
    1051                 :          0 :                 flow->f = lookup_tid(t, ctx.tid);
    1052                 :            :         } else {
    1053                 :          0 :                 flow->fidx = fidx;
    1054                 :          0 :                 flow->f = &adap->tids.ftid_tab[fidx];
    1055                 :            :         }
    1056                 :            : 
    1057                 :            :         return 0;
    1058                 :            : }
    1059                 :            : 
    1060                 :            : static struct rte_flow *
    1061                 :          0 : cxgbe_flow_create(struct rte_eth_dev *dev,
    1062                 :            :                   const struct rte_flow_attr *attr,
    1063                 :            :                   const struct rte_flow_item item[],
    1064                 :            :                   const struct rte_flow_action action[],
    1065                 :            :                   struct rte_flow_error *e)
    1066                 :            : {
    1067                 :            :         struct adapter *adap = ethdev2adap(dev);
    1068                 :            :         struct rte_flow *flow;
    1069                 :            :         int ret;
    1070                 :            : 
    1071                 :          0 :         flow = t4_os_alloc(sizeof(struct rte_flow));
    1072         [ #  # ]:          0 :         if (!flow) {
    1073                 :          0 :                 rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
    1074                 :            :                                    NULL, "Unable to allocate memory for"
    1075                 :            :                                    " filter_entry");
    1076                 :          0 :                 return NULL;
    1077                 :            :         }
    1078                 :            : 
    1079                 :          0 :         flow->item_parser = parseitem;
    1080                 :          0 :         flow->dev = dev;
    1081                 :          0 :         flow->fs.private = (void *)flow;
    1082                 :            : 
    1083         [ #  # ]:          0 :         if (cxgbe_flow_parse(flow, attr, item, action, e)) {
    1084                 :          0 :                 t4_os_free(flow);
    1085                 :          0 :                 return NULL;
    1086                 :            :         }
    1087                 :            : 
    1088                 :          0 :         t4_os_lock(&adap->flow_lock);
    1089                 :            :         /* go, interact with cxgbe_filter */
    1090                 :          0 :         ret = __cxgbe_flow_create(dev, flow);
    1091                 :            :         t4_os_unlock(&adap->flow_lock);
    1092         [ #  # ]:          0 :         if (ret) {
    1093                 :          0 :                 rte_flow_error_set(e, ret, RTE_FLOW_ERROR_TYPE_HANDLE,
    1094                 :            :                                    NULL, "Unable to create flow rule");
    1095                 :          0 :                 t4_os_free(flow);
    1096                 :          0 :                 return NULL;
    1097                 :            :         }
    1098                 :            : 
    1099                 :          0 :         flow->f->private = flow; /* Will be used during flush */
    1100                 :            : 
    1101                 :          0 :         return flow;
    1102                 :            : }
    1103                 :            : 
    1104                 :          0 : static int __cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
    1105                 :            : {
    1106                 :            :         struct adapter *adap = ethdev2adap(dev);
    1107                 :          0 :         struct filter_entry *f = flow->f;
    1108                 :            :         struct ch_filter_specification *fs;
    1109                 :            :         struct filter_ctx ctx;
    1110                 :            :         int err;
    1111                 :            : 
    1112                 :          0 :         fs = &f->fs;
    1113         [ #  # ]:          0 :         if (cxgbe_verify_fidx(flow, flow->fidx, 1))
    1114                 :            :                 return -1;
    1115                 :            : 
    1116                 :            :         t4_init_completion(&ctx.completion);
    1117                 :          0 :         err = cxgbe_del_filter(dev, flow->fidx, fs, &ctx);
    1118         [ #  # ]:          0 :         if (err) {
    1119                 :          0 :                 dev_err(adap, "Error %d while deleting filter.\n", err);
    1120                 :          0 :                 return err;
    1121                 :            :         }
    1122                 :            : 
    1123                 :            :         /* Poll the FW for reply */
    1124                 :          0 :         err = cxgbe_poll_for_completion(&adap->sge.fw_evtq,
    1125                 :            :                                         CXGBE_FLOW_POLL_MS,
    1126                 :            :                                         CXGBE_FLOW_POLL_CNT,
    1127                 :            :                                         &ctx.completion);
    1128         [ #  # ]:          0 :         if (err) {
    1129                 :          0 :                 dev_err(adap, "Filter delete operation timed out (%d)\n", err);
    1130                 :          0 :                 return err;
    1131                 :            :         }
    1132         [ #  # ]:          0 :         if (ctx.result) {
    1133                 :          0 :                 dev_err(adap, "Hardware error %d while deleting the filter.\n",
    1134                 :            :                         ctx.result);
    1135                 :          0 :                 return ctx.result;
    1136                 :            :         }
    1137                 :            : 
    1138                 :            :         return 0;
    1139                 :            : }
    1140                 :            : 
    1141                 :            : static int
    1142                 :          0 : cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
    1143                 :            :                    struct rte_flow_error *e)
    1144                 :            : {
    1145                 :            :         struct adapter *adap = ethdev2adap(dev);
    1146                 :            :         int ret;
    1147                 :            : 
    1148                 :          0 :         t4_os_lock(&adap->flow_lock);
    1149                 :          0 :         ret = __cxgbe_flow_destroy(dev, flow);
    1150                 :            :         t4_os_unlock(&adap->flow_lock);
    1151         [ #  # ]:          0 :         if (ret)
    1152                 :          0 :                 return rte_flow_error_set(e, ret, RTE_FLOW_ERROR_TYPE_HANDLE,
    1153                 :            :                                           flow, "error destroying filter.");
    1154                 :          0 :         t4_os_free(flow);
    1155                 :          0 :         return 0;
    1156                 :            : }
    1157                 :            : 
    1158                 :          0 : static int __cxgbe_flow_query(struct rte_flow *flow, u64 *count,
    1159                 :            :                               u64 *byte_count)
    1160                 :            : {
    1161                 :          0 :         struct adapter *adap = ethdev2adap(flow->dev);
    1162                 :          0 :         struct ch_filter_specification fs = flow->f->fs;
    1163                 :          0 :         unsigned int fidx = flow->fidx;
    1164                 :            :         int ret = 0;
    1165                 :            : 
    1166                 :          0 :         ret = cxgbe_get_filter_count(adap, fidx, count, fs.cap, 0);
    1167         [ #  # ]:          0 :         if (ret)
    1168                 :            :                 return ret;
    1169                 :          0 :         return cxgbe_get_filter_count(adap, fidx, byte_count, fs.cap, 1);
    1170                 :            : }
    1171                 :            : 
    1172                 :            : static int
    1173                 :          0 : cxgbe_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
    1174                 :            :                  const struct rte_flow_action *action, void *data,
    1175                 :            :                  struct rte_flow_error *e)
    1176                 :            : {
    1177         [ #  # ]:          0 :         struct adapter *adap = ethdev2adap(flow->dev);
    1178                 :            :         struct ch_filter_specification fs;
    1179                 :            :         struct rte_flow_query_count *c;
    1180                 :            :         struct filter_entry *f;
    1181                 :            :         int ret;
    1182                 :            : 
    1183                 :            :         RTE_SET_USED(dev);
    1184                 :            : 
    1185                 :          0 :         f = flow->f;
    1186                 :          0 :         fs = f->fs;
    1187                 :            : 
    1188         [ #  # ]:          0 :         if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
    1189                 :          0 :                 return rte_flow_error_set(e, ENOTSUP,
    1190                 :            :                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
    1191                 :            :                                           "only count supported for query");
    1192                 :            : 
    1193                 :            :         /*
    1194                 :            :          * This is a valid operation, Since we are allowed to do chelsio
    1195                 :            :          * specific operations in rte side of our code but not vise-versa
    1196                 :            :          *
    1197                 :            :          * So, fs can be queried/modified here BUT rte_flow_query_count
    1198                 :            :          * cannot be worked on by the lower layer since we want to maintain
    1199                 :            :          * it as rte_flow agnostic.
    1200                 :            :          */
    1201         [ #  # ]:          0 :         if (!fs.hitcnts)
    1202                 :          0 :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
    1203                 :            :                                           &fs, "filter hit counters were not"
    1204                 :            :                                           " enabled during filter creation");
    1205                 :            : 
    1206                 :            :         c = (struct rte_flow_query_count *)data;
    1207                 :            : 
    1208                 :          0 :         t4_os_lock(&adap->flow_lock);
    1209                 :          0 :         ret = __cxgbe_flow_query(flow, &c->hits, &c->bytes);
    1210         [ #  # ]:          0 :         if (ret) {
    1211                 :          0 :                 rte_flow_error_set(e, -ret, RTE_FLOW_ERROR_TYPE_ACTION,
    1212                 :            :                                    f, "cxgbe pmd failed to perform query");
    1213                 :          0 :                 goto out;
    1214                 :            :         }
    1215                 :            : 
    1216                 :            :         /* Query was successful */
    1217                 :          0 :         c->bytes_set = 1;
    1218                 :          0 :         c->hits_set = 1;
    1219         [ #  # ]:          0 :         if (c->reset)
    1220                 :          0 :                 cxgbe_clear_filter_count(adap, flow->fidx, f->fs.cap, true);
    1221                 :            : 
    1222                 :          0 : out:
    1223                 :            :         t4_os_unlock(&adap->flow_lock);
    1224                 :          0 :         return ret;
    1225                 :            : }
    1226                 :            : 
    1227                 :            : static int
    1228                 :          0 : cxgbe_flow_validate(struct rte_eth_dev *dev,
    1229                 :            :                     const struct rte_flow_attr *attr,
    1230                 :            :                     const struct rte_flow_item item[],
    1231                 :            :                     const struct rte_flow_action action[],
    1232                 :            :                     struct rte_flow_error *e)
    1233                 :            : {
    1234                 :            :         struct adapter *adap = ethdev2adap(dev);
    1235                 :            :         struct rte_flow *flow;
    1236                 :            :         unsigned int fidx;
    1237                 :            :         int ret = 0;
    1238                 :            : 
    1239                 :          0 :         flow = t4_os_alloc(sizeof(struct rte_flow));
    1240         [ #  # ]:          0 :         if (!flow)
    1241                 :          0 :                 return rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
    1242                 :            :                                 NULL,
    1243                 :            :                                 "Unable to allocate memory for filter_entry");
    1244                 :            : 
    1245                 :          0 :         flow->item_parser = parseitem;
    1246                 :          0 :         flow->dev = dev;
    1247                 :          0 :         flow->fs.private = (void *)flow;
    1248                 :            : 
    1249                 :          0 :         ret = cxgbe_flow_parse(flow, attr, item, action, e);
    1250         [ #  # ]:          0 :         if (ret) {
    1251                 :          0 :                 t4_os_free(flow);
    1252                 :          0 :                 return ret;
    1253                 :            :         }
    1254                 :            : 
    1255         [ #  # ]:          0 :         if (cxgbe_validate_filter(adap, &flow->fs)) {
    1256                 :          0 :                 t4_os_free(flow);
    1257                 :          0 :                 return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
    1258                 :            :                                 NULL,
    1259                 :            :                                 "validation failed. Check f/w config file.");
    1260                 :            :         }
    1261                 :            : 
    1262                 :          0 :         t4_os_lock(&adap->flow_lock);
    1263         [ #  # ]:          0 :         if (cxgbe_get_fidx(flow, &fidx)) {
    1264                 :          0 :                 ret = rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
    1265                 :            :                                          NULL, "no memory in tcam.");
    1266                 :          0 :                 goto out;
    1267                 :            :         }
    1268                 :            : 
    1269         [ #  # ]:          0 :         if (cxgbe_verify_fidx(flow, fidx, 0)) {
    1270                 :          0 :                 ret = rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
    1271                 :            :                                          NULL, "validation failed");
    1272                 :          0 :                 goto out;
    1273                 :            :         }
    1274                 :            : 
    1275                 :          0 : out:
    1276                 :            :         t4_os_unlock(&adap->flow_lock);
    1277                 :          0 :         t4_os_free(flow);
    1278                 :          0 :         return ret;
    1279                 :            : }
    1280                 :            : 
    1281                 :            : /*
    1282                 :            :  * @ret : > 0 filter destroyed successfully
    1283                 :            :  *        < 0 error destroying filter
    1284                 :            :  *        == 1 filter not active / not found
    1285                 :            :  */
    1286                 :            : static int
    1287                 :          0 : cxgbe_check_n_destroy(struct filter_entry *f, struct rte_eth_dev *dev)
    1288                 :            : {
    1289   [ #  #  #  # ]:          0 :         if (f && (f->valid || f->pending) &&
    1290         [ #  # ]:          0 :             f->dev == dev && /* Only if user has asked for this port */
    1291         [ #  # ]:          0 :              f->private) /* We (rte_flow) created this filter */
    1292                 :          0 :                 return __cxgbe_flow_destroy(dev, (struct rte_flow *)f->private);
    1293                 :            :         return 1;
    1294                 :            : }
    1295                 :            : 
    1296                 :          0 : static int cxgbe_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *e)
    1297                 :            : {
    1298                 :            :         struct adapter *adap = ethdev2adap(dev);
    1299                 :            :         unsigned int i;
    1300                 :            :         int ret = 0;
    1301                 :            : 
    1302                 :          0 :         t4_os_lock(&adap->flow_lock);
    1303         [ #  # ]:          0 :         if (adap->tids.ftid_tab) {
    1304                 :            :                 struct filter_entry *f = &adap->tids.ftid_tab[0];
    1305                 :            : 
    1306         [ #  # ]:          0 :                 for (i = 0; i < adap->tids.nftids; i++, f++) {
    1307                 :          0 :                         ret = cxgbe_check_n_destroy(f, dev);
    1308         [ #  # ]:          0 :                         if (ret < 0) {
    1309                 :          0 :                                 rte_flow_error_set(e, ret,
    1310                 :            :                                                    RTE_FLOW_ERROR_TYPE_HANDLE,
    1311                 :          0 :                                                    f->private,
    1312                 :            :                                                    "error destroying TCAM "
    1313                 :            :                                                    "filter.");
    1314                 :          0 :                                 goto out;
    1315                 :            :                         }
    1316                 :            :                 }
    1317                 :            :         }
    1318                 :            : 
    1319   [ #  #  #  # ]:          0 :         if (is_hashfilter(adap) && adap->tids.tid_tab) {
    1320                 :            :                 struct filter_entry *f;
    1321                 :            : 
    1322         [ #  # ]:          0 :                 for (i = adap->tids.hash_base; i <= adap->tids.ntids; i++) {
    1323                 :          0 :                         f = (struct filter_entry *)adap->tids.tid_tab[i];
    1324                 :            : 
    1325                 :          0 :                         ret = cxgbe_check_n_destroy(f, dev);
    1326         [ #  # ]:          0 :                         if (ret < 0) {
    1327                 :          0 :                                 rte_flow_error_set(e, ret,
    1328                 :            :                                                    RTE_FLOW_ERROR_TYPE_HANDLE,
    1329                 :          0 :                                                    f->private,
    1330                 :            :                                                    "error destroying HASH "
    1331                 :            :                                                    "filter.");
    1332                 :          0 :                                 goto out;
    1333                 :            :                         }
    1334                 :            :                 }
    1335                 :            :         }
    1336                 :            : 
    1337                 :          0 : out:
    1338                 :            :         t4_os_unlock(&adap->flow_lock);
    1339                 :          0 :         return ret >= 0 ? 0 : ret;
    1340                 :            : }
    1341                 :            : 
    1342                 :            : static const struct rte_flow_ops cxgbe_flow_ops = {
    1343                 :            :         .validate       = cxgbe_flow_validate,
    1344                 :            :         .create         = cxgbe_flow_create,
    1345                 :            :         .destroy        = cxgbe_flow_destroy,
    1346                 :            :         .flush          = cxgbe_flow_flush,
    1347                 :            :         .query          = cxgbe_flow_query,
    1348                 :            :         .isolate        = NULL,
    1349                 :            : };
    1350                 :            : 
    1351                 :            : int
    1352                 :          0 : cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
    1353                 :            :                        const struct rte_flow_ops **ops)
    1354                 :            : {
    1355                 :          0 :         *ops = &cxgbe_flow_ops;
    1356                 :          0 :         return 0;
    1357                 :            : }

Generated by: LCOV version 1.14