LCOV - code coverage report
Current view: top level - drivers/net/hinic3 - hinic3_flow.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 516 0.0 %
Date: 2025-11-01 17:50:34 Functions: 0 27 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 413 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2025 Huawei Technologies Co., Ltd
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_flow_driver.h>
       6                 :            : 
       7                 :            : #include "base/hinic3_compat.h"
       8                 :            : #include "base/hinic3_hwdev.h"
       9                 :            : #include "base/hinic3_nic_cfg.h"
      10                 :            : #include "hinic3_ethdev.h"
      11                 :            : #include "hinic3_flow.h"
      12                 :            : 
      13                 :            : #define HINIC3_UINT8_MAX 0xff
      14                 :            : 
      15                 :            : typedef int (*hinic3_parse_filter_t)(struct rte_eth_dev *dev,
      16                 :            :                                      const struct rte_flow_attr *attr,
      17                 :            :                                      const struct rte_flow_item pattern[],
      18                 :            :                                      const struct rte_flow_action actions[],
      19                 :            :                                      struct rte_flow_error *error,
      20                 :            :                                      struct hinic3_filter_t *filter);
      21                 :            : 
      22                 :            : /* Indicate valid filter mode . */
      23                 :            : struct hinic3_valid_pattern {
      24                 :            :         enum rte_flow_item_type *items;
      25                 :            :         hinic3_parse_filter_t parse_filter;
      26                 :            : };
      27                 :            : 
      28                 :            : static int hinic3_flow_parse_fdir_filter(struct rte_eth_dev *dev,
      29                 :            :                                          const struct rte_flow_attr *attr,
      30                 :            :                                          const struct rte_flow_item pattern[],
      31                 :            :                                          const struct rte_flow_action actions[],
      32                 :            :                                          struct rte_flow_error *error,
      33                 :            :                                          struct hinic3_filter_t *filter);
      34                 :            : 
      35                 :            : static int hinic3_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
      36                 :            :                                               const struct rte_flow_attr *attr,
      37                 :            :                                               const struct rte_flow_item pattern[],
      38                 :            :                                               const struct rte_flow_action actions[],
      39                 :            :                                               struct rte_flow_error *error,
      40                 :            :                                               struct hinic3_filter_t *filter);
      41                 :            : 
      42                 :            : static int hinic3_flow_parse_fdir_vxlan_filter(struct rte_eth_dev *dev,
      43                 :            :                                                const struct rte_flow_attr *attr,
      44                 :            :                                                const struct rte_flow_item pattern[],
      45                 :            :                                                const struct rte_flow_action actions[],
      46                 :            :                                                struct rte_flow_error *error,
      47                 :            :                                                struct hinic3_filter_t *filter);
      48                 :            : 
      49                 :            : /*
      50                 :            :  * Define a supported pattern array, including the matching patterns of
      51                 :            :  * various network protocols and corresponding parsing functions.
      52                 :            :  */
      53                 :            : static const struct hinic3_valid_pattern hinic3_supported_patterns[] = {
      54                 :            :         /* Support ethertype. */
      55                 :            :         {pattern_ethertype, hinic3_flow_parse_ethertype_filter},
      56                 :            :         /* Support ipv4 but not tunnel, and any field can be masked. */
      57                 :            :         {pattern_ipv4, hinic3_flow_parse_fdir_filter},
      58                 :            :         {pattern_ipv4_any, hinic3_flow_parse_fdir_filter},
      59                 :            :         /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
      60                 :            :         {pattern_ipv4_udp, hinic3_flow_parse_fdir_filter},
      61                 :            :         {pattern_ipv4_tcp, hinic3_flow_parse_fdir_filter},
      62                 :            :         /* Support ipv4 + icmp not tunnel, and any field can be masked. */
      63                 :            :         {pattern_ipv4_icmp, hinic3_flow_parse_fdir_filter},
      64                 :            : 
      65                 :            :         /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
      66                 :            :         {pattern_ethertype_udp, hinic3_flow_parse_fdir_filter},
      67                 :            :         {pattern_ethertype_tcp, hinic3_flow_parse_fdir_filter},
      68                 :            : 
      69                 :            :         /* Support ipv4 + vxlan + any, and any field can be masked. */
      70                 :            :         {pattern_ipv4_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
      71                 :            :         /* Support ipv4 + vxlan + ipv4, and any field can be masked. */
      72                 :            :         {pattern_ipv4_vxlan_ipv4, hinic3_flow_parse_fdir_vxlan_filter},
      73                 :            :         /* Support ipv4 + vxlan + ipv4 + l4, and any field can be masked. */
      74                 :            :         {pattern_ipv4_vxlan_ipv4_tcp, hinic3_flow_parse_fdir_vxlan_filter},
      75                 :            :         {pattern_ipv4_vxlan_ipv4_udp, hinic3_flow_parse_fdir_vxlan_filter},
      76                 :            :         /* Support ipv4 + vxlan + ipv6, and any field can be masked. */
      77                 :            :         {pattern_ipv4_vxlan_ipv6, hinic3_flow_parse_fdir_vxlan_filter},
      78                 :            :         /* Support ipv4 + vxlan + ipv6 + l4, and any field can be masked. */
      79                 :            :         {pattern_ipv4_vxlan_ipv6_tcp, hinic3_flow_parse_fdir_vxlan_filter},
      80                 :            :         {pattern_ipv4_vxlan_ipv6_udp, hinic3_flow_parse_fdir_vxlan_filter},
      81                 :            :         /* Support ipv4 + vxlan + l4, and any field can be masked. */
      82                 :            :         {pattern_ipv4_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
      83                 :            :         {pattern_ipv4_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
      84                 :            :         {pattern_ipv4_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
      85                 :            : 
      86                 :            :         /* Support ipv6 but not tunnel, and any field can be masked. */
      87                 :            :         {pattern_ipv6, hinic3_flow_parse_fdir_filter},
      88                 :            :         /* Support ipv6 + l4 but not tunnel, and any field can be masked. */
      89                 :            :         {pattern_ipv6_udp, hinic3_flow_parse_fdir_filter},
      90                 :            :         {pattern_ipv6_tcp, hinic3_flow_parse_fdir_filter},
      91                 :            : 
      92                 :            :         /* Support ipv6 + vxlan + any, and any field can be masked. */
      93                 :            :         {pattern_ipv6_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
      94                 :            :         {pattern_ipv6_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
      95                 :            : 
      96                 :            :         /* Support ipv6 + vxlan + l4, and any field can be masked. */
      97                 :            :         {pattern_ipv6_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
      98                 :            :         {pattern_ipv6_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
      99                 :            : 
     100                 :            : };
     101                 :            : 
     102                 :            : static inline void
     103                 :            : net_addr_to_host(uint32_t *dst, const uint32_t *src, size_t len)
     104                 :            : {
     105                 :            :         size_t i;
     106   [ #  #  #  #  :          0 :         for (i = 0; i < len; i++)
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     107   [ #  #  #  #  :          0 :                 dst[i] = rte_be_to_cpu_32(src[i]);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     108                 :            : }
     109                 :            : 
     110                 :            : static bool
     111                 :          0 : hinic3_match_pattern(enum rte_flow_item_type *item_array,
     112                 :            :                      const struct rte_flow_item *pattern)
     113                 :            : {
     114                 :            :         const struct rte_flow_item *item = pattern;
     115                 :            : 
     116                 :            :         /* skip the first void item. */
     117         [ #  # ]:          0 :         while (item->type == RTE_FLOW_ITEM_TYPE_VOID)
     118                 :          0 :                 item++;
     119                 :            : 
     120                 :            :         /* Find no void item. */
     121         [ #  # ]:          0 :         while (((*item_array == item->type) &&
     122   [ #  #  #  # ]:          0 :                 (*item_array != RTE_FLOW_ITEM_TYPE_END)) ||
     123                 :            :                (item->type == RTE_FLOW_ITEM_TYPE_VOID)) {
     124         [ #  # ]:          0 :                 if (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
     125                 :          0 :                         item++;
     126                 :            :                 } else {
     127                 :          0 :                         item_array++;
     128                 :          0 :                         item++;
     129                 :            :                 }
     130                 :            :         }
     131                 :            : 
     132   [ #  #  #  # ]:          0 :         return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
     133                 :            :                 item->type == RTE_FLOW_ITEM_TYPE_END);
     134                 :            : }
     135                 :            : 
     136                 :            : /**
     137                 :            :  * Find matching parsing filter functions.
     138                 :            :  *
     139                 :            :  * @param[in] pattern
     140                 :            :  * Pattern to match.
     141                 :            :  * @return
     142                 :            :  * Matched resolution filter. If no resolution filter is found, return NULL.
     143                 :            :  */
     144                 :            : static hinic3_parse_filter_t
     145                 :          0 : hinic3_find_parse_filter_func(const struct rte_flow_item *pattern)
     146                 :            : {
     147                 :            :         hinic3_parse_filter_t parse_filter = NULL;
     148                 :            :         uint8_t i;
     149                 :            :         /* Traverse all supported patterns. */
     150         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(hinic3_supported_patterns); i++) {
     151         [ #  # ]:          0 :                 if (hinic3_match_pattern(hinic3_supported_patterns[i].items, pattern)) {
     152                 :          0 :                         parse_filter =
     153                 :            :                                 hinic3_supported_patterns[i].parse_filter;
     154                 :          0 :                         break;
     155                 :            :                 }
     156                 :            :         }
     157                 :            : 
     158                 :          0 :         return parse_filter;
     159                 :            : }
     160                 :            : 
     161                 :            : /**
     162                 :            :  * Action for parsing and processing Ethernet types.
     163                 :            :  *
     164                 :            :  * @param[in] dev
     165                 :            :  * Pointer to ethernet device structure.
     166                 :            :  * @param[in] actions
     167                 :            :  * Indicates the action to be taken on the matched traffic.
     168                 :            :  * @param[out] error
     169                 :            :  * Structure that contains error information, such as error code and error
     170                 :            :  * description.
     171                 :            :  * @param[out] filter
     172                 :            :  * Filter information, its used to store and manipulate packet filtering rules.
     173                 :            :  * @return
     174                 :            :  * 0 on success, non-zero on failure.
     175                 :            :  */
     176                 :            : static int
     177                 :          0 : hinic3_flow_parse_action(struct rte_eth_dev *dev,
     178                 :            :                          const struct rte_flow_action *actions,
     179                 :            :                          struct rte_flow_error *error,
     180                 :            :                          struct hinic3_filter_t *filter)
     181                 :            : {
     182                 :            :         const struct rte_flow_action_queue *act_q;
     183                 :            :         const struct rte_flow_action *act = actions;
     184                 :            : 
     185                 :            :         /* skip the first void item. */
     186         [ #  # ]:          0 :         while (act->type == RTE_FLOW_ACTION_TYPE_VOID)
     187                 :          0 :                 act++;
     188                 :            : 
     189         [ #  # ]:          0 :         switch (act->type) {
     190                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUEUE:
     191                 :          0 :                 act_q = (const struct rte_flow_action_queue *)act->conf;
     192                 :          0 :                 filter->fdir_filter.rq_index = act_q->index;
     193         [ #  # ]:          0 :                 if (filter->fdir_filter.rq_index >= dev->data->nb_rx_queues) {
     194                 :          0 :                         rte_flow_error_set(error, EINVAL,
     195                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, act,
     196                 :            :                                            "Invalid action param.");
     197                 :          0 :                         return -rte_errno;
     198                 :            :                 }
     199                 :            :                 break;
     200                 :          0 :         default:
     201                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
     202                 :            :                                    act, "Invalid action type.");
     203                 :          0 :                 return -rte_errno;
     204                 :            :         }
     205                 :            : 
     206                 :            :         return 0;
     207                 :            : }
     208                 :            : 
     209                 :            : int
     210                 :          0 : hinic3_flow_parse_attr(const struct rte_flow_attr *attr,
     211                 :            :                        struct rte_flow_error *error)
     212                 :            : {
     213                 :            :         /* Not supported. */
     214   [ #  #  #  #  :          0 :         if (!attr->ingress || attr->egress || attr->priority || attr->group) {
                   #  # ]
     215                 :          0 :                 rte_flow_error_set(error, EINVAL,
     216                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, attr,
     217                 :            :                                    "Only support ingress.");
     218                 :          0 :                 return -rte_errno;
     219                 :            :         }
     220                 :            : 
     221                 :            :         return 0;
     222                 :            : }
     223                 :            : 
     224                 :            : static int
     225                 :          0 : hinic3_flow_fdir_ipv4(const struct rte_flow_item *flow_item,
     226                 :            :                       struct hinic3_filter_t *filter,
     227                 :            :                       struct rte_flow_error *error)
     228                 :            : {
     229                 :            :         const struct rte_flow_item_ipv4 *spec_ipv4, *mask_ipv4;
     230                 :            : 
     231                 :          0 :         mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
     232                 :          0 :         spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
     233         [ #  # ]:          0 :         if (!mask_ipv4 || !spec_ipv4) {
     234                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     235                 :            :                                    flow_item,
     236                 :            :                                    "Invalid fdir filter ipv4 mask or spec");
     237                 :          0 :                 return -rte_errno;
     238                 :            :         }
     239                 :            : 
     240                 :            :         /*
     241                 :            :          * Only support src address , dst addresses, proto,
     242                 :            :          * others should be masked.
     243                 :            :          */
     244         [ #  # ]:          0 :         if (mask_ipv4->hdr.version_ihl || mask_ipv4->hdr.type_of_service ||
     245   [ #  #  #  # ]:          0 :             mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
     246   [ #  #  #  # ]:          0 :             mask_ipv4->hdr.fragment_offset || mask_ipv4->hdr.time_to_live ||
     247         [ #  # ]:          0 :             mask_ipv4->hdr.hdr_checksum) {
     248                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     249                 :            :                                    flow_item,
     250                 :            :                                    "Not supported by fdir filter, ipv4 only support src ip, dst ip, proto");
     251                 :          0 :                 return -rte_errno;
     252                 :            :         }
     253                 :            : 
     254                 :            :         /* Set the filter information. */
     255                 :          0 :         filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
     256                 :          0 :         filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
     257                 :          0 :         filter->fdir_filter.key_mask.ipv4.src_ip =
     258         [ #  # ]:          0 :                 rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
     259                 :          0 :         filter->fdir_filter.key_spec.ipv4.src_ip =
     260         [ #  # ]:          0 :                 rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
     261                 :          0 :         filter->fdir_filter.key_mask.ipv4.dst_ip =
     262         [ #  # ]:          0 :                 rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
     263                 :          0 :         filter->fdir_filter.key_spec.ipv4.dst_ip =
     264         [ #  # ]:          0 :                 rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
     265                 :          0 :         filter->fdir_filter.key_mask.proto = mask_ipv4->hdr.next_proto_id;
     266                 :          0 :         filter->fdir_filter.key_spec.proto = spec_ipv4->hdr.next_proto_id;
     267                 :            : 
     268                 :          0 :         return 0;
     269                 :            : }
     270                 :            : 
     271                 :            : static int
     272                 :          0 : hinic3_flow_fdir_ipv6(const struct rte_flow_item *flow_item,
     273                 :            :                       struct hinic3_filter_t *filter,
     274                 :            :                       struct rte_flow_error *error)
     275                 :            : {
     276                 :            :         const struct rte_flow_item_ipv6 *spec_ipv6, *mask_ipv6;
     277                 :            : 
     278                 :          0 :         mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
     279                 :          0 :         spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
     280         [ #  # ]:          0 :         if (!mask_ipv6 || !spec_ipv6) {
     281                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     282                 :            :                                    flow_item,
     283                 :            :                                    "Invalid fdir filter ipv6 mask or spec");
     284                 :          0 :                 return -rte_errno;
     285                 :            :         }
     286                 :            : 
     287                 :            :         /* Only support dst addresses, src addresses, proto. */
     288   [ #  #  #  # ]:          0 :         if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
     289                 :            :             mask_ipv6->hdr.hop_limits) {
     290                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     291                 :            :                                    flow_item,
     292                 :            :                                    "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
     293                 :          0 :                 return -rte_errno;
     294                 :            :         }
     295                 :            : 
     296                 :            :         /* Set the filter information. */
     297                 :          0 :         filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
     298                 :          0 :         filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
     299                 :          0 :         net_addr_to_host(filter->fdir_filter.key_mask.ipv6.src_ip,
     300                 :          0 :                          (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
     301                 :          0 :         net_addr_to_host(filter->fdir_filter.key_spec.ipv6.src_ip,
     302                 :          0 :                          (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
     303                 :          0 :         net_addr_to_host(filter->fdir_filter.key_mask.ipv6.dst_ip,
     304                 :          0 :                          (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
     305                 :          0 :         net_addr_to_host(filter->fdir_filter.key_spec.ipv6.dst_ip,
     306                 :          0 :                          (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
     307                 :          0 :         filter->fdir_filter.key_mask.proto = mask_ipv6->hdr.proto;
     308                 :          0 :         filter->fdir_filter.key_spec.proto = spec_ipv6->hdr.proto;
     309                 :            : 
     310                 :          0 :         return 0;
     311                 :            : }
     312                 :            : 
     313                 :            : static int
     314                 :          0 : hinic3_flow_fdir_tcp(const struct rte_flow_item *flow_item,
     315                 :            :                      struct hinic3_filter_t *filter,
     316                 :            :                      struct rte_flow_error *error)
     317                 :            : {
     318                 :            :         const struct rte_flow_item_tcp *spec_tcp, *mask_tcp;
     319                 :            : 
     320                 :          0 :         mask_tcp = (const struct rte_flow_item_tcp *)flow_item->mask;
     321                 :          0 :         spec_tcp = (const struct rte_flow_item_tcp *)flow_item->spec;
     322                 :            : 
     323                 :          0 :         filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
     324                 :          0 :         filter->fdir_filter.key_spec.proto = IPPROTO_TCP;
     325                 :            : 
     326         [ #  # ]:          0 :         if (!mask_tcp && !spec_tcp)
     327                 :            :                 return 0;
     328                 :            : 
     329         [ #  # ]:          0 :         if (!mask_tcp || !spec_tcp) {
     330                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     331                 :            :                                    flow_item,
     332                 :            :                                    "Invalid fdir filter tcp mask or spec");
     333                 :          0 :                 return -rte_errno;
     334                 :            :         }
     335                 :            : 
     336                 :            :         /* Only support src, dst ports, others should be masked. */
     337   [ #  #  #  # ]:          0 :         if (mask_tcp->hdr.sent_seq || mask_tcp->hdr.recv_ack ||
     338   [ #  #  #  # ]:          0 :             mask_tcp->hdr.data_off || mask_tcp->hdr.rx_win ||
     339   [ #  #  #  # ]:          0 :             mask_tcp->hdr.tcp_flags || mask_tcp->hdr.cksum ||
     340         [ #  # ]:          0 :             mask_tcp->hdr.tcp_urp) {
     341                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     342                 :            :                                    flow_item,
     343                 :            :                                    "Not supported by fdir filter, tcp only support src port, dst port");
     344                 :          0 :                 return -rte_errno;
     345                 :            :         }
     346                 :            : 
     347                 :            :         /* Set the filter information. */
     348                 :          0 :         filter->fdir_filter.key_mask.src_port =
     349         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.src_port);
     350                 :          0 :         filter->fdir_filter.key_spec.src_port =
     351         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.src_port);
     352                 :          0 :         filter->fdir_filter.key_mask.dst_port =
     353         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.dst_port);
     354                 :          0 :         filter->fdir_filter.key_spec.dst_port =
     355         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.dst_port);
     356                 :            : 
     357                 :          0 :         return 0;
     358                 :            : }
     359                 :            : 
     360                 :            : static int
     361                 :          0 : hinic3_flow_fdir_udp(const struct rte_flow_item *flow_item,
     362                 :            :                      struct hinic3_filter_t *filter,
     363                 :            :                      struct rte_flow_error *error)
     364                 :            : {
     365                 :            :         const struct rte_flow_item_udp *spec_udp, *mask_udp;
     366                 :            : 
     367                 :          0 :         mask_udp = (const struct rte_flow_item_udp *)flow_item->mask;
     368                 :          0 :         spec_udp = (const struct rte_flow_item_udp *)flow_item->spec;
     369                 :            : 
     370                 :          0 :         filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
     371                 :          0 :         filter->fdir_filter.key_spec.proto = IPPROTO_UDP;
     372                 :            : 
     373         [ #  # ]:          0 :         if (!mask_udp && !spec_udp)
     374                 :            :                 return 0;
     375                 :            : 
     376         [ #  # ]:          0 :         if (!mask_udp || !spec_udp) {
     377                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     378                 :            :                                    flow_item,
     379                 :            :                                    "Invalid fdir filter udp mask or spec");
     380                 :          0 :                 return -rte_errno;
     381                 :            :         }
     382                 :            : 
     383                 :            :         /* Set the filter information. */
     384                 :          0 :         filter->fdir_filter.key_mask.src_port =
     385         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.src_port);
     386                 :          0 :         filter->fdir_filter.key_spec.src_port =
     387         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.src_port);
     388                 :          0 :         filter->fdir_filter.key_mask.dst_port =
     389         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.dst_port);
     390                 :          0 :         filter->fdir_filter.key_spec.dst_port =
     391         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.dst_port);
     392                 :            : 
     393                 :          0 :         return 0;
     394                 :            : }
     395                 :            : 
     396                 :            : /**
     397                 :            :  * Parse the pattern of network traffic and apply the parsing result to the
     398                 :            :  * traffic filter.
     399                 :            :  *
     400                 :            :  * @param[in] dev
     401                 :            :  * Pointer to ethernet device structure.
     402                 :            :  * @param[in] pattern
     403                 :            :  * Indicates the pattern or matching condition of a traffic rule.
     404                 :            :  * @param[out] error
     405                 :            :  * Structure that contains error information, such as error code and error
     406                 :            :  * description.
     407                 :            :  * @param[out] filter
     408                 :            :  * Filter information, Its used to store and manipulate packet filtering rules.
     409                 :            :  * @return
     410                 :            :  * 0 on success, non-zero on failure.
     411                 :            :  */
     412                 :            : static int
     413                 :          0 : hinic3_flow_parse_fdir_pattern(__rte_unused struct rte_eth_dev *dev,
     414                 :            :                                const struct rte_flow_item *pattern,
     415                 :            :                                struct rte_flow_error *error,
     416                 :            :                                struct hinic3_filter_t *filter)
     417                 :            : {
     418                 :            :         const struct rte_flow_item *flow_item = pattern;
     419                 :            :         enum rte_flow_item_type type;
     420                 :            :         int err;
     421                 :            : 
     422                 :          0 :         filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_ANY;
     423                 :            :         /* Traverse all modes until RTE_FLOW_ITEM_TYPE_END is reached. */
     424         [ #  # ]:          0 :         for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
     425         [ #  # ]:          0 :                 if (flow_item->last) {
     426                 :          0 :                         rte_flow_error_set(error, EINVAL,
     427                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     428                 :            :                                            flow_item, "Not support range");
     429                 :          0 :                         return -rte_errno;
     430                 :            :                 }
     431                 :            :                 type = flow_item->type;
     432   [ #  #  #  #  :          0 :                 switch (type) {
                   #  # ]
     433                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
     434   [ #  #  #  # ]:          0 :                         if (flow_item->spec || flow_item->mask) {
     435                 :          0 :                                 rte_flow_error_set(error, EINVAL,
     436                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
     437                 :            :                                                    flow_item,
     438                 :            :                                                    "Not supported by fdir filter, not support mac");
     439                 :          0 :                                 return -rte_errno;
     440                 :            :                         }
     441                 :            :                         break;
     442                 :            : 
     443                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
     444                 :          0 :                         err = hinic3_flow_fdir_ipv4(flow_item, filter, error);
     445         [ #  # ]:          0 :                         if (err)
     446                 :          0 :                                 return -rte_errno;
     447                 :            :                         break;
     448                 :            : 
     449                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
     450                 :          0 :                         err = hinic3_flow_fdir_ipv6(flow_item, filter, error);
     451         [ #  # ]:          0 :                         if (err)
     452                 :          0 :                                 return -rte_errno;
     453                 :            :                         break;
     454                 :            : 
     455                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
     456                 :          0 :                         err = hinic3_flow_fdir_tcp(flow_item, filter, error);
     457         [ #  # ]:          0 :                         if (err)
     458                 :          0 :                                 return -rte_errno;
     459                 :            :                         break;
     460                 :            : 
     461                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
     462                 :          0 :                         err = hinic3_flow_fdir_udp(flow_item, filter, error);
     463         [ #  # ]:          0 :                         if (err)
     464                 :          0 :                                 return -rte_errno;
     465                 :            :                         break;
     466                 :            : 
     467                 :            :                 default:
     468                 :            :                         break;
     469                 :            :                 }
     470                 :            :         }
     471                 :            : 
     472                 :            :         return 0;
     473                 :            : }
     474                 :            : 
     475                 :            : /**
     476                 :            :  * Resolve rules for network traffic filters.
     477                 :            :  *
     478                 :            :  * @param[in] dev
     479                 :            :  * Pointer to ethernet device structure.
     480                 :            :  * @param[in] attr
     481                 :            :  * Indicates the attribute of a flow rule.
     482                 :            :  * @param[in] pattern
     483                 :            :  * Indicates the pattern or matching condition of a traffic rule.
     484                 :            :  * @param[in] actions
     485                 :            :  * Indicates the action to be taken on the matched traffic.
     486                 :            :  * @param[out] error
     487                 :            :  * Structure that contains error information, such as error code and error
     488                 :            :  * description.
     489                 :            :  * @param[out] filter
     490                 :            :  * Filter information, Its used to store and manipulate packet filtering rules.
     491                 :            :  * @return
     492                 :            :  * 0 on success, non-zero on failure.
     493                 :            :  */
     494                 :            : static int
     495                 :          0 : hinic3_flow_parse_fdir_filter(struct rte_eth_dev *dev,
     496                 :            :                               const struct rte_flow_attr *attr,
     497                 :            :                               const struct rte_flow_item pattern[],
     498                 :            :                               const struct rte_flow_action actions[],
     499                 :            :                               struct rte_flow_error *error,
     500                 :            :                               struct hinic3_filter_t *filter)
     501                 :            : {
     502                 :            :         int ret;
     503                 :            : 
     504                 :          0 :         ret = hinic3_flow_parse_fdir_pattern(dev, pattern, error, filter);
     505         [ #  # ]:          0 :         if (ret)
     506                 :            :                 return ret;
     507                 :            : 
     508                 :          0 :         ret = hinic3_flow_parse_action(dev, actions, error, filter);
     509         [ #  # ]:          0 :         if (ret)
     510                 :            :                 return ret;
     511                 :            : 
     512                 :          0 :         ret = hinic3_flow_parse_attr(attr, error);
     513         [ #  # ]:          0 :         if (ret)
     514                 :            :                 return ret;
     515                 :            : 
     516                 :          0 :         filter->filter_type = RTE_ETH_FILTER_FDIR;
     517                 :            : 
     518                 :          0 :         return 0;
     519                 :            : }
     520                 :            : 
     521                 :            : /**
     522                 :            :  * Parse and process the actions of the Ethernet type.
     523                 :            :  *
     524                 :            :  * @param[in] dev
     525                 :            :  * Pointer to ethernet device structure.
     526                 :            :  * @param[in] actions
     527                 :            :  * Indicates the action to be taken on the matched traffic.
     528                 :            :  * @param[out] error
     529                 :            :  * Structure that contains error information, such as error code and error
     530                 :            :  * description.
     531                 :            :  * @param[out] filter
     532                 :            :  * Filter information, Its used to store and manipulate packet filtering rules.
     533                 :            :  * @return
     534                 :            :  * 0 on success, non-zero on failure.
     535                 :            :  */
     536                 :            : static int
     537                 :          0 : hinic3_flow_parse_ethertype_action(struct rte_eth_dev *dev,
     538                 :            :                                    const struct rte_flow_action *actions,
     539                 :            :                                    struct rte_flow_error *error,
     540                 :            :                                    struct hinic3_filter_t *filter)
     541                 :            : {
     542                 :            :         const struct rte_flow_action *act = actions;
     543                 :            :         const struct rte_flow_action_queue *act_q;
     544                 :            : 
     545                 :            :         /* Skip the firset void item. */
     546         [ #  # ]:          0 :         while (act->type == RTE_FLOW_ACTION_TYPE_VOID)
     547                 :          0 :                 act++;
     548                 :            : 
     549         [ #  # ]:          0 :         switch (act->type) {
     550                 :          0 :         case RTE_FLOW_ACTION_TYPE_QUEUE:
     551                 :          0 :                 act_q = (const struct rte_flow_action_queue *)act->conf;
     552                 :          0 :                 filter->ethertype_filter.queue = act_q->index;
     553         [ #  # ]:          0 :                 if (filter->ethertype_filter.queue >= dev->data->nb_rx_queues) {
     554                 :          0 :                         rte_flow_error_set(error, EINVAL,
     555                 :            :                                            RTE_FLOW_ERROR_TYPE_ACTION, act,
     556                 :            :                                            "Invalid action param.");
     557                 :          0 :                         return -rte_errno;
     558                 :            :                 }
     559                 :            :                 break;
     560                 :            : 
     561                 :          0 :         default:
     562                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
     563                 :            :                                    act, "Invalid action type.");
     564                 :          0 :                 return -rte_errno;
     565                 :            :         }
     566                 :            : 
     567                 :            :         return 0;
     568                 :            : }
     569                 :            : 
     570                 :            : static int
     571                 :          0 : hinic3_flow_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
     572                 :            :                                     const struct rte_flow_item *pattern,
     573                 :            :                                     struct rte_flow_error *error,
     574                 :            :                                     struct hinic3_filter_t *filter)
     575                 :            : {
     576                 :            :         const struct rte_flow_item_eth *ether_spec, *ether_mask;
     577                 :            :         const struct rte_flow_item *flow_item = pattern;
     578                 :            :         enum rte_flow_item_type type;
     579                 :            : 
     580                 :            :         /* Traverse all modes until RTE_FLOW_ITEM_TYPE_END is reached. */
     581         [ #  # ]:          0 :         for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
     582         [ #  # ]:          0 :                 if (flow_item->last) {
     583                 :          0 :                         rte_flow_error_set(error, EINVAL,
     584                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     585                 :            :                                            flow_item, "Not support range");
     586                 :          0 :                         return -rte_errno;
     587                 :            :                 }
     588                 :            :                 type = flow_item->type;
     589         [ #  # ]:          0 :                 switch (type) {
     590                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
     591                 :            :                         /* Obtaining Ethernet Specifications and Masks. */
     592                 :          0 :                         ether_spec = (const struct rte_flow_item_eth *)
     593                 :            :                                              flow_item->spec;
     594                 :          0 :                         ether_mask = (const struct rte_flow_item_eth *)
     595                 :            :                                              flow_item->mask;
     596         [ #  # ]:          0 :                         if (!ether_spec || !ether_mask) {
     597                 :          0 :                                 rte_flow_error_set(error, EINVAL,
     598                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
     599                 :            :                                                    flow_item,
     600                 :            :                                                    "NULL ETH spec/mask");
     601                 :          0 :                                 return -rte_errno;
     602                 :            :                         }
     603                 :            : 
     604                 :            :                         /*
     605                 :            :                          * Mask bits of source MAC address must be full of 0.
     606                 :            :                          * Mask bits of destination MAC address must be full 0.
     607                 :            :                          * Filters traffic based on the type of Ethernet.
     608                 :            :                          */
     609   [ #  #  #  # ]:          0 :                         if (!rte_is_zero_ether_addr(&ether_mask->src) ||
     610                 :            :                             (!rte_is_zero_ether_addr(&ether_mask->dst))) {
     611                 :          0 :                                 rte_flow_error_set(error, EINVAL,
     612                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
     613                 :            :                                                    flow_item,
     614                 :            :                                                    "Invalid ether address mask");
     615                 :          0 :                                 return -rte_errno;
     616                 :            :                         }
     617                 :            : 
     618         [ #  # ]:          0 :                         if ((ether_mask->type & UINT16_MAX) != UINT16_MAX) {
     619                 :          0 :                                 rte_flow_error_set(error, EINVAL,
     620                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
     621                 :            :                                                    flow_item,
     622                 :            :                                                    "Invalid ethertype mask");
     623                 :          0 :                                 return -rte_errno;
     624                 :            :                         }
     625                 :            : 
     626         [ #  # ]:          0 :                         filter->ethertype_filter.ether_type =
     627         [ #  # ]:          0 :                                 (uint16_t)rte_be_to_cpu_16(ether_spec->type);
     628                 :            : 
     629                 :            :                         switch (filter->ethertype_filter.ether_type) {
     630                 :            :                         case RTE_ETHER_TYPE_SLOW:
     631                 :            :                                 break;
     632                 :            : 
     633                 :            :                         case RTE_ETHER_TYPE_ARP:
     634                 :            :                                 break;
     635                 :            : 
     636                 :            :                         case RTE_ETHER_TYPE_RARP:
     637                 :            :                                 break;
     638                 :            : 
     639                 :            :                         case RTE_ETHER_TYPE_LLDP:
     640                 :            :                                 break;
     641                 :            : 
     642                 :          0 :                         default:
     643                 :          0 :                                 rte_flow_error_set(error, EINVAL,
     644                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
     645                 :            :                                                    flow_item,
     646                 :            :                                                    "Unsupported ether_type in control packet filter.");
     647                 :          0 :                                 return -rte_errno;
     648                 :            :                         }
     649                 :            :                         break;
     650                 :            : 
     651                 :            :                 default:
     652                 :            :                         break;
     653                 :            :                 }
     654                 :            :         }
     655                 :            : 
     656                 :            :         return 0;
     657                 :            : }
     658                 :            : 
     659                 :            : static int
     660                 :          0 : hinic3_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
     661                 :            :                                    const struct rte_flow_attr *attr,
     662                 :            :                                    const struct rte_flow_item pattern[],
     663                 :            :                                    const struct rte_flow_action actions[],
     664                 :            :                                    struct rte_flow_error *error,
     665                 :            :                                    struct hinic3_filter_t *filter)
     666                 :            : {
     667                 :            :         int ret;
     668                 :            : 
     669                 :          0 :         ret = hinic3_flow_parse_ethertype_pattern(dev, pattern, error, filter);
     670         [ #  # ]:          0 :         if (ret)
     671                 :            :                 return ret;
     672                 :            : 
     673                 :          0 :         ret = hinic3_flow_parse_ethertype_action(dev, actions, error, filter);
     674         [ #  # ]:          0 :         if (ret)
     675                 :            :                 return ret;
     676                 :            : 
     677                 :          0 :         ret = hinic3_flow_parse_attr(attr, error);
     678         [ #  # ]:          0 :         if (ret)
     679                 :            :                 return ret;
     680                 :            : 
     681                 :          0 :         filter->filter_type = RTE_ETH_FILTER_ETHERTYPE;
     682                 :          0 :         return 0;
     683                 :            : }
     684                 :            : 
     685                 :            : static int
     686                 :          0 : hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
     687                 :            :                              struct hinic3_filter_t *filter,
     688                 :            :                              const struct rte_flow_item *flow_item,
     689                 :            :                              enum hinic3_fdir_tunnel_mode tunnel_mode)
     690                 :            : {
     691                 :            :         const struct rte_flow_item_ipv4 *spec_ipv4, *mask_ipv4;
     692                 :          0 :         mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
     693                 :          0 :         spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
     694                 :            : 
     695         [ #  # ]:          0 :         if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
     696                 :          0 :                 filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
     697                 :            : 
     698         [ #  # ]:          0 :                 if (!mask_ipv4 && !spec_ipv4)
     699                 :            :                         return 0;
     700                 :            : 
     701         [ #  # ]:          0 :                 if (!mask_ipv4 || !spec_ipv4) {
     702                 :          0 :                         rte_flow_error_set(error, EINVAL,
     703                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     704                 :            :                                            flow_item,
     705                 :            :                                            "Invalid fdir filter, vxlan outer ipv4 mask or spec");
     706                 :          0 :                         return -rte_errno;
     707                 :            :                 }
     708                 :            : 
     709                 :            :                 /*
     710                 :            :                  * Only support src address , dst addresses, others should be
     711                 :            :                  * masked.
     712                 :            :                  */
     713         [ #  # ]:          0 :                 if (mask_ipv4->hdr.version_ihl ||
     714                 :          0 :                     mask_ipv4->hdr.type_of_service ||
     715   [ #  #  #  # ]:          0 :                     mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
     716         [ #  # ]:          0 :                     mask_ipv4->hdr.fragment_offset ||
     717         [ #  # ]:          0 :                     mask_ipv4->hdr.time_to_live ||
     718                 :          0 :                     mask_ipv4->hdr.next_proto_id ||
     719         [ #  # ]:          0 :                     mask_ipv4->hdr.hdr_checksum) {
     720                 :          0 :                         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
     721                 :            :                                 "Not supported by fdir filter, vxlan outer ipv4 only support src ip, dst ip");
     722                 :          0 :                         return -rte_errno;
     723                 :            :                 }
     724                 :            : 
     725                 :            :                 /* Set the filter information. */
     726                 :          0 :                 filter->fdir_filter.key_mask.ipv4.src_ip =
     727         [ #  # ]:          0 :                         rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
     728                 :          0 :                 filter->fdir_filter.key_spec.ipv4.src_ip =
     729         [ #  # ]:          0 :                         rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
     730                 :          0 :                 filter->fdir_filter.key_mask.ipv4.dst_ip =
     731         [ #  # ]:          0 :                         rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
     732                 :          0 :                 filter->fdir_filter.key_spec.ipv4.dst_ip =
     733         [ #  # ]:          0 :                         rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
     734                 :            :         } else {
     735                 :          0 :                 filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
     736                 :            : 
     737         [ #  # ]:          0 :                 if (!mask_ipv4 && !spec_ipv4)
     738                 :            :                         return 0;
     739                 :            : 
     740         [ #  # ]:          0 :                 if (!mask_ipv4 || !spec_ipv4) {
     741                 :          0 :                         rte_flow_error_set(error, EINVAL,
     742                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     743                 :            :                                            flow_item,
     744                 :            :                                            "Invalid fdir filter, vxlan inner ipv4 mask or spec");
     745                 :          0 :                         return -rte_errno;
     746                 :            :                 }
     747                 :            : 
     748                 :            :                 /*
     749                 :            :                  * Only support src addr , dst addr, ip proto, others should be
     750                 :            :                  * masked.
     751                 :            :                  */
     752         [ #  # ]:          0 :                 if (mask_ipv4->hdr.version_ihl ||
     753                 :          0 :                     mask_ipv4->hdr.type_of_service ||
     754   [ #  #  #  # ]:          0 :                     mask_ipv4->hdr.total_length || mask_ipv4->hdr.packet_id ||
     755         [ #  # ]:          0 :                     mask_ipv4->hdr.fragment_offset ||
     756         [ #  # ]:          0 :                     mask_ipv4->hdr.time_to_live ||
     757         [ #  # ]:          0 :                     mask_ipv4->hdr.hdr_checksum) {
     758                 :          0 :                         rte_flow_error_set(error, EINVAL,
     759                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     760                 :            :                                            flow_item,
     761                 :            :                                            "Not supported by fdir filter, vxlan inner ipv4 only support src ip, dst ip, proto");
     762                 :          0 :                         return -rte_errno;
     763                 :            :                 }
     764                 :            : 
     765                 :            :                 /* Set the filter information. */
     766                 :          0 :                 filter->fdir_filter.key_mask.inner_ipv4.src_ip =
     767         [ #  # ]:          0 :                         rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
     768                 :          0 :                 filter->fdir_filter.key_spec.inner_ipv4.src_ip =
     769         [ #  # ]:          0 :                         rte_be_to_cpu_32(spec_ipv4->hdr.src_addr);
     770                 :          0 :                 filter->fdir_filter.key_mask.inner_ipv4.dst_ip =
     771         [ #  # ]:          0 :                         rte_be_to_cpu_32(mask_ipv4->hdr.dst_addr);
     772                 :          0 :                 filter->fdir_filter.key_spec.inner_ipv4.dst_ip =
     773         [ #  # ]:          0 :                         rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
     774                 :          0 :                 filter->fdir_filter.key_mask.proto =
     775                 :          0 :                         mask_ipv4->hdr.next_proto_id;
     776                 :          0 :                 filter->fdir_filter.key_spec.proto =
     777                 :          0 :                         spec_ipv4->hdr.next_proto_id;
     778                 :            :         }
     779                 :            :         return 0;
     780                 :            : }
     781                 :            : 
     782                 :            : static int
     783                 :          0 : hinic3_flow_fdir_tunnel_ipv6(struct rte_flow_error *error,
     784                 :            :                              struct hinic3_filter_t *filter,
     785                 :            :                              const struct rte_flow_item *flow_item,
     786                 :            :                              enum hinic3_fdir_tunnel_mode tunnel_mode)
     787                 :            : {
     788                 :            :         const struct rte_flow_item_ipv6 *spec_ipv6, *mask_ipv6;
     789                 :            : 
     790                 :          0 :         mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
     791                 :          0 :         spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
     792                 :            : 
     793         [ #  # ]:          0 :         if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
     794                 :          0 :                 filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
     795                 :            : 
     796         [ #  # ]:          0 :                 if (!mask_ipv6 && !spec_ipv6)
     797                 :            :                         return 0;
     798                 :            : 
     799         [ #  # ]:          0 :                 if (!mask_ipv6 || !spec_ipv6) {
     800                 :          0 :                         rte_flow_error_set(error, EINVAL,
     801                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
     802                 :            :                                 "Invalid fdir filter ipv6 mask or spec");
     803                 :          0 :                         return -rte_errno;
     804                 :            :                 }
     805                 :            : 
     806                 :            :                 /* Only support dst addresses, src addresses. */
     807         [ #  # ]:          0 :                 if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
     808         [ #  # ]:          0 :                     mask_ipv6->hdr.hop_limits || mask_ipv6->hdr.proto) {
     809                 :          0 :                         rte_flow_error_set(error, EINVAL,
     810                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
     811                 :            :                                 "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
     812                 :          0 :                         return -rte_errno;
     813                 :            :                 }
     814                 :            : 
     815                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_mask.ipv6.src_ip,
     816                 :          0 :                                  (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
     817                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_spec.ipv6.src_ip,
     818                 :          0 :                                  (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
     819                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_mask.ipv6.dst_ip,
     820                 :          0 :                                  (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
     821                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_spec.ipv6.dst_ip,
     822                 :          0 :                                  (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
     823                 :            :         } else {
     824                 :          0 :                 filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
     825                 :            : 
     826         [ #  # ]:          0 :                 if (!mask_ipv6 && !spec_ipv6)
     827                 :            :                         return 0;
     828                 :            : 
     829         [ #  # ]:          0 :                 if (!mask_ipv6 || !spec_ipv6) {
     830                 :          0 :                         rte_flow_error_set(error, EINVAL,
     831                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
     832                 :            :                                 "Invalid fdir filter ipv6 mask or spec");
     833                 :          0 :                         return -rte_errno;
     834                 :            :                 }
     835                 :            : 
     836                 :            :                 /* Only support dst addresses, src addresses, proto. */
     837   [ #  #  #  # ]:          0 :                 if (mask_ipv6->hdr.vtc_flow || mask_ipv6->hdr.payload_len ||
     838                 :            :                     mask_ipv6->hdr.hop_limits) {
     839                 :          0 :                         rte_flow_error_set(error, EINVAL,
     840                 :            :                                 RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
     841                 :            :                                 "Not supported by fdir filter, ipv6 only support src ip, dst ip, proto");
     842                 :          0 :                         return -rte_errno;
     843                 :            :                 }
     844                 :            : 
     845                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_mask.inner_ipv6.src_ip,
     846                 :          0 :                                  (const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
     847                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_spec.inner_ipv6.src_ip,
     848                 :          0 :                                  (const uint32_t *)spec_ipv6->hdr.src_addr.a, 4);
     849                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_mask.inner_ipv6.dst_ip,
     850                 :          0 :                                  (const uint32_t *)mask_ipv6->hdr.dst_addr.a, 4);
     851                 :          0 :                 net_addr_to_host(filter->fdir_filter.key_spec.inner_ipv6.dst_ip,
     852                 :          0 :                                  (const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
     853                 :            : 
     854                 :          0 :                 filter->fdir_filter.key_mask.proto = mask_ipv6->hdr.proto;
     855                 :          0 :                 filter->fdir_filter.key_spec.proto = spec_ipv6->hdr.proto;
     856                 :            :         }
     857                 :            : 
     858                 :            :         return 0;
     859                 :            : }
     860                 :            : 
     861                 :            : static int
     862                 :          0 : hinic3_flow_fdir_tunnel_tcp(struct rte_flow_error *error,
     863                 :            :                             struct hinic3_filter_t *filter,
     864                 :            :                             enum hinic3_fdir_tunnel_mode tunnel_mode,
     865                 :            :                             const struct rte_flow_item *flow_item)
     866                 :            : {
     867                 :            :         const struct rte_flow_item_tcp *spec_tcp, *mask_tcp;
     868                 :            : 
     869         [ #  # ]:          0 :         if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
     870                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     871                 :            :                                    flow_item,
     872                 :            :                                    "Not supported by fdir filter, vxlan only support inner tcp");
     873                 :          0 :                 return -rte_errno;
     874                 :            :         }
     875                 :            : 
     876                 :          0 :         filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
     877                 :          0 :         filter->fdir_filter.key_spec.proto = IPPROTO_TCP;
     878                 :            : 
     879                 :          0 :         mask_tcp = (const struct rte_flow_item_tcp *)flow_item->mask;
     880                 :          0 :         spec_tcp = (const struct rte_flow_item_tcp *)flow_item->spec;
     881         [ #  # ]:          0 :         if (!mask_tcp && !spec_tcp)
     882                 :            :                 return 0;
     883         [ #  # ]:          0 :         if (!mask_tcp || !spec_tcp) {
     884                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     885                 :            :                                    flow_item,
     886                 :            :                                    "Invalid fdir filter tcp mask or spec");
     887                 :          0 :                 return -rte_errno;
     888                 :            :         }
     889                 :            : 
     890                 :            :         /* Only support src, dst ports, others should be masked. */
     891   [ #  #  #  # ]:          0 :         if (mask_tcp->hdr.sent_seq || mask_tcp->hdr.recv_ack ||
     892   [ #  #  #  # ]:          0 :             mask_tcp->hdr.data_off || mask_tcp->hdr.rx_win ||
     893   [ #  #  #  # ]:          0 :             mask_tcp->hdr.tcp_flags || mask_tcp->hdr.cksum ||
     894         [ #  # ]:          0 :             mask_tcp->hdr.tcp_urp) {
     895                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     896                 :            :                                    flow_item,
     897                 :            :                                    "Not supported by fdir filter, vxlan inner tcp only support src port,dst port");
     898                 :          0 :                 return -rte_errno;
     899                 :            :         }
     900                 :            : 
     901                 :            :         /* Set the filter information. */
     902                 :          0 :         filter->fdir_filter.key_mask.src_port =
     903         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.src_port);
     904                 :          0 :         filter->fdir_filter.key_spec.src_port =
     905         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.src_port);
     906                 :          0 :         filter->fdir_filter.key_mask.dst_port =
     907         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(mask_tcp->hdr.dst_port);
     908                 :          0 :         filter->fdir_filter.key_spec.dst_port =
     909         [ #  # ]:          0 :                 (uint16_t)rte_be_to_cpu_16(spec_tcp->hdr.dst_port);
     910                 :          0 :         return 0;
     911                 :            : }
     912                 :            : 
     913                 :            : static int
     914                 :          0 : hinic3_flow_fdir_tunnel_udp(struct rte_flow_error *error,
     915                 :            :                             struct hinic3_filter_t *filter,
     916                 :            :                             enum hinic3_fdir_tunnel_mode tunnel_mode,
     917                 :            :                             const struct rte_flow_item *flow_item)
     918                 :            : {
     919                 :            :         const struct rte_flow_item_udp *spec_udp, *mask_udp;
     920                 :            : 
     921                 :          0 :         mask_udp = (const struct rte_flow_item_udp *)flow_item->mask;
     922                 :          0 :         spec_udp = (const struct rte_flow_item_udp *)flow_item->spec;
     923                 :            : 
     924         [ #  # ]:          0 :         if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
     925                 :            :                 /*
     926                 :            :                  * UDP is used to describe protocol,
     927                 :            :                  * spec and mask should be NULL.
     928                 :            :                  */
     929   [ #  #  #  # ]:          0 :                 if (flow_item->spec || flow_item->mask) {
     930                 :          0 :                         rte_flow_error_set(error, EINVAL,
     931                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     932                 :            :                                            flow_item, "Invalid UDP item");
     933                 :          0 :                         return -rte_errno;
     934                 :            :                 }
     935                 :            :         } else {
     936                 :          0 :                 filter->fdir_filter.key_mask.proto = HINIC3_UINT8_MAX;
     937                 :          0 :                 filter->fdir_filter.key_spec.proto = IPPROTO_UDP;
     938         [ #  # ]:          0 :                 if (!mask_udp && !spec_udp)
     939                 :            :                         return 0;
     940                 :            : 
     941         [ #  # ]:          0 :                 if (!mask_udp || !spec_udp) {
     942                 :          0 :                         rte_flow_error_set(error, EINVAL,
     943                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
     944                 :            :                                            flow_item,
     945                 :            :                                            "Invalid fdir filter vxlan inner udp mask or spec");
     946                 :          0 :                         return -rte_errno;
     947                 :            :                 }
     948                 :            : 
     949                 :            :                 /* Set the filter information. */
     950                 :          0 :                 filter->fdir_filter.key_mask.src_port =
     951         [ #  # ]:          0 :                         (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.src_port);
     952                 :          0 :                 filter->fdir_filter.key_spec.src_port =
     953         [ #  # ]:          0 :                         (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.src_port);
     954                 :          0 :                 filter->fdir_filter.key_mask.dst_port =
     955         [ #  # ]:          0 :                         (uint16_t)rte_be_to_cpu_16(mask_udp->hdr.dst_port);
     956                 :          0 :                 filter->fdir_filter.key_spec.dst_port =
     957         [ #  # ]:          0 :                         (uint16_t)rte_be_to_cpu_16(spec_udp->hdr.dst_port);
     958                 :            :         }
     959                 :            : 
     960                 :            :         return 0;
     961                 :            : }
     962                 :            : 
     963                 :            : static int
     964                 :          0 : hinic3_flow_fdir_vxlan(struct rte_flow_error *error,
     965                 :            :                        struct hinic3_filter_t *filter,
     966                 :            :                        const struct rte_flow_item *flow_item)
     967                 :            : {
     968                 :            :         const struct rte_flow_item_vxlan *spec_vxlan, *mask_vxlan;
     969                 :          0 :         uint32_t vxlan_vni_id = 0;
     970                 :            : 
     971                 :          0 :         spec_vxlan = (const struct rte_flow_item_vxlan *)flow_item->spec;
     972                 :          0 :         mask_vxlan = (const struct rte_flow_item_vxlan *)flow_item->mask;
     973                 :            : 
     974                 :          0 :         filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
     975                 :            : 
     976         [ #  # ]:          0 :         if (!spec_vxlan && !mask_vxlan) {
     977                 :            :                 return 0;
     978         [ #  # ]:          0 :         } else if (filter->fdir_filter.outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV6) {
     979                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     980                 :            :                                    flow_item,
     981                 :            :                                    "Invalid fdir filter vxlan mask or spec, ipv6 vxlan, don't support vni");
     982                 :          0 :                 return -rte_errno;
     983                 :            :         }
     984                 :            : 
     985         [ #  # ]:          0 :         if (!spec_vxlan || !mask_vxlan) {
     986                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
     987                 :            :                                    flow_item,
     988                 :            :                                    "Invalid fdir filter vxlan mask or spec");
     989                 :          0 :                 return -rte_errno;
     990                 :            :         }
     991                 :            : 
     992         [ #  # ]:          0 :         memcpy(((uint8_t *)&vxlan_vni_id + 1), spec_vxlan->vni, 3);
     993                 :          0 :         filter->fdir_filter.key_mask.tunnel.tunnel_id =
     994         [ #  # ]:          0 :                 rte_be_to_cpu_32(vxlan_vni_id);
     995                 :          0 :         return 0;
     996                 :            : }
     997                 :            : 
     998                 :            : static int
     999                 :          0 : hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
    1000                 :            :                                      const struct rte_flow_item *pattern,
    1001                 :            :                                      struct rte_flow_error *error,
    1002                 :            :                                      struct hinic3_filter_t *filter)
    1003                 :            : {
    1004                 :            :         const struct rte_flow_item *flow_item = pattern;
    1005                 :            :         enum hinic3_fdir_tunnel_mode tunnel_mode =
    1006                 :            :                 HINIC3_FDIR_TUNNEL_MODE_NORMAL;
    1007                 :            :         enum rte_flow_item_type type;
    1008                 :            :         int err;
    1009                 :            : 
    1010                 :            :         /* Inner and outer ip type, set it to any by default */
    1011                 :          0 :         filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_ANY;
    1012                 :          0 :         filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_ANY;
    1013                 :            : 
    1014         [ #  # ]:          0 :         for (; flow_item->type != RTE_FLOW_ITEM_TYPE_END; flow_item++) {
    1015         [ #  # ]:          0 :                 if (flow_item->last) {
    1016                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1017                 :            :                                            RTE_FLOW_ERROR_TYPE_ITEM,
    1018                 :            :                                            flow_item, "Not support range");
    1019                 :          0 :                         return -rte_errno;
    1020                 :            :                 }
    1021                 :            : 
    1022                 :            :                 type = flow_item->type;
    1023   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
    1024                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    1025                 :            :                         /* All should be masked. */
    1026   [ #  #  #  # ]:          0 :                         if (flow_item->spec || flow_item->mask) {
    1027                 :          0 :                                 rte_flow_error_set(error, EINVAL,
    1028                 :            :                                                    RTE_FLOW_ERROR_TYPE_ITEM,
    1029                 :            :                                                    flow_item,
    1030                 :            :                                                    "Not supported by fdir filter, not support mac");
    1031                 :          0 :                                 return -rte_errno;
    1032                 :            :                         }
    1033                 :            :                         break;
    1034                 :            : 
    1035                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    1036                 :          0 :                         err = hinic3_flow_fdir_tunnel_ipv4(error,
    1037                 :            :                                 filter, flow_item, tunnel_mode);
    1038         [ #  # ]:          0 :                         if (err)
    1039                 :          0 :                                 return -rte_errno;
    1040                 :            :                         break;
    1041                 :            : 
    1042                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV6:
    1043                 :          0 :                         err = hinic3_flow_fdir_tunnel_ipv6(error,
    1044                 :            :                                 filter, flow_item, tunnel_mode);
    1045         [ #  # ]:          0 :                         if (err)
    1046                 :          0 :                                 return -rte_errno;
    1047                 :            :                         break;
    1048                 :            : 
    1049                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    1050                 :          0 :                         err = hinic3_flow_fdir_tunnel_tcp(error,
    1051                 :            :                                 filter, tunnel_mode, flow_item);
    1052         [ #  # ]:          0 :                         if (err)
    1053                 :          0 :                                 return -rte_errno;
    1054                 :            :                         break;
    1055                 :            : 
    1056                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    1057                 :          0 :                         err = hinic3_flow_fdir_tunnel_udp(error,
    1058                 :            :                                 filter, tunnel_mode, flow_item);
    1059         [ #  # ]:          0 :                         if (err)
    1060                 :          0 :                                 return -rte_errno;
    1061                 :            :                         break;
    1062                 :            : 
    1063                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    1064                 :          0 :                         err = hinic3_flow_fdir_vxlan(error, filter, flow_item);
    1065         [ #  # ]:          0 :                         if (err)
    1066                 :          0 :                                 return -rte_errno;
    1067                 :            :                         tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
    1068                 :            :                         break;
    1069                 :            : 
    1070                 :            :                 default:
    1071                 :            :                         break;
    1072                 :            :                 }
    1073                 :            :         }
    1074                 :            : 
    1075                 :            :         return 0;
    1076                 :            : }
    1077                 :            : 
    1078                 :            : /**
    1079                 :            :  * Resolve VXLAN Filters in Flow Filters.
    1080                 :            :  *
    1081                 :            :  * @param[in] dev
    1082                 :            :  * Pointer to ethernet device structure.
    1083                 :            :  * @param[in] attr
    1084                 :            :  * Indicates the attribute of a flow rule.
    1085                 :            :  * @param[in] pattern
    1086                 :            :  * Indicates the pattern or matching condition of a traffic rule.
    1087                 :            :  * @param[in] actions
    1088                 :            :  * Indicates the action to be taken on the matched traffic.
    1089                 :            :  * @param[out] error
    1090                 :            :  * Structure that contains error information, such as error code and error
    1091                 :            :  * description.
    1092                 :            :  * @param[out] filter
    1093                 :            :  * Filter information, its used to store and manipulate packet filtering rules.
    1094                 :            :  * @return
    1095                 :            :  * 0 on success, non-zero on failure.
    1096                 :            :  */
    1097                 :            : static int
    1098                 :          0 : hinic3_flow_parse_fdir_vxlan_filter(struct rte_eth_dev *dev,
    1099                 :            :                                     const struct rte_flow_attr *attr,
    1100                 :            :                                     const struct rte_flow_item pattern[],
    1101                 :            :                                     const struct rte_flow_action actions[],
    1102                 :            :                                     struct rte_flow_error *error,
    1103                 :            :                                     struct hinic3_filter_t *filter)
    1104                 :            : {
    1105                 :            :         int ret;
    1106                 :            : 
    1107                 :          0 :         ret = hinic3_flow_parse_fdir_vxlan_pattern(dev, pattern, error, filter);
    1108         [ #  # ]:          0 :         if (ret)
    1109                 :            :                 return ret;
    1110                 :            : 
    1111                 :          0 :         ret = hinic3_flow_parse_action(dev, actions, error, filter);
    1112         [ #  # ]:          0 :         if (ret)
    1113                 :            :                 return ret;
    1114                 :            : 
    1115                 :          0 :         ret = hinic3_flow_parse_attr(attr, error);
    1116         [ #  # ]:          0 :         if (ret)
    1117                 :            :                 return ret;
    1118                 :            : 
    1119                 :          0 :         filter->filter_type = RTE_ETH_FILTER_FDIR;
    1120                 :            : 
    1121                 :          0 :         return 0;
    1122                 :            : }
    1123                 :            : 
    1124                 :            : /**
    1125                 :            :  * Parse patterns and actions of network traffic.
    1126                 :            :  *
    1127                 :            :  * @param[in] dev
    1128                 :            :  * Pointer to ethernet device structure.
    1129                 :            :  * @param[in] attr
    1130                 :            :  * Indicates the attribute of a flow rule.
    1131                 :            :  * @param[in] pattern
    1132                 :            :  * Indicates the pattern or matching condition of a traffic rule.
    1133                 :            :  * @param[in] actions
    1134                 :            :  * Indicates the action to be taken on the matched traffic.
    1135                 :            :  * @param[out] error
    1136                 :            :  * Structure that contains error information, such as error code and error
    1137                 :            :  * description.
    1138                 :            :  * @param[out] filter
    1139                 :            :  * Filter information, its used to store and manipulate packet filtering rules.
    1140                 :            :  * @return
    1141                 :            :  * 0 on success, non-zero on failure.
    1142                 :            :  */
    1143                 :            : static int
    1144                 :          0 : hinic3_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    1145                 :            :                   const struct rte_flow_item pattern[],
    1146                 :            :                   const struct rte_flow_action actions[],
    1147                 :            :                   struct rte_flow_error *error, struct hinic3_filter_t *filter)
    1148                 :            : {
    1149                 :            :         hinic3_parse_filter_t parse_filter;
    1150                 :            :         uint32_t pattern_num = 0;
    1151                 :            :         int ret = 0;
    1152                 :            :         /* Check whether the parameter is valid. */
    1153   [ #  #  #  # ]:          0 :         if (!pattern || !actions || !attr) {
    1154                 :          0 :                 rte_flow_error_set(error, EINVAL,
    1155                 :            :                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
    1156                 :            :                                    "NULL param.");
    1157                 :          0 :                 return -rte_errno;
    1158                 :            :         }
    1159                 :            : 
    1160         [ #  # ]:          0 :         while ((pattern + pattern_num)->type != RTE_FLOW_ITEM_TYPE_END) {
    1161                 :          0 :                 pattern_num++;
    1162         [ #  # ]:          0 :                 if (pattern_num > HINIC3_FLOW_MAX_PATTERN_NUM) {
    1163                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1164                 :            :                                            HINIC3_FLOW_MAX_PATTERN_NUM, NULL,
    1165                 :            :                                            "Too many patterns.");
    1166                 :          0 :                         return -rte_errno;
    1167                 :            :                 }
    1168                 :            :         }
    1169                 :            :         /*
    1170                 :            :          * The corresponding filter is returned. If the filter is not found,
    1171                 :            :          * NULL is returned.
    1172                 :            :          */
    1173                 :          0 :         parse_filter = hinic3_find_parse_filter_func(pattern);
    1174         [ #  # ]:          0 :         if (!parse_filter) {
    1175                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
    1176                 :            :                                    pattern, "Unsupported pattern");
    1177                 :          0 :                 return -rte_errno;
    1178                 :            :         }
    1179                 :            :         /* Parsing with filters. */
    1180                 :          0 :         ret = parse_filter(dev, attr, pattern, actions, error, filter);
    1181                 :            : 
    1182                 :          0 :         return ret;
    1183                 :            : }
    1184                 :            : 
    1185                 :            : /**
    1186                 :            :  * Check whether the traffic rule provided by the user is valid.
    1187                 :            :  *
    1188                 :            :  * @param[in] dev
    1189                 :            :  * Pointer to ethernet device structure.
    1190                 :            :  * @param[in] attr
    1191                 :            :  * Indicates the attribute of a flow rule.
    1192                 :            :  * @param[in] pattern
    1193                 :            :  * Indicates the pattern or matching condition of a traffic rule.
    1194                 :            :  * @param[in] actions
    1195                 :            :  * Indicates the action to be taken on the matched traffic.
    1196                 :            :  * @param[out] error
    1197                 :            :  * Structure that contains error information, such as error code and error
    1198                 :            :  * description.
    1199                 :            :  * @return
    1200                 :            :  * 0 on success, non-zero on failure.
    1201                 :            :  */
    1202                 :            : static int
    1203                 :          0 : hinic3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    1204                 :            :                      const struct rte_flow_item pattern[],
    1205                 :            :                      const struct rte_flow_action actions[],
    1206                 :            :                      struct rte_flow_error *error)
    1207                 :            : {
    1208                 :          0 :         struct hinic3_filter_t filter_rules = {0};
    1209                 :            : 
    1210                 :          0 :         return hinic3_flow_parse(dev, attr, pattern, actions, error, &filter_rules);
    1211                 :            : }
    1212                 :            : 
    1213                 :            : /**
    1214                 :            :  * Create a flow item.
    1215                 :            :  *
    1216                 :            :  * @param[in] dev
    1217                 :            :  * Pointer to ethernet device structure.
    1218                 :            :  * @param[in] attr
    1219                 :            :  * Indicates the attribute of a flow rule.
    1220                 :            :  * @param[in] pattern
    1221                 :            :  * Indicates the pattern or matching condition of a traffic rule.
    1222                 :            :  * @param[in] actions
    1223                 :            :  * Indicates the action to be taken on the matched traffic.
    1224                 :            :  * @param[out] error
    1225                 :            :  * Structure that contains error information, such as error code and error
    1226                 :            :  * description.
    1227                 :            :  * @return
    1228                 :            :  * If the operation is successful, the created flow is returned. Otherwise, NULL
    1229                 :            :  * is returned.
    1230                 :            :  *
    1231                 :            :  */
    1232                 :            : static struct rte_flow *
    1233                 :          0 : hinic3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
    1234                 :            :                    const struct rte_flow_item pattern[],
    1235                 :            :                    const struct rte_flow_action actions[],
    1236                 :            :                    struct rte_flow_error *error)
    1237                 :            : {
    1238                 :          0 :         struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
    1239                 :            :         struct hinic3_filter_t *filter_rules = NULL;
    1240                 :            :         struct rte_flow *flow = NULL;
    1241                 :            :         int ret;
    1242                 :            : 
    1243                 :            :         filter_rules =
    1244                 :          0 :                 rte_zmalloc("filter_rules", sizeof(struct hinic3_filter_t), 0);
    1245         [ #  # ]:          0 :         if (!filter_rules) {
    1246                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
    1247                 :            :                                    NULL,
    1248                 :            :                                    "Failed to allocate filter rules memory.");
    1249                 :          0 :                 return NULL;
    1250                 :            :         }
    1251                 :            : 
    1252                 :          0 :         flow = rte_zmalloc("hinic3_rte_flow", sizeof(struct rte_flow), 0);
    1253         [ #  # ]:          0 :         if (!flow) {
    1254                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
    1255                 :            :                                    NULL, "Failed to allocate flow memory.");
    1256                 :          0 :                 rte_free(filter_rules);
    1257                 :          0 :                 return NULL;
    1258                 :            :         }
    1259                 :            :         /* Parses the flow rule to be created and generates a filter. */
    1260                 :          0 :         ret = hinic3_flow_parse(dev, attr, pattern, actions, error,
    1261                 :            :                                 filter_rules);
    1262         [ #  # ]:          0 :         if (ret < 0)
    1263                 :          0 :                 goto free_flow;
    1264                 :            : 
    1265      [ #  #  # ]:          0 :         switch (filter_rules->filter_type) {
    1266                 :          0 :         case RTE_ETH_FILTER_ETHERTYPE:
    1267                 :          0 :                 ret = hinic3_flow_add_del_ethertype_filter(dev,
    1268                 :            :                         &filter_rules->ethertype_filter, true);
    1269         [ #  # ]:          0 :                 if (ret) {
    1270                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1271                 :            :                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
    1272                 :            :                                            "Create ethertype filter failed.");
    1273                 :          0 :                         goto free_flow;
    1274                 :            :                 }
    1275                 :            : 
    1276                 :          0 :                 flow->rule = filter_rules;
    1277                 :          0 :                 flow->filter_type = filter_rules->filter_type;
    1278                 :          0 :                 TAILQ_INSERT_TAIL(&nic_dev->filter_ethertype_list, flow, node);
    1279                 :          0 :                 break;
    1280                 :            : 
    1281                 :          0 :         case RTE_ETH_FILTER_FDIR:
    1282                 :          0 :                 ret = hinic3_flow_add_del_fdir_filter(dev,
    1283                 :            :                         &filter_rules->fdir_filter, true);
    1284         [ #  # ]:          0 :                 if (ret) {
    1285                 :          0 :                         rte_flow_error_set(error, EINVAL,
    1286                 :            :                                            RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
    1287                 :            :                                            "Create fdir filter failed.");
    1288                 :          0 :                         goto free_flow;
    1289                 :            :                 }
    1290                 :            : 
    1291                 :          0 :                 flow->rule = filter_rules;
    1292                 :          0 :                 flow->filter_type = filter_rules->filter_type;
    1293                 :          0 :                 TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list, flow, node);
    1294                 :          0 :                 break;
    1295                 :          0 :         default:
    1296                 :          0 :                 PMD_DRV_LOG(ERR, "Filter type %d not supported",
    1297                 :            :                             filter_rules->filter_type);
    1298                 :          0 :                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
    1299                 :            :                                    NULL, "Unsupported filter type.");
    1300                 :          0 :                 goto free_flow;
    1301                 :            :         }
    1302                 :            : 
    1303                 :            :         return flow;
    1304                 :            : 
    1305                 :          0 : free_flow:
    1306                 :          0 :         rte_free(flow);
    1307                 :          0 :         rte_free(filter_rules);
    1308                 :            : 
    1309                 :          0 :         return NULL;
    1310                 :            : }
    1311                 :            : 
    1312                 :            : static int
    1313                 :          0 : hinic3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
    1314                 :            :                     struct rte_flow_error *error)
    1315                 :            : {
    1316                 :            :         int ret = -EINVAL;
    1317                 :            :         enum rte_filter_type type;
    1318                 :            :         struct hinic3_filter_t *rules = NULL;
    1319                 :          0 :         struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
    1320                 :            : 
    1321         [ #  # ]:          0 :         if (!flow) {
    1322                 :          0 :                 PMD_DRV_LOG(ERR, "Invalid flow parameter!");
    1323                 :          0 :                 return -EPERM;
    1324                 :            :         }
    1325                 :            : 
    1326                 :          0 :         type = flow->filter_type;
    1327                 :          0 :         rules = (struct hinic3_filter_t *)flow->rule;
    1328                 :            :         /* Perform operations based on the type. */
    1329      [ #  #  # ]:          0 :         switch (type) {
    1330                 :          0 :         case RTE_ETH_FILTER_ETHERTYPE:
    1331                 :          0 :                 ret = hinic3_flow_add_del_ethertype_filter(dev,
    1332                 :            :                         &rules->ethertype_filter, false);
    1333         [ #  # ]:          0 :                 if (!ret)
    1334         [ #  # ]:          0 :                         TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
    1335                 :            : 
    1336                 :          0 :                 flow->rule = rules;
    1337                 :          0 :                 flow->filter_type = rules->filter_type;
    1338         [ #  # ]:          0 :                 TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
    1339                 :          0 :                 break;
    1340                 :            : 
    1341                 :          0 :         case RTE_ETH_FILTER_FDIR:
    1342                 :          0 :                 ret = hinic3_flow_add_del_fdir_filter(dev, &rules->fdir_filter, false);
    1343         [ #  # ]:          0 :                 if (!ret)
    1344         [ #  # ]:          0 :                         TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, flow, node);
    1345                 :            :                 break;
    1346                 :          0 :         default:
    1347                 :          0 :                 PMD_DRV_LOG(WARNING, "Filter type %d not supported", type);
    1348                 :            :                 ret = -EINVAL;
    1349                 :            :                 break;
    1350                 :            :         }
    1351                 :            : 
    1352                 :            :         /* Deleted successfully. Resources are released. */
    1353         [ #  # ]:          0 :         if (!ret) {
    1354                 :          0 :                 rte_free(rules);
    1355                 :          0 :                 rte_free(flow);
    1356                 :            :         } else {
    1357                 :          0 :                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
    1358                 :            :                                    NULL, "Failed to destroy flow.");
    1359                 :            :         }
    1360                 :            : 
    1361                 :            :         return ret;
    1362                 :            : }
    1363                 :            : 
    1364                 :            : /**
    1365                 :            :  * Clear all fdir type flow rules on the network device.
    1366                 :            :  *
    1367                 :            :  * @param[in] dev
    1368                 :            :  * Pointer to ethernet device structure.
    1369                 :            :  * @return
    1370                 :            :  * 0 on success, non-zero on failure.
    1371                 :            :  */
    1372                 :            : static int
    1373                 :          0 : hinic3_flow_flush_fdir_filter(struct rte_eth_dev *dev)
    1374                 :            : {
    1375                 :            :         int ret = 0;
    1376                 :            :         struct hinic3_filter_t *filter_rules = NULL;
    1377                 :          0 :         struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
    1378                 :            :         struct rte_flow *flow;
    1379                 :            : 
    1380                 :            :         while (true) {
    1381                 :          0 :                 flow = TAILQ_FIRST(&nic_dev->filter_fdir_rule_list);
    1382         [ #  # ]:          0 :                 if (flow == NULL)
    1383                 :            :                         break;
    1384                 :          0 :                 filter_rules = (struct hinic3_filter_t *)flow->rule;
    1385                 :            : 
    1386                 :            :                 /* Delete flow rules. */
    1387                 :          0 :                 ret = hinic3_flow_add_del_fdir_filter(dev,
    1388                 :            :                         &filter_rules->fdir_filter, false);
    1389                 :            : 
    1390         [ #  # ]:          0 :                 if (ret)
    1391                 :          0 :                         return ret;
    1392                 :            : 
    1393         [ #  # ]:          0 :                 TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, flow, node);
    1394                 :          0 :                 rte_free(filter_rules);
    1395                 :          0 :                 rte_free(flow);
    1396                 :            :         }
    1397                 :            : 
    1398                 :            :         return ret;
    1399                 :            : }
    1400                 :            : 
    1401                 :            : /**
    1402                 :            :  * Clear all ether type flow rules on the network device.
    1403                 :            :  *
    1404                 :            :  * @param[in] dev
    1405                 :            :  * Pointer to ethernet device structure.
    1406                 :            :  * @return
    1407                 :            :  * 0 on success, non-zero on failure.
    1408                 :            :  */
    1409                 :            : static int
    1410                 :          0 : hinic3_flow_flush_ethertype_filter(struct rte_eth_dev *dev)
    1411                 :            : {
    1412                 :            :         struct hinic3_filter_t *filter_rules = NULL;
    1413                 :          0 :         struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
    1414                 :            :         struct rte_flow *flow;
    1415                 :            :         int ret = 0;
    1416                 :            : 
    1417                 :            :         while (true) {
    1418                 :          0 :                 flow = TAILQ_FIRST(&nic_dev->filter_ethertype_list);
    1419         [ #  # ]:          0 :                 if (flow == NULL)
    1420                 :            :                         break;
    1421                 :          0 :                 filter_rules = (struct hinic3_filter_t *)flow->rule;
    1422                 :            : 
    1423                 :            :                 /* Delete flow rules. */
    1424                 :          0 :                 ret = hinic3_flow_add_del_ethertype_filter(dev,
    1425                 :            :                         &filter_rules->ethertype_filter, false);
    1426                 :            : 
    1427         [ #  # ]:          0 :                 if (ret)
    1428                 :          0 :                         return ret;
    1429                 :            : 
    1430         [ #  # ]:          0 :                 TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
    1431                 :          0 :                 rte_free(filter_rules);
    1432                 :          0 :                 rte_free(flow);
    1433                 :            :         }
    1434                 :            : 
    1435                 :            :         return ret;
    1436                 :            : }
    1437                 :            : 
    1438                 :            : /**
    1439                 :            :  * Clear all flow rules on the network device.
    1440                 :            :  *
    1441                 :            :  * @param[in] dev
    1442                 :            :  * Pointer to ethernet device structure.
    1443                 :            :  * @param[out] error
    1444                 :            :  * Structure that contains error information, such as error code and error
    1445                 :            :  * description.
    1446                 :            :  * @return
    1447                 :            :  * 0 on success, non-zero on failure.
    1448                 :            :  */
    1449                 :            : static int
    1450                 :          0 : hinic3_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
    1451                 :            : {
    1452                 :            :         int ret;
    1453                 :            : 
    1454                 :          0 :         ret = hinic3_flow_flush_fdir_filter(dev);
    1455         [ #  # ]:          0 :         if (ret) {
    1456                 :          0 :                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
    1457                 :            :                                    NULL, "Failed to flush fdir flows.");
    1458                 :          0 :                 return -rte_errno;
    1459                 :            :         }
    1460                 :            : 
    1461                 :          0 :         ret = hinic3_flow_flush_ethertype_filter(dev);
    1462         [ #  # ]:          0 :         if (ret) {
    1463                 :          0 :                 rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE,
    1464                 :            :                                    NULL, "Failed to flush ethertype flows.");
    1465                 :          0 :                 return -rte_errno;
    1466                 :            :         }
    1467                 :            :         return ret;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : /* Structure for managing flow table operations. */
    1471                 :            : const struct rte_flow_ops hinic3_flow_ops = {
    1472                 :            :         .validate = hinic3_flow_validate,
    1473                 :            :         .create = hinic3_flow_create,
    1474                 :            :         .destroy = hinic3_flow_destroy,
    1475                 :            :         .flush = hinic3_flow_flush,
    1476                 :            : };

Generated by: LCOV version 1.14