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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Corigine, Inc.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "nfp_conntrack.h"
       7                 :            : 
       8                 :            : #include <rte_malloc.h>
       9                 :            : #include <rte_hash.h>
      10                 :            : #include <rte_jhash.h>
      11                 :            : 
      12                 :            : #include "../nfp_logs.h"
      13                 :            : #include "nfp_flower_cmsg.h"
      14                 :            : #include "nfp_flower_representor.h"
      15                 :            : 
      16                 :            : struct ct_data {
      17                 :            :         uint8_t  ct_state;        /* Connection state. */
      18                 :            :         uint16_t ct_zone;         /* Connection zone. */
      19                 :            : };
      20                 :            : 
      21                 :            : enum ct_entry_type {
      22                 :            :         CT_TYPE_PRE_CT,
      23                 :            :         CT_TYPE_POST_CT,
      24                 :            : };
      25                 :            : 
      26                 :            : struct nfp_initial_flow {
      27                 :            :         struct rte_flow_item *items;
      28                 :            :         struct rte_flow_action *actions;
      29                 :            :         uint8_t items_cnt;
      30                 :            :         uint8_t actions_cnt;
      31                 :            : };
      32                 :            : 
      33                 :            : struct nfp_ct_flow_entry {
      34                 :            :         uint64_t cookie;
      35                 :            :         LIST_ENTRY(nfp_ct_flow_entry) pre_ct_list;
      36                 :            :         LIST_ENTRY(nfp_ct_flow_entry) post_ct_list;
      37                 :            :         LIST_HEAD(, nfp_ct_merge_entry) children;
      38                 :            :         enum ct_entry_type type;
      39                 :            :         struct rte_eth_dev *dev;
      40                 :            :         struct nfp_ct_zone_entry *ze;
      41                 :            :         struct nfp_initial_flow rule;
      42                 :            :         struct nfp_fl_stats stats;
      43                 :            : };
      44                 :            : 
      45                 :            : struct nfp_ct_map_entry {
      46                 :            :         uint64_t cookie;
      47                 :            :         struct nfp_ct_flow_entry *fe;
      48                 :            : };
      49                 :            : 
      50                 :            : struct nfp_ct_zone_entry {
      51                 :            :         uint32_t zone;
      52                 :            :         struct nfp_flow_priv *priv;
      53                 :            :         LIST_HEAD(, nfp_ct_flow_entry) pre_ct_list;
      54                 :            :         LIST_HEAD(, nfp_ct_flow_entry) post_ct_list;
      55                 :            :         struct rte_hash *ct_merge_table;
      56                 :            : };
      57                 :            : 
      58                 :            : struct nfp_ct_merge_entry {
      59                 :            :         uint64_t cookie[2];
      60                 :            :         uint32_t ctx_id;
      61                 :            :         LIST_ENTRY(nfp_ct_merge_entry) pre_ct_list;
      62                 :            :         LIST_ENTRY(nfp_ct_merge_entry) post_ct_list;
      63                 :            :         struct nfp_initial_flow rule;
      64                 :            :         struct rte_flow *compiled_rule;
      65                 :            :         struct nfp_ct_zone_entry *ze;
      66                 :            :         struct nfp_ct_flow_entry *pre_ct_parent;
      67                 :            :         struct nfp_ct_flow_entry *post_ct_parent;
      68                 :            : };
      69                 :            : 
      70                 :            : /* OVS_KEY_ATTR_CT_STATE flags */
      71                 :            : #define OVS_CS_F_NEW            0x01 /* Beginning of a new connection. */
      72                 :            : #define OVS_CS_F_ESTABLISHED    0x02 /* Part of an existing connection. */
      73                 :            : #define OVS_CS_F_RELATED        0x04 /* Related to an established connection. */
      74                 :            : #define OVS_CS_F_REPLY_DIR      0x08 /* Flow is in the reply direction. */
      75                 :            : #define OVS_CS_F_INVALID        0x10 /* Could not track connection. */
      76                 :            : #define OVS_CS_F_TRACKED        0x20 /* Conntrack has occurred. */
      77                 :            : #define OVS_CS_F_SRC_NAT        0x40 /* Packet's source address/port was mangled by NAT. */
      78                 :            : #define OVS_CS_F_DST_NAT        0x80 /* Packet's destination address/port was mangled by NAT. */
      79                 :            : 
      80                 :            : typedef void (*nfp_action_free_fn)(void *field);
      81                 :            : typedef bool (*nfp_action_copy_fn)(const void *src, void *dst);
      82                 :            : 
      83                 :            : static bool
      84                 :            : is_pre_ct_flow(const struct ct_data *ct,
      85                 :            :                 const struct rte_flow_action *actions)
      86                 :            : {
      87                 :            :         const struct rte_flow_action *action;
      88                 :            : 
      89         [ #  # ]:          0 :         if (ct == NULL)
      90                 :            :                 return false;
      91                 :            : 
      92         [ #  # ]:          0 :         for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
      93         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK)
      94                 :            :                         return true;
      95                 :            :         }
      96                 :            : 
      97                 :            :         return false;
      98                 :            : }
      99                 :            : 
     100                 :            : static bool
     101                 :            : is_post_ct_flow(const struct ct_data *ct)
     102                 :            : {
     103         [ #  # ]:          0 :         if (ct == NULL)
     104                 :            :                 return false;
     105                 :            : 
     106         [ #  # ]:          0 :         if ((ct->ct_state & OVS_CS_F_ESTABLISHED) != 0)
     107                 :            :                 return true;
     108                 :            : 
     109                 :            :         return false;
     110                 :            : }
     111                 :            : 
     112                 :            : static bool
     113                 :            : is_ct_commit_flow(const struct ct_data *ct)
     114                 :            : {
     115                 :          0 :         if (ct == NULL)
     116                 :            :                 return false;
     117                 :            : 
     118         [ #  # ]:          0 :         if ((ct->ct_state & OVS_CS_F_NEW) != 0)
     119                 :            :                 return true;
     120                 :            : 
     121                 :            :         return false;
     122                 :            : }
     123                 :            : 
     124                 :            : static struct nfp_ct_merge_entry *
     125                 :          0 : nfp_ct_merge_table_search(struct nfp_ct_zone_entry *ze,
     126                 :            :                 char *hash_data,
     127                 :            :                 uint32_t hash_len)
     128                 :            : {
     129                 :            :         int index;
     130                 :            :         uint32_t hash_key;
     131                 :            :         struct nfp_ct_merge_entry *m_ent;
     132                 :            : 
     133                 :          0 :         hash_key = rte_jhash(hash_data, hash_len, ze->priv->hash_seed);
     134                 :          0 :         index = rte_hash_lookup_data(ze->ct_merge_table, &hash_key, (void **)&m_ent);
     135         [ #  # ]:          0 :         if (index < 0) {
     136                 :          0 :                 PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_merge table.");
     137                 :          0 :                 return NULL;
     138                 :            :         }
     139                 :            : 
     140                 :          0 :         return m_ent;
     141                 :            : }
     142                 :            : 
     143                 :            : static bool
     144                 :          0 : nfp_ct_merge_table_add(struct nfp_ct_zone_entry *ze,
     145                 :            :                 struct nfp_ct_merge_entry *merge_entry)
     146                 :            : {
     147                 :            :         int ret;
     148                 :            :         uint32_t hash_key;
     149                 :            : 
     150                 :          0 :         hash_key = rte_jhash(merge_entry, sizeof(uint64_t) * 2, ze->priv->hash_seed);
     151                 :          0 :         ret = rte_hash_add_key_data(ze->ct_merge_table, &hash_key, merge_entry);
     152         [ #  # ]:          0 :         if (ret != 0) {
     153                 :          0 :                 PMD_DRV_LOG(ERR, "Add to ct_merge table failed.");
     154                 :          0 :                 return false;
     155                 :            :         }
     156                 :            : 
     157                 :            :         return true;
     158                 :            : }
     159                 :            : 
     160                 :            : static void
     161                 :          0 : nfp_ct_merge_table_delete(struct nfp_ct_zone_entry *ze,
     162                 :            :                 struct nfp_ct_merge_entry *m_ent)
     163                 :            : {
     164                 :            :         int ret;
     165                 :            :         uint32_t hash_key;
     166                 :            : 
     167                 :          0 :         hash_key = rte_jhash(m_ent, sizeof(uint64_t) * 2, ze->priv->hash_seed);
     168                 :          0 :         ret = rte_hash_del_key(ze->ct_merge_table, &hash_key);
     169         [ #  # ]:          0 :         if (ret < 0)
     170                 :          0 :                 PMD_DRV_LOG(ERR, "Delete from ct_merge table failed, ret=%d.", ret);
     171                 :          0 : }
     172                 :            : 
     173                 :            : static void
     174                 :          0 : nfp_ct_merge_entry_destroy(struct nfp_ct_merge_entry *m_ent)
     175                 :            : {
     176                 :            :         struct nfp_ct_zone_entry *ze;
     177                 :            : 
     178                 :          0 :         ze = m_ent->ze;
     179                 :          0 :         nfp_ct_merge_table_delete(ze, m_ent);
     180                 :            : 
     181                 :          0 :         rte_free(m_ent->rule.actions);
     182                 :          0 :         rte_free(m_ent->rule.items);
     183         [ #  # ]:          0 :         LIST_REMOVE(m_ent, pre_ct_list);
     184         [ #  # ]:          0 :         LIST_REMOVE(m_ent, post_ct_list);
     185                 :          0 :         rte_free(m_ent);
     186                 :          0 : }
     187                 :            : 
     188                 :            : struct nfp_ct_map_entry *
     189                 :          0 : nfp_ct_map_table_search(struct nfp_flow_priv *priv,
     190                 :            :                 char *hash_data,
     191                 :            :                 uint32_t hash_len)
     192                 :            : {
     193                 :            :         int index;
     194                 :            :         uint32_t hash_key;
     195                 :            :         struct nfp_ct_map_entry *me;
     196                 :            : 
     197                 :          0 :         hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
     198                 :          0 :         index = rte_hash_lookup_data(priv->ct_map_table, &hash_key, (void **)&me);
     199         [ #  # ]:          0 :         if (index < 0) {
     200                 :          0 :                 PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_map table.");
     201                 :          0 :                 return NULL;
     202                 :            :         }
     203                 :            : 
     204                 :          0 :         return me;
     205                 :            : }
     206                 :            : 
     207                 :            : static bool
     208                 :          0 : nfp_ct_map_table_add(struct nfp_flow_priv *priv,
     209                 :            :                 struct nfp_ct_map_entry *me)
     210                 :            : {
     211                 :            :         int ret;
     212                 :            :         uint32_t hash_key;
     213                 :            : 
     214                 :          0 :         hash_key = rte_jhash(me, sizeof(uint64_t), priv->hash_seed);
     215                 :          0 :         ret = rte_hash_add_key_data(priv->ct_map_table, &hash_key, me);
     216         [ #  # ]:          0 :         if (ret != 0) {
     217                 :          0 :                 PMD_DRV_LOG(ERR, "Add to ct_map table failed.");
     218                 :          0 :                 return false;
     219                 :            :         }
     220                 :            : 
     221                 :            :         return true;
     222                 :            : }
     223                 :            : 
     224                 :            : static void
     225                 :          0 : nfp_ct_map_table_delete(struct nfp_flow_priv *priv,
     226                 :            :                 struct nfp_ct_map_entry *me)
     227                 :            : {
     228                 :            :         int ret;
     229                 :            :         uint32_t hash_key;
     230                 :            : 
     231                 :          0 :         hash_key = rte_jhash(me, sizeof(uint64_t), priv->hash_seed);
     232                 :          0 :         ret = rte_hash_del_key(priv->ct_map_table, &hash_key);
     233         [ #  # ]:          0 :         if (ret < 0)
     234                 :          0 :                 PMD_DRV_LOG(ERR, "Delete form ct_map table failed.");
     235                 :          0 : }
     236                 :            : 
     237                 :            : static void
     238                 :            : nfp_ct_map_entry_destroy(struct nfp_ct_map_entry *me)
     239                 :            : {
     240                 :          0 :         rte_free(me);
     241                 :          0 : }
     242                 :            : 
     243                 :            : static void
     244                 :          0 : nfp_ct_flow_item_free_real(void *field,
     245                 :            :                 enum rte_flow_item_type type)
     246                 :            : {
     247         [ #  # ]:          0 :         switch (type) {
     248                 :            :         case RTE_FLOW_ITEM_TYPE_VOID:
     249                 :            :                 break;
     250                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:        /* FALLTHROUGH */
     251                 :            :         case RTE_FLOW_ITEM_TYPE_VLAN:       /* FALLTHROUGH */
     252                 :            :         case RTE_FLOW_ITEM_TYPE_IPV4:       /* FALLTHROUGH */
     253                 :            :         case RTE_FLOW_ITEM_TYPE_IPV6:       /* FALLTHROUGH */
     254                 :            :         case RTE_FLOW_ITEM_TYPE_TCP:        /* FALLTHROUGH */
     255                 :            :         case RTE_FLOW_ITEM_TYPE_UDP:        /* FALLTHROUGH */
     256                 :            :         case RTE_FLOW_ITEM_TYPE_SCTP:       /* FALLTHROUGH */
     257                 :            :         case RTE_FLOW_ITEM_TYPE_VXLAN:      /* FALLTHROUGH */
     258                 :            :         case RTE_FLOW_ITEM_TYPE_GRE:        /* FALLTHROUGH */
     259                 :            :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:    /* FALLTHROUGH */
     260                 :            :         case RTE_FLOW_ITEM_TYPE_GENEVE:
     261                 :          0 :                 rte_free(field);
     262                 :          0 :                 break;
     263                 :            :         default:
     264                 :            :                 break;
     265                 :            :         }
     266                 :          0 : }
     267                 :            : 
     268                 :            : static void
     269                 :          0 : nfp_ct_flow_item_free(struct rte_flow_item *item)
     270                 :            : {
     271         [ #  # ]:          0 :         if (item->spec != NULL)
     272                 :          0 :                 nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->spec, item->type);
     273                 :            : 
     274         [ #  # ]:          0 :         if (item->mask != NULL)
     275                 :          0 :                 nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->mask, item->type);
     276                 :            : 
     277         [ #  # ]:          0 :         if (item->last != NULL)
     278                 :          0 :                 nfp_ct_flow_item_free_real((void *)(ptrdiff_t)item->last, item->type);
     279                 :          0 : }
     280                 :            : 
     281                 :            : static void
     282                 :            : nfp_ct_flow_items_free(struct rte_flow_item *items,
     283                 :            :                 uint8_t item_cnt)
     284                 :            : {
     285                 :            :         uint8_t loop;
     286                 :            : 
     287   [ #  #  #  #  :          0 :         for (loop = 0; loop < item_cnt; ++loop)
             #  #  #  # ]
     288                 :          0 :                 nfp_ct_flow_item_free(items + loop);
     289                 :            : }
     290                 :            : 
     291                 :            : static bool
     292                 :          0 : nfp_flow_item_conf_size_get(enum rte_flow_item_type type,
     293                 :            :                 size_t *size)
     294                 :            : {
     295                 :            :         size_t len = 0;
     296                 :            : 
     297   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
             #  #  #  # ]
     298                 :            :         case RTE_FLOW_ITEM_TYPE_VOID:
     299                 :            :                 break;
     300                 :          0 :         case RTE_FLOW_ITEM_TYPE_ETH:
     301                 :            :                 len = sizeof(struct rte_flow_item_eth);
     302                 :          0 :                 break;
     303                 :          0 :         case RTE_FLOW_ITEM_TYPE_VLAN:
     304                 :            :                 len = sizeof(struct rte_flow_item_vlan);
     305                 :          0 :                 break;
     306                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV4:
     307                 :            :                 len = sizeof(struct rte_flow_item_ipv4);
     308                 :          0 :                 break;
     309                 :          0 :         case RTE_FLOW_ITEM_TYPE_IPV6:
     310                 :            :                 len = sizeof(struct rte_flow_item_ipv6);
     311                 :          0 :                 break;
     312                 :          0 :         case RTE_FLOW_ITEM_TYPE_TCP:
     313                 :            :                 len = sizeof(struct rte_flow_item_tcp);
     314                 :          0 :                 break;
     315                 :          0 :         case RTE_FLOW_ITEM_TYPE_UDP:
     316                 :            :                 len = sizeof(struct rte_flow_item_udp);
     317                 :          0 :                 break;
     318                 :          0 :         case RTE_FLOW_ITEM_TYPE_SCTP:
     319                 :            :                 len = sizeof(struct rte_flow_item_sctp);
     320                 :          0 :                 break;
     321                 :          0 :         case RTE_FLOW_ITEM_TYPE_VXLAN:
     322                 :            :                 len = sizeof(struct rte_flow_item_vxlan);
     323                 :          0 :                 break;
     324                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE:
     325                 :            :                 len = sizeof(struct rte_flow_item_gre);
     326                 :          0 :                 break;
     327                 :          0 :         case RTE_FLOW_ITEM_TYPE_GRE_KEY:
     328                 :            :                 len = sizeof(rte_be32_t);
     329                 :          0 :                 break;
     330                 :          0 :         case RTE_FLOW_ITEM_TYPE_GENEVE:
     331                 :            :                 len = sizeof(struct rte_flow_item_geneve);
     332                 :          0 :                 break;
     333                 :          0 :         default:
     334                 :          0 :                 PMD_DRV_LOG(ERR, "Unsupported item type: %d.", type);
     335                 :          0 :                 *size = 0;
     336                 :          0 :                 return false;
     337                 :            :         }
     338                 :            : 
     339                 :          0 :         *size = len;
     340                 :            : 
     341                 :          0 :         return true;
     342                 :            : }
     343                 :            : 
     344                 :            : static void *
     345                 :          0 : nfp_ct_flow_item_copy_real(const void *src,
     346                 :            :                 enum rte_flow_item_type type)
     347                 :            : {
     348                 :            :         bool ret;
     349                 :            :         void *dst;
     350                 :            :         size_t len;
     351                 :            : 
     352                 :          0 :         ret = nfp_flow_item_conf_size_get(type, &len);
     353         [ #  # ]:          0 :         if (!ret) {
     354                 :          0 :                 PMD_DRV_LOG(ERR, "Get flow item conf size failed.");
     355                 :          0 :                 return NULL;
     356                 :            :         }
     357                 :            : 
     358                 :          0 :         dst = rte_zmalloc("flow_item", len, 0);
     359         [ #  # ]:          0 :         if (dst == NULL) {
     360                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct item failed.");
     361                 :          0 :                 return NULL;
     362                 :            :         }
     363                 :            : 
     364                 :            :         rte_memcpy(dst, src, len);
     365                 :            : 
     366                 :            :         return dst;
     367                 :            : }
     368                 :            : 
     369                 :            : static bool
     370                 :          0 : nfp_ct_flow_item_copy(const struct rte_flow_item *src,
     371                 :            :                 struct rte_flow_item *dst)
     372                 :            : {
     373                 :          0 :         dst->type = src->type;
     374                 :            : 
     375         [ #  # ]:          0 :         if (src->spec != NULL) {
     376                 :          0 :                 dst->spec = nfp_ct_flow_item_copy_real(src->spec, src->type);
     377         [ #  # ]:          0 :                 if (dst->spec == NULL) {
     378                 :          0 :                         PMD_DRV_LOG(ERR, "Copy spec of ct item failed.");
     379                 :          0 :                         goto end;
     380                 :            :                 }
     381                 :            :         }
     382                 :            : 
     383         [ #  # ]:          0 :         if (src->mask != NULL) {
     384                 :          0 :                 dst->mask = nfp_ct_flow_item_copy_real(src->mask, src->type);
     385         [ #  # ]:          0 :                 if (dst->mask == NULL) {
     386                 :          0 :                         PMD_DRV_LOG(ERR, "Copy mask of ct item failed.");
     387                 :          0 :                         goto free_spec;
     388                 :            :                 }
     389                 :            :         }
     390                 :            : 
     391         [ #  # ]:          0 :         if (src->last != NULL) {
     392                 :          0 :                 dst->last = nfp_ct_flow_item_copy_real(src->last, src->type);
     393         [ #  # ]:          0 :                 if (dst->last == NULL) {
     394                 :          0 :                         PMD_DRV_LOG(ERR, "Copy last of ct item failed.");
     395                 :          0 :                         goto free_mask;
     396                 :            :                 }
     397                 :            :         }
     398                 :            : 
     399                 :            :         return true;
     400                 :            : 
     401                 :            : free_mask:
     402                 :          0 :         nfp_ct_flow_item_free_real((void *)(ptrdiff_t)dst->mask, dst->type);
     403                 :          0 : free_spec:
     404                 :          0 :         nfp_ct_flow_item_free_real((void *)(ptrdiff_t)dst->spec, dst->type);
     405                 :            : end:
     406                 :            :         return false;
     407                 :            : }
     408                 :            : 
     409                 :            : static bool
     410                 :          0 : nfp_ct_flow_items_copy(const struct rte_flow_item *src,
     411                 :            :                 struct rte_flow_item *dst,
     412                 :            :                 uint8_t item_cnt)
     413                 :            : {
     414                 :            :         bool ret;
     415                 :            :         uint8_t loop;
     416                 :            : 
     417         [ #  # ]:          0 :         for (loop = 0; loop < item_cnt; ++loop) {
     418                 :          0 :                 ret = nfp_ct_flow_item_copy(src + loop, dst + loop);
     419         [ #  # ]:          0 :                 if (!ret) {
     420                 :          0 :                         PMD_DRV_LOG(ERR, "Copy ct item failed.");
     421                 :            :                         nfp_ct_flow_items_free(dst, loop);
     422                 :            :                         return false;
     423                 :            :                 }
     424                 :            :         }
     425                 :            : 
     426                 :            :         return true;
     427                 :            : }
     428                 :            : 
     429                 :            : static void
     430                 :            : nfp_ct_flow_action_free_real(void *field,
     431                 :            :                 nfp_action_free_fn func)
     432                 :            : {
     433                 :            :         if (func != NULL)
     434                 :          0 :                 func(field);
     435                 :            : 
     436                 :          0 :         rte_free(field);
     437                 :          0 : }
     438                 :            : 
     439                 :            : static void
     440                 :          0 : nfp_ct_flow_action_free_vxlan(void *field)
     441                 :            : {
     442                 :            :         struct vxlan_data *vxlan = field;
     443                 :            : 
     444                 :          0 :         nfp_ct_flow_items_free(vxlan->items, ACTION_VXLAN_ENCAP_ITEMS_NUM);
     445                 :          0 : }
     446                 :            : 
     447                 :            : static void
     448                 :          0 : nfp_ct_flow_action_free_raw(void *field)
     449                 :            : {
     450                 :            :         struct rte_flow_action_raw_encap *raw_encap = field;
     451                 :            : 
     452                 :          0 :         rte_free(raw_encap->data);
     453                 :          0 : }
     454                 :            : 
     455                 :            : static void
     456                 :          0 : nfp_ct_flow_action_free(struct rte_flow_action *action)
     457                 :            : {
     458                 :            :         nfp_action_free_fn func = NULL;
     459                 :            : 
     460         [ #  # ]:          0 :         if (action->conf == NULL)
     461                 :            :                 return;
     462                 :            : 
     463   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
     464                 :            :         case RTE_FLOW_ACTION_TYPE_VOID:           /* FALLTHROUGH */
     465                 :            :         case RTE_FLOW_ACTION_TYPE_DROP:           /* FALLTHROUGH */
     466                 :            :         case RTE_FLOW_ACTION_TYPE_COUNT:          /* FALLTHROUGH */
     467                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP:           /* FALLTHROUGH */
     468                 :            :         case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:    /* FALLTHROUGH */
     469                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:    /* FALLTHROUGH */
     470                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
     471                 :            :                 return;
     472                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:    /* FALLTHROUGH */
     473                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:    /* FALLTHROUGH */
     474                 :            :         case RTE_FLOW_ACTION_TYPE_PORT_ID:        /* FALLTHROUGH */
     475                 :            :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:   /* FALLTHROUGH */
     476                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:   /* FALLTHROUGH */
     477                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:   /* FALLTHROUGH */
     478                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:  /* FALLTHROUGH */
     479                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:  /* FALLTHROUGH */
     480                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:   /* FALLTHROUGH */
     481                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:   /* FALLTHROUGH */
     482                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TTL:        /* FALLTHROUGH */
     483                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:     /* FALLTHROUGH */
     484                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
     485                 :            :                 break;
     486                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
     487                 :            :                 func = nfp_ct_flow_action_free_vxlan;
     488                 :            :                 break;
     489                 :          0 :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
     490                 :            :                 func = nfp_ct_flow_action_free_raw;
     491                 :          0 :                 break;
     492                 :          0 :         default:
     493                 :          0 :                 PMD_DRV_LOG(ERR, "Unsupported action type: %d.", action->type);
     494                 :            :                 break;
     495                 :            :         }
     496                 :            : 
     497                 :          0 :         nfp_ct_flow_action_free_real((void *)(ptrdiff_t)action->conf, func);
     498                 :            : }
     499                 :            : 
     500                 :            : static void
     501                 :            : nfp_ct_flow_actions_free(struct rte_flow_action *actions,
     502                 :            :                 uint8_t action_cnt)
     503                 :            : {
     504                 :            :         uint8_t loop;
     505                 :            : 
     506   [ #  #  #  #  :          0 :         for (loop = 0; loop < action_cnt; ++loop)
                   #  # ]
     507                 :          0 :                 nfp_ct_flow_action_free(actions + loop);
     508                 :            : }
     509                 :            : 
     510                 :            : static void *
     511                 :          0 : nfp_ct_flow_action_copy_real(const void *src,
     512                 :            :                 size_t len,
     513                 :            :                 nfp_action_copy_fn func)
     514                 :            : {
     515                 :            :         bool ret;
     516                 :            :         void *dst;
     517                 :            : 
     518                 :          0 :         dst = rte_zmalloc("flow_action", len, 0);
     519         [ #  # ]:          0 :         if (dst == NULL) {
     520                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct action failed.");
     521                 :          0 :                 return NULL;
     522                 :            :         }
     523                 :            : 
     524         [ #  # ]:          0 :         if (func != NULL) {
     525                 :          0 :                 ret = func(src, dst);
     526         [ #  # ]:          0 :                 if (!ret) {
     527                 :          0 :                         PMD_DRV_LOG(ERR, "Copy ct action failed.");
     528                 :          0 :                         return NULL;
     529                 :            :                 }
     530                 :            : 
     531                 :            :                 return dst;
     532                 :            :         }
     533                 :            : 
     534                 :            :         rte_memcpy(dst, src, len);
     535                 :            : 
     536                 :            :         return dst;
     537                 :            : }
     538                 :            : 
     539                 :            : static bool
     540                 :          0 : nfp_ct_flow_action_copy_vxlan(const void *src,
     541                 :            :                 void *dst)
     542                 :            : {
     543                 :            :         struct vxlan_data *vxlan_dst = dst;
     544                 :            :         const struct vxlan_data *vxlan_src = src;
     545                 :            : 
     546                 :          0 :         vxlan_dst->conf.definition = vxlan_dst->items;
     547                 :          0 :         return nfp_ct_flow_items_copy(vxlan_src->items, vxlan_dst->items,
     548                 :            :                         ACTION_VXLAN_ENCAP_ITEMS_NUM);
     549                 :            : }
     550                 :            : 
     551                 :            : static bool
     552                 :          0 : nfp_ct_flow_action_copy_raw(const void *src,
     553                 :            :                 void *dst)
     554                 :            : {
     555                 :            :         struct rte_flow_action_raw_encap *raw_dst = dst;
     556                 :            :         const struct rte_flow_action_raw_encap *raw_src = src;
     557                 :            : 
     558                 :          0 :         raw_dst->size = raw_src->size;
     559                 :          0 :         raw_dst->data = nfp_ct_flow_action_copy_real(raw_src->data,
     560                 :            :                         raw_src->size, NULL);
     561         [ #  # ]:          0 :         if (raw_dst->data == NULL) {
     562                 :          0 :                 PMD_DRV_LOG(ERR, "Copy ct action process failed.");
     563                 :          0 :                 return false;
     564                 :            :         }
     565                 :            : 
     566                 :            :         return true;
     567                 :            : }
     568                 :            : 
     569                 :            : static bool
     570                 :          0 : nfp_ct_flow_action_copy(const struct rte_flow_action *src,
     571                 :            :                 struct rte_flow_action *dst)
     572                 :            : {
     573                 :            :         size_t len;
     574                 :            :         nfp_action_copy_fn func = NULL;
     575                 :            : 
     576                 :          0 :         dst->type = src->type;
     577                 :            : 
     578         [ #  # ]:          0 :         if (src->conf == NULL)
     579                 :            :                 return true;
     580                 :            : 
     581   [ #  #  #  #  :          0 :         switch (src->type) {
          #  #  #  #  #  
                #  #  # ]
     582                 :            :         case RTE_FLOW_ACTION_TYPE_VOID:         /* FALLTHROUGH */
     583                 :            :         case RTE_FLOW_ACTION_TYPE_DROP:         /* FALLTHROUGH */
     584                 :            :         case RTE_FLOW_ACTION_TYPE_COUNT:        /* FALLTHROUGH */
     585                 :            :         case RTE_FLOW_ACTION_TYPE_JUMP:         /* FALLTHROUGH */
     586                 :            :         case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:  /* FALLTHROUGH */
     587                 :            :         case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:  /* FALLTHROUGH */
     588                 :            :         case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
     589                 :            :                 return true;
     590                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:  /* FALLTHROUGH */
     591                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
     592                 :            :                 len = sizeof(struct rte_flow_action_set_mac);
     593                 :            :                 break;
     594                 :          0 :         case RTE_FLOW_ACTION_TYPE_PORT_ID:
     595                 :            :                 len = sizeof(struct rte_flow_action_port_id);
     596                 :          0 :                 break;
     597                 :          0 :         case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
     598                 :            :                 len = sizeof(struct rte_flow_action_of_push_vlan);
     599                 :          0 :                 break;
     600                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:  /* FALLTHROUGH */
     601                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
     602                 :            :                 len = sizeof(struct rte_flow_action_set_ipv4);
     603                 :          0 :                 break;
     604                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:  /* FALLTHROUGH */
     605                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
     606                 :            :                 len = sizeof(struct rte_flow_action_set_dscp);
     607                 :          0 :                 break;
     608                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:  /* FALLTHROUGH */
     609                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
     610                 :            :                 len = sizeof(struct rte_flow_action_set_ipv6);
     611                 :          0 :                 break;
     612                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_TTL:
     613                 :            :                 len = sizeof(struct rte_flow_action_set_ttl);
     614                 :          0 :                 break;
     615                 :          0 :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:  /* FALLTHROUGH */
     616                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
     617                 :            :                 len = sizeof(struct rte_flow_action_set_tp);
     618                 :          0 :                 break;
     619                 :          0 :         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
     620                 :            :                 len = sizeof(struct vxlan_data);
     621                 :            :                 func = nfp_ct_flow_action_copy_vxlan;
     622                 :          0 :                 break;
     623                 :          0 :         case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
     624                 :            :                 len = sizeof(struct rte_flow_action_raw_encap);
     625                 :            :                 func = nfp_ct_flow_action_copy_raw;
     626                 :          0 :                 break;
     627                 :          0 :         default:
     628                 :          0 :                 PMD_DRV_LOG(DEBUG, "Unsupported action type: %d.", src->type);
     629                 :          0 :                 return false;
     630                 :            :         }
     631                 :            : 
     632                 :          0 :         dst->conf = nfp_ct_flow_action_copy_real(src->conf, len, func);
     633         [ #  # ]:          0 :         if (dst->conf == NULL) {
     634                 :          0 :                 PMD_DRV_LOG(DEBUG, "Copy ct action process failed.");
     635                 :          0 :                 return false;
     636                 :            :         }
     637                 :            : 
     638                 :            :         return true;
     639                 :            : }
     640                 :            : 
     641                 :            : static bool
     642                 :          0 : nfp_ct_flow_actions_copy(const struct rte_flow_action *src,
     643                 :            :                 struct rte_flow_action *dst,
     644                 :            :                 uint8_t action_cnt)
     645                 :            : {
     646                 :            :         bool ret;
     647                 :            :         uint8_t loop;
     648                 :            : 
     649         [ #  # ]:          0 :         for (loop = 0; loop < action_cnt; ++loop) {
     650                 :          0 :                 ret = nfp_ct_flow_action_copy(src + loop, dst + loop);
     651         [ #  # ]:          0 :                 if (!ret) {
     652                 :          0 :                         PMD_DRV_LOG(DEBUG, "Copy ct action failed.");
     653                 :            :                         nfp_ct_flow_actions_free(dst, loop);
     654                 :            :                         return false;
     655                 :            :                 }
     656                 :            :         }
     657                 :            : 
     658                 :            :         return true;
     659                 :            : }
     660                 :            : 
     661                 :            : static struct nfp_ct_flow_entry *
     662                 :          0 : nfp_ct_flow_entry_get(struct nfp_ct_zone_entry *ze,
     663                 :            :                 struct rte_eth_dev *dev,
     664                 :            :                 const struct rte_flow_item items[],
     665                 :            :                 const struct rte_flow_action actions[],
     666                 :            :                 uint64_t cookie)
     667                 :            : {
     668                 :            :         bool ret;
     669                 :            :         uint8_t loop;
     670                 :            :         uint8_t item_cnt = 1;      /* The RTE_FLOW_ITEM_TYPE_END */
     671                 :            :         uint8_t action_cnt = 1;    /* The RTE_FLOW_ACTION_TYPE_END */
     672                 :            :         struct nfp_flow_priv *priv;
     673                 :            :         struct nfp_ct_map_entry *me;
     674                 :            :         struct nfp_ct_flow_entry *fe;
     675                 :            :         struct nfp_flower_representor *repr;
     676                 :            : 
     677                 :          0 :         fe = rte_zmalloc("ct_flow_entry", sizeof(*fe), 0);
     678         [ #  # ]:          0 :         if (fe == NULL) {
     679                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct_flow entry.");
     680                 :          0 :                 return NULL;
     681                 :            :         }
     682                 :            : 
     683                 :          0 :         fe->ze = ze;
     684                 :          0 :         fe->dev = dev;
     685                 :          0 :         fe->cookie = cookie;
     686                 :          0 :         LIST_INIT(&fe->children);
     687                 :            : 
     688         [ #  # ]:          0 :         for (loop = 0; (items + loop)->type != RTE_FLOW_ITEM_TYPE_END; loop++)
     689                 :          0 :                 item_cnt++;
     690         [ #  # ]:          0 :         for (loop = 0; (actions + loop)->type != RTE_FLOW_ACTION_TYPE_END; loop++)
     691                 :          0 :                 action_cnt++;
     692                 :            : 
     693                 :          0 :         fe->rule.items = rte_zmalloc("ct_flow_item",
     694                 :            :                         sizeof(struct rte_flow_item) * item_cnt, 0);
     695         [ #  # ]:          0 :         if (fe->rule.items == NULL) {
     696                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct flow items.");
     697                 :          0 :                 goto free_flow_entry;
     698                 :            :         }
     699                 :            : 
     700                 :          0 :         fe->rule.actions = rte_zmalloc("ct_flow_action",
     701                 :            :                         sizeof(struct rte_flow_action) * action_cnt, 0);
     702         [ #  # ]:          0 :         if (fe->rule.actions == NULL) {
     703                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct flow actions.");
     704                 :          0 :                 goto free_flow_item;
     705                 :            :         }
     706                 :            : 
     707                 :            :         /* Deep copy of items */
     708                 :          0 :         ret = nfp_ct_flow_items_copy(items, fe->rule.items, item_cnt);
     709         [ #  # ]:          0 :         if (!ret) {
     710                 :          0 :                 PMD_DRV_LOG(ERR, "Could not deep copy ct flow items.");
     711                 :          0 :                 goto free_flow_action;
     712                 :            :         }
     713                 :            : 
     714                 :            :         /* Deep copy of actions */
     715                 :          0 :         ret = nfp_ct_flow_actions_copy(actions, fe->rule.actions, action_cnt);
     716         [ #  # ]:          0 :         if (!ret) {
     717                 :          0 :                 PMD_DRV_LOG(ERR, "Could not deep copy ct flow actions.");
     718                 :          0 :                 goto free_copied_items;
     719                 :            :         }
     720                 :            : 
     721                 :          0 :         fe->rule.items_cnt = item_cnt;
     722                 :          0 :         fe->rule.actions_cnt = action_cnt;
     723                 :            : 
     724                 :            :         /* Now add a ct map entry */
     725                 :          0 :         me = rte_zmalloc("ct_map_entry", sizeof(*me), 0);
     726         [ #  # ]:          0 :         if (me == NULL) {
     727                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct map entry failed.");
     728                 :          0 :                 goto free_copied_actions;
     729                 :            :         }
     730                 :            : 
     731                 :          0 :         me->cookie = fe->cookie;
     732                 :          0 :         me->fe = fe;
     733                 :            : 
     734                 :          0 :         repr = dev->data->dev_private;
     735                 :          0 :         priv = repr->app_fw_flower->flow_priv;
     736                 :          0 :         ret = nfp_ct_map_table_add(priv, me);
     737         [ #  # ]:          0 :         if (!ret) {
     738                 :          0 :                 PMD_DRV_LOG(ERR, "Add into ct map table failed.");
     739                 :          0 :                 goto free_map_entry;
     740                 :            :         }
     741                 :            : 
     742                 :            :         return fe;
     743                 :            : 
     744                 :            : free_map_entry:
     745                 :            :         nfp_ct_map_entry_destroy(me);
     746                 :          0 : free_copied_actions:
     747                 :          0 :         nfp_ct_flow_actions_free(fe->rule.actions, action_cnt);
     748                 :          0 : free_copied_items:
     749                 :          0 :         nfp_ct_flow_items_free(fe->rule.items, item_cnt);
     750                 :          0 : free_flow_action:
     751                 :          0 :         rte_free(fe->rule.actions);
     752                 :          0 : free_flow_item:
     753                 :          0 :         rte_free(fe->rule.items);
     754                 :          0 : free_flow_entry:
     755                 :          0 :         rte_free(fe);
     756                 :            : 
     757                 :          0 :         return NULL;
     758                 :            : }
     759                 :            : 
     760                 :            : static void
     761                 :          0 : nfp_flow_children_merge_free(struct nfp_ct_flow_entry *fe)
     762                 :            : {
     763                 :            :         struct nfp_ct_merge_entry *m_ent;
     764                 :            : 
     765      [ #  #  # ]:          0 :         switch (fe->type) {
     766                 :          0 :         case CT_TYPE_PRE_CT:
     767         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, pre_ct_list)
     768                 :          0 :                         nfp_ct_merge_entry_destroy(m_ent);
     769                 :            :                 break;
     770                 :          0 :         case CT_TYPE_POST_CT:
     771         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, post_ct_list)
     772                 :          0 :                         nfp_ct_merge_entry_destroy(m_ent);
     773                 :            :                 break;
     774                 :            :         default:
     775                 :            :                 break;
     776                 :            :         }
     777                 :          0 : }
     778                 :            : 
     779                 :            : static void
     780                 :          0 : nfp_ct_flow_entry_destroy_partly(struct nfp_ct_flow_entry *fe)
     781                 :            : {
     782                 :            :         struct nfp_ct_map_entry *me;
     783                 :            : 
     784         [ #  # ]:          0 :         if (!LIST_EMPTY(&fe->children))
     785                 :          0 :                 nfp_flow_children_merge_free(fe);
     786                 :            : 
     787                 :          0 :         me = nfp_ct_map_table_search(fe->ze->priv, (char *)&fe->cookie, sizeof(uint64_t));
     788         [ #  # ]:          0 :         if (me != NULL) {
     789                 :          0 :                 nfp_ct_map_table_delete(fe->ze->priv, me);
     790                 :            :                 nfp_ct_map_entry_destroy(me);
     791                 :            :         }
     792                 :            : 
     793                 :          0 :         nfp_ct_flow_actions_free(fe->rule.actions, fe->rule.actions_cnt);
     794                 :          0 :         nfp_ct_flow_items_free(fe->rule.items, fe->rule.items_cnt);
     795                 :          0 :         rte_free(fe->rule.actions);
     796                 :          0 :         rte_free(fe->rule.items);
     797                 :          0 :         rte_free(fe);
     798                 :          0 : }
     799                 :            : 
     800                 :            : static void
     801                 :          0 : nfp_ct_flow_entry_destroy(struct nfp_ct_flow_entry *fe)
     802                 :            : {
     803         [ #  # ]:          0 :         LIST_REMOVE(fe, pre_ct_list);
     804         [ #  # ]:          0 :         LIST_REMOVE(fe, post_ct_list);
     805                 :            : 
     806                 :          0 :         nfp_ct_flow_entry_destroy_partly(fe);
     807                 :          0 : }
     808                 :            : 
     809                 :            : static struct nfp_ct_zone_entry *
     810                 :          0 : nfp_ct_zone_table_search(struct nfp_flow_priv *priv,
     811                 :            :                 char *hash_data,
     812                 :            :                 uint32_t hash_len)
     813                 :            : {
     814                 :            :         int index;
     815                 :            :         uint32_t hash_key;
     816                 :            :         struct nfp_ct_zone_entry *ze;
     817                 :            : 
     818                 :          0 :         hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
     819                 :          0 :         index = rte_hash_lookup_data(priv->ct_zone_table, &hash_key, (void **)&ze);
     820         [ #  # ]:          0 :         if (index < 0) {
     821                 :          0 :                 PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_zone table.");
     822                 :          0 :                 return NULL;
     823                 :            :         }
     824                 :            : 
     825                 :          0 :         return ze;
     826                 :            : }
     827                 :            : 
     828                 :            : static bool
     829                 :          0 : nfp_ct_zone_table_add(struct nfp_flow_priv *priv,
     830                 :            :                 struct nfp_ct_zone_entry *ze)
     831                 :            : {
     832                 :            :         int ret;
     833                 :            :         uint32_t hash_key;
     834                 :            : 
     835                 :          0 :         hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
     836                 :          0 :         ret = rte_hash_add_key_data(priv->ct_zone_table, &hash_key, ze);
     837         [ #  # ]:          0 :         if (ret != 0) {
     838                 :          0 :                 PMD_DRV_LOG(ERR, "Add to the ct_zone table failed.");
     839                 :          0 :                 return false;
     840                 :            :         }
     841                 :            : 
     842                 :            :         return true;
     843                 :            : }
     844                 :            : 
     845                 :            : static void
     846                 :          0 : nfp_ct_zone_table_delete(struct nfp_flow_priv *priv,
     847                 :            :                 struct nfp_ct_zone_entry *ze)
     848                 :            : {
     849                 :            :         int ret;
     850                 :            :         uint32_t hash_key;
     851                 :            : 
     852                 :          0 :         hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
     853                 :          0 :         ret = rte_hash_del_key(priv->ct_zone_table, &hash_key);
     854         [ #  # ]:          0 :         if (ret < 0)
     855                 :          0 :                 PMD_DRV_LOG(ERR, "Delete from the ct_zone table failed.");
     856                 :          0 : }
     857                 :            : 
     858                 :            : static bool
     859                 :          0 : nfp_ct_zone_entry_init(struct nfp_ct_zone_entry *ze,
     860                 :            :                 struct nfp_flow_priv *priv,
     861                 :            :                 uint32_t zone,
     862                 :            :                 bool wildcard)
     863                 :            : {
     864                 :            :         char hash_name[RTE_HASH_NAMESIZE];
     865                 :          0 :         struct rte_hash_parameters ct_merge_hash_params = {
     866                 :            :                 .entries    = 1000,
     867                 :            :                 .hash_func  = rte_jhash,
     868                 :          0 :                 .socket_id  = rte_socket_id(),
     869                 :            :                 .key_len    = sizeof(uint32_t),
     870                 :            :                 .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
     871                 :            :         };
     872                 :            : 
     873         [ #  # ]:          0 :         if (wildcard) {
     874                 :          0 :                 ct_merge_hash_params.name = "ct_wc_merge_table";
     875                 :            :         } else {
     876                 :          0 :                 snprintf(hash_name, sizeof(hash_name), "ct_%d_merge_table", ze->zone);
     877                 :          0 :                 ct_merge_hash_params.name = hash_name;
     878                 :            :         }
     879                 :            : 
     880                 :          0 :         ct_merge_hash_params.hash_func_init_val = priv->hash_seed;
     881                 :          0 :         ze->ct_merge_table = rte_hash_create(&ct_merge_hash_params);
     882         [ #  # ]:          0 :         if (ze->ct_merge_table == NULL) {
     883                 :          0 :                 PMD_DRV_LOG(ERR, "CT merge table creation failed.");
     884                 :          0 :                 return false;
     885                 :            :         }
     886                 :            : 
     887                 :          0 :         ze->zone = zone;
     888                 :          0 :         ze->priv = priv;
     889                 :          0 :         LIST_INIT(&ze->pre_ct_list);
     890                 :          0 :         LIST_INIT(&ze->post_ct_list);
     891                 :            : 
     892                 :          0 :         return true;
     893                 :            : }
     894                 :            : 
     895                 :            : static void
     896                 :          0 : nfp_ct_zone_entry_destroy(struct nfp_ct_zone_entry *ze)
     897                 :            : {
     898                 :            :         struct nfp_ct_flow_entry *fe;
     899                 :            : 
     900         [ #  # ]:          0 :         if (ze == NULL)
     901                 :            :                 return;
     902                 :            : 
     903                 :          0 :         rte_hash_free(ze->ct_merge_table);
     904                 :            : 
     905         [ #  # ]:          0 :         LIST_FOREACH(fe, &ze->pre_ct_list, pre_ct_list)
     906                 :          0 :                 nfp_ct_flow_entry_destroy(fe);
     907                 :            : 
     908         [ #  # ]:          0 :         LIST_FOREACH(fe, &ze->post_ct_list, post_ct_list)
     909                 :          0 :                 nfp_ct_flow_entry_destroy(fe);
     910                 :            : 
     911                 :          0 :         rte_free(ze);
     912                 :            : }
     913                 :            : 
     914                 :            : static struct nfp_ct_zone_entry *
     915                 :          0 : nfp_ct_zone_entry_get(struct nfp_flow_priv *priv,
     916                 :            :                 uint32_t zone,
     917                 :            :                 bool wildcard)
     918                 :            : {
     919                 :            :         bool is_ok;
     920                 :            :         struct nfp_ct_zone_entry *ze;
     921                 :            : 
     922         [ #  # ]:          0 :         if (wildcard) {
     923         [ #  # ]:          0 :                 if (priv->ct_zone_wc != NULL)
     924                 :            :                         return priv->ct_zone_wc;
     925                 :            : 
     926                 :          0 :                 ze = rte_zmalloc("ct_zone_wc", sizeof(*ze), 0);
     927         [ #  # ]:          0 :                 if (ze == NULL) {
     928                 :          0 :                         PMD_DRV_LOG(ERR, "Could not alloc ct_zone_wc entry.");
     929                 :          0 :                         return NULL;
     930                 :            :                 }
     931                 :            : 
     932                 :          0 :                 is_ok = nfp_ct_zone_entry_init(ze, priv, zone, true);
     933         [ #  # ]:          0 :                 if (!is_ok) {
     934                 :          0 :                         PMD_DRV_LOG(ERR, "Init ct zone wc entry failed.");
     935                 :          0 :                         goto free_ct_zone_entry;
     936                 :            :                 }
     937                 :            : 
     938                 :          0 :                 priv->ct_zone_wc = ze;
     939                 :            :         } else {
     940                 :          0 :                 ze = nfp_ct_zone_table_search(priv, (char *)&zone, sizeof(uint32_t));
     941         [ #  # ]:          0 :                 if (ze != NULL)
     942                 :            :                         return ze;
     943                 :            : 
     944                 :          0 :                 ze = rte_zmalloc("ct_zone_entry", sizeof(*ze), 0);
     945         [ #  # ]:          0 :                 if (ze == NULL) {
     946                 :          0 :                         PMD_DRV_LOG(ERR, "Could not alloc ct_zone entry.");
     947                 :          0 :                         return NULL;
     948                 :            :                 }
     949                 :            : 
     950                 :          0 :                 is_ok = nfp_ct_zone_entry_init(ze, priv, zone, false);
     951         [ #  # ]:          0 :                 if (!is_ok) {
     952                 :          0 :                         PMD_DRV_LOG(ERR, "Init ct zone entry failed.");
     953                 :          0 :                         goto free_ct_zone_entry;
     954                 :            :                 }
     955                 :            : 
     956                 :          0 :                 is_ok = nfp_ct_zone_table_add(priv, ze);
     957         [ #  # ]:          0 :                 if (!is_ok) {
     958                 :          0 :                         PMD_DRV_LOG(ERR, "Add into ct zone table failed.");
     959                 :          0 :                         goto free_ct_zone_entry;
     960                 :            :                 }
     961                 :            :         }
     962                 :            : 
     963                 :            :         return ze;
     964                 :            : 
     965                 :          0 : free_ct_zone_entry:
     966                 :          0 :         nfp_ct_zone_entry_destroy(ze);
     967                 :            : 
     968                 :          0 :         return NULL;
     969                 :            : }
     970                 :            : 
     971                 :            : static void
     972                 :          0 : nfp_ct_zone_entry_free(struct nfp_ct_zone_entry *ze,
     973                 :            :                 bool wildcard)
     974                 :            : {
     975   [ #  #  #  # ]:          0 :         if (LIST_EMPTY(&ze->pre_ct_list) && LIST_EMPTY(&ze->post_ct_list)) {
     976         [ #  # ]:          0 :                 if (!wildcard)
     977                 :          0 :                         nfp_ct_zone_table_delete(ze->priv, ze);
     978                 :            : 
     979                 :          0 :                 nfp_ct_zone_entry_destroy(ze);
     980                 :            :         }
     981                 :          0 : }
     982                 :            : 
     983                 :            : static int
     984                 :          0 : nfp_ct_offload_add(struct rte_eth_dev *dev,
     985                 :            :                 struct nfp_ct_merge_entry *merge_entry)
     986                 :            : {
     987                 :            :         int ret;
     988                 :            :         uint64_t cookie;
     989                 :            :         struct rte_flow *nfp_flow;
     990                 :            :         struct nfp_flow_priv *priv;
     991                 :            :         const struct rte_flow_item *items;
     992                 :            :         struct nfp_flower_representor *repr;
     993                 :            :         const struct rte_flow_action *actions;
     994                 :            : 
     995                 :          0 :         cookie = rte_rand();
     996                 :          0 :         items = merge_entry->rule.items;
     997                 :          0 :         actions = merge_entry->rule.actions;
     998                 :          0 :         nfp_flow = nfp_flow_process(dev, items, actions, false, cookie, true, true);
     999         [ #  # ]:          0 :         if (nfp_flow == NULL) {
    1000                 :          0 :                 PMD_DRV_LOG(ERR, "Process the merged flow rule failed.");
    1001                 :          0 :                 return -EINVAL;
    1002                 :            :         }
    1003                 :            : 
    1004         [ #  # ]:          0 :         merge_entry->ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id);
    1005                 :            : 
    1006                 :            :         /* Add the flow to hardware */
    1007                 :          0 :         repr = dev->data->dev_private;
    1008                 :          0 :         priv = repr->app_fw_flower->flow_priv;
    1009                 :          0 :         ret = nfp_flower_cmsg_flow_add(repr->app_fw_flower, nfp_flow);
    1010         [ #  # ]:          0 :         if (ret != 0) {
    1011                 :          0 :                 PMD_DRV_LOG(ERR, "Add the merged flow to firmware failed.");
    1012                 :          0 :                 goto flow_teardown;
    1013                 :            :         }
    1014                 :            : 
    1015                 :            :         /* Add the flow to flow hash table */
    1016                 :          0 :         ret = nfp_flow_table_add_merge(priv, nfp_flow);
    1017         [ #  # ]:          0 :         if (ret != 0) {
    1018                 :          0 :                 PMD_DRV_LOG(ERR, "Add the merged flow to flow table failed.");
    1019                 :          0 :                 goto flow_teardown;
    1020                 :            :         }
    1021                 :            : 
    1022                 :          0 :         merge_entry->compiled_rule = nfp_flow;
    1023                 :            : 
    1024                 :          0 :         return 0;
    1025                 :            : 
    1026                 :          0 : flow_teardown:
    1027                 :          0 :         nfp_flow_teardown(repr->app_fw_flower, nfp_flow, false);
    1028                 :          0 :         nfp_flow_free(nfp_flow);
    1029                 :            : 
    1030                 :          0 :         return ret;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : int
    1034                 :          0 : nfp_ct_offload_del(struct rte_eth_dev *dev,
    1035                 :            :                 struct nfp_ct_map_entry *me,
    1036                 :            :                 struct rte_flow_error *error)
    1037                 :            : {
    1038                 :            :         int ret;
    1039                 :            :         struct nfp_ct_flow_entry *fe;
    1040                 :            :         struct nfp_ct_merge_entry *m_ent;
    1041                 :            : 
    1042                 :          0 :         fe = me->fe;
    1043                 :            : 
    1044         [ #  # ]:          0 :         if (fe->type == CT_TYPE_PRE_CT) {
    1045         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, pre_ct_list) {
    1046         [ #  # ]:          0 :                         if (m_ent->compiled_rule != NULL) {
    1047                 :          0 :                                 ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
    1048         [ #  # ]:          0 :                                 if (ret != 0) {
    1049                 :          0 :                                         PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item.");
    1050                 :          0 :                                         return -EINVAL;
    1051                 :            :                                 }
    1052                 :          0 :                                 m_ent->compiled_rule = NULL;
    1053                 :            :                         }
    1054                 :            : 
    1055                 :          0 :                         m_ent->pre_ct_parent = NULL;
    1056         [ #  # ]:          0 :                         LIST_REMOVE(m_ent, pre_ct_list);
    1057         [ #  # ]:          0 :                         if (m_ent->post_ct_parent == NULL)
    1058                 :          0 :                                 nfp_ct_merge_entry_destroy(m_ent);
    1059                 :            :                 }
    1060                 :            :         } else {
    1061         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, post_ct_list) {
    1062         [ #  # ]:          0 :                         if (m_ent->compiled_rule != NULL) {
    1063                 :          0 :                                 ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
    1064         [ #  # ]:          0 :                                 if (ret != 0) {
    1065                 :          0 :                                         PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item.");
    1066                 :          0 :                                         return -EINVAL;
    1067                 :            :                                 }
    1068                 :          0 :                                 m_ent->compiled_rule = NULL;
    1069                 :            :                         }
    1070                 :            : 
    1071                 :          0 :                         m_ent->post_ct_parent = NULL;
    1072         [ #  # ]:          0 :                         LIST_REMOVE(m_ent, post_ct_list);
    1073         [ #  # ]:          0 :                         if (m_ent->pre_ct_parent == NULL)
    1074                 :          0 :                                 nfp_ct_merge_entry_destroy(m_ent);
    1075                 :            :                 }
    1076                 :            :         }
    1077                 :            : 
    1078                 :          0 :         nfp_ct_flow_entry_destroy_partly(fe);
    1079                 :            : 
    1080                 :          0 :         return 0;
    1081                 :            : }
    1082                 :            : 
    1083                 :            : static inline bool
    1084                 :          0 : is_item_check_pass(const struct rte_flow_item *item1,
    1085                 :            :                 const struct rte_flow_item *item2,
    1086                 :            :                 uint8_t *cnt_same)
    1087                 :            : {
    1088                 :            :         bool pass;
    1089                 :            :         uint32_t i;
    1090                 :            :         size_t size;
    1091                 :          0 :         const char *key1 = item1->spec;
    1092                 :          0 :         const char *key2 = item2->spec;
    1093                 :          0 :         const char *mask1 = item1->mask;
    1094                 :          0 :         const char *mask2 = item2->mask;
    1095                 :            : 
    1096         [ #  # ]:          0 :         if (item1->type != item2->type)
    1097                 :            :                 return true;
    1098                 :            : 
    1099                 :          0 :         pass = nfp_flow_item_conf_size_get(item1->type, &size);
    1100         [ #  # ]:          0 :         if (!pass)
    1101                 :            :                 return false;
    1102                 :            : 
    1103         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1104         [ #  # ]:          0 :                 if ((key1[i] & mask1[i] & mask2[i]) ^ (key2[i] & mask1[i] & mask2[i]))
    1105                 :            :                         return false;
    1106                 :            :         }
    1107                 :            : 
    1108                 :          0 :         *cnt_same = *cnt_same + 1;
    1109                 :            : 
    1110                 :          0 :         return true;
    1111                 :            : }
    1112                 :            : 
    1113                 :            : static bool
    1114                 :          0 : nfp_ct_merge_items_check(struct rte_flow_item *items1,
    1115                 :            :                 struct rte_flow_item *items2,
    1116                 :            :                 uint8_t *cnt_same)
    1117                 :            : {
    1118                 :            :         bool pass;
    1119                 :            :         bool is_tun_flow_1;
    1120                 :            :         bool is_tun_flow_2;
    1121                 :            :         const struct rte_flow_item *item1;
    1122                 :            :         const struct rte_flow_item *item2;
    1123                 :          0 :         const struct rte_flow_item *inner_item1 = NULL;
    1124                 :          0 :         const struct rte_flow_item *inner_item2 = NULL;
    1125                 :            : 
    1126                 :          0 :         is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner_item1);
    1127                 :          0 :         is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner_item2);
    1128                 :            : 
    1129         [ #  # ]:          0 :         if (is_tun_flow_1) {
    1130         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1131                 :            :                         /* Outer layer */
    1132         [ #  # ]:          0 :                         for (item1 = items1; item1 != inner_item1; item1++) {
    1133         [ #  # ]:          0 :                                 for (item2 = items2; item2 != inner_item2; item2++) {
    1134                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1135         [ #  # ]:          0 :                                         if (!pass)
    1136                 :            :                                                 return false;
    1137                 :            :                                 }
    1138                 :            :                         }
    1139                 :            :                         /* Inner layer */
    1140         [ #  # ]:          0 :                         for (item1 = inner_item1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1141         [ #  # ]:          0 :                                 for (item2 = inner_item2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1142                 :          0 :                                                 item2++) {
    1143                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1144         [ #  # ]:          0 :                                         if (!pass)
    1145                 :            :                                                 return false;
    1146                 :            :                                 }
    1147                 :            :                         }
    1148                 :            :                 } else {
    1149         [ #  # ]:          0 :                         for (item1 = items1; item1 != inner_item1; item1++) {
    1150         [ #  # ]:          0 :                                 for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1151                 :          0 :                                                 item2++) {
    1152                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1153         [ #  # ]:          0 :                                         if (!pass)
    1154                 :            :                                                 return false;
    1155                 :            :                                 }
    1156                 :            :                         }
    1157                 :            :                 }
    1158                 :            :         } else {
    1159         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1160         [ #  # ]:          0 :                         for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1161         [ #  # ]:          0 :                                 for (item2 = items2; item2 != inner_item2; item2++) {
    1162                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1163         [ #  # ]:          0 :                                         if (!pass)
    1164                 :            :                                                 return false;
    1165                 :            :                                 }
    1166                 :            :                         }
    1167                 :            :                 } else {
    1168         [ #  # ]:          0 :                         for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1169         [ #  # ]:          0 :                                 for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1170                 :          0 :                                                 item2++) {
    1171                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1172         [ #  # ]:          0 :                                         if (!pass)
    1173                 :            :                                                 return false;
    1174                 :            :                                 }
    1175                 :            :                         }
    1176                 :            :                 }
    1177                 :            :         }
    1178                 :            : 
    1179                 :            :         return true;
    1180                 :            : }
    1181                 :            : 
    1182                 :            : static inline bool
    1183                 :            : is_action_pattern_check_pass(struct rte_flow_item *items,
    1184                 :            :                 enum rte_flow_item_type type)
    1185                 :            : {
    1186                 :            :         struct rte_flow_item *item;
    1187                 :            : 
    1188   [ #  #  #  #  :          0 :         for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
          #  #  #  #  #  
                #  #  # ]
    1189   [ #  #  #  #  :          0 :                 if (item->type == type)
          #  #  #  #  #  
                #  #  # ]
    1190                 :            :                         return false;
    1191                 :            :         }
    1192                 :            : 
    1193                 :            :         return true;
    1194                 :            : }
    1195                 :            : 
    1196                 :            : static bool
    1197                 :          0 : nfp_ct_merge_action_check(struct rte_flow_action *action,
    1198                 :            :                 struct rte_flow_item *items)
    1199                 :            : {
    1200                 :            :         bool pass = true;
    1201                 :            : 
    1202   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
    1203                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:    /* FALLTHROUGH */
    1204                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    1205                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_ETH);
    1206                 :            :                 break;
    1207                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:   /* FALLTHROUGH */
    1208                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:   /* FALLTHROUGH */
    1209                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    1210                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV4);
    1211                 :            :                 break;
    1212                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:   /* FALLTHROUGH */
    1213                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:   /* FALLTHROUGH */
    1214                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    1215                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV6);
    1216                 :            :                 break;
    1217                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:    /* FALLTHROUGH */
    1218                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    1219                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_UDP);
    1220                 :          0 :                 pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_TCP);
    1221                 :          0 :                 pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_SCTP);
    1222                 :          0 :                 break;
    1223                 :            :         default:
    1224                 :            :                 break;
    1225                 :            :         }
    1226                 :            : 
    1227                 :          0 :         return pass;
    1228                 :            : }
    1229                 :            : 
    1230                 :            : static bool
    1231                 :          0 : nfp_ct_merge_actions_check(struct rte_flow_action *actions,
    1232                 :            :                 struct rte_flow_item *items,
    1233                 :            :                 uint8_t *cnt_same)
    1234                 :            : {
    1235                 :            :         bool pass = true;
    1236                 :            :         struct rte_flow_action *action;
    1237                 :            : 
    1238         [ #  # ]:          0 :         for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1239      [ #  #  # ]:          0 :                 switch (action->type) {
    1240                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:    /* FALLTHROUGH */
    1241                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:    /* FALLTHROUGH */
    1242                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:   /* FALLTHROUGH */
    1243                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:   /* FALLTHROUGH */
    1244                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:  /* FALLTHROUGH */
    1245                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:   /* FALLTHROUGH */
    1246                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:   /* FALLTHROUGH */
    1247                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:  /* FALLTHROUGH */
    1248                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:     /* FALLTHROUGH */
    1249                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    1250                 :          0 :                         pass = nfp_ct_merge_action_check(action, items);
    1251                 :          0 :                         break;
    1252                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK: /* FALLTHROUGH */
    1253                 :            :                 case RTE_FLOW_ACTION_TYPE_JUMP:      /* FALLTHROUGH */
    1254                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:     /* FALLTHROUGH */
    1255                 :            :                 case RTE_FLOW_ACTION_TYPE_DROP:      /* FALLTHROUGH */
    1256                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    1257                 :          0 :                         *cnt_same = *cnt_same + 1;
    1258                 :          0 :                         break;
    1259                 :            :                 default:
    1260                 :            :                         pass = false;
    1261                 :            :                         break;
    1262                 :            :                 }
    1263                 :            :         }
    1264                 :            : 
    1265                 :          0 :         return pass;
    1266                 :            : }
    1267                 :            : 
    1268                 :            : static void
    1269                 :          0 : nfp_ct_merge_item_real(const struct rte_flow_item *item_src,
    1270                 :            :                 struct rte_flow_item *item_dst)
    1271                 :            : {
    1272                 :            :         uint32_t i;
    1273                 :            :         char *key_dst;
    1274                 :            :         char *mask_dst;
    1275                 :          0 :         size_t size = 0;
    1276                 :            :         const char *key_src;
    1277                 :            :         const char *mask_src;
    1278                 :            : 
    1279                 :          0 :         key_src = item_src->spec;
    1280                 :          0 :         mask_src = item_src->mask;
    1281                 :          0 :         key_dst = (char *)(ptrdiff_t)item_dst->spec;
    1282                 :          0 :         mask_dst = (char *)(ptrdiff_t)item_dst->mask;
    1283                 :          0 :         nfp_flow_item_conf_size_get(item_src->type, &size);
    1284                 :            : 
    1285         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1286                 :          0 :                 key_dst[i] |= key_src[i];
    1287                 :          0 :                 mask_dst[i] |= mask_src[i];
    1288                 :            :         }
    1289                 :          0 : }
    1290                 :            : 
    1291                 :            : static bool
    1292                 :          0 : nfp_ct_merge_item(uint32_t index,
    1293                 :            :                 const struct rte_flow_item *item1,
    1294                 :            :                 const struct rte_flow_item *item2_start,
    1295                 :            :                 const struct rte_flow_item *item2_end,
    1296                 :            :                 struct nfp_ct_merge_entry *merge_entry)
    1297                 :            : {
    1298                 :            :         struct rte_flow_item *item;
    1299                 :            :         const struct rte_flow_item *item2;
    1300                 :            : 
    1301                 :            :         /* Copy to the merged items */
    1302                 :          0 :         item = &merge_entry->rule.items[index];
    1303                 :          0 :         *item = *item1;
    1304                 :            : 
    1305                 :            :         item2 = item2_start;
    1306         [ #  # ]:          0 :         if (item2_end != NULL) {
    1307         [ #  # ]:          0 :                 for (; item2 != item2_end; item2++) {
    1308         [ #  # ]:          0 :                         if (item1->type == item2->type) {
    1309                 :          0 :                                 nfp_ct_merge_item_real(item2, item);
    1310                 :          0 :                                 return true;
    1311                 :            :                         }
    1312                 :            :                 }
    1313                 :            :         } else {
    1314         [ #  # ]:          0 :                 for (; item2->type != RTE_FLOW_ITEM_TYPE_END; item2++) {
    1315         [ #  # ]:          0 :                         if (item1->type == item2->type) {
    1316                 :          0 :                                 nfp_ct_merge_item_real(item2, item);
    1317                 :          0 :                                 return true;
    1318                 :            :                         }
    1319                 :            :                 }
    1320                 :            :         }
    1321                 :            : 
    1322                 :            :         return false;
    1323                 :            : }
    1324                 :            : 
    1325                 :            : static void
    1326                 :          0 : nfp_ct_merge_items(struct nfp_ct_merge_entry *merge_entry)
    1327                 :            : {
    1328                 :            :         uint32_t index = 0;
    1329                 :            :         bool is_tun_flow_1;
    1330                 :            :         bool is_tun_flow_2;
    1331                 :            :         struct rte_flow_item *items1;
    1332                 :            :         struct rte_flow_item *items2;
    1333                 :            :         struct rte_flow_item *merge_item;
    1334                 :            :         const struct rte_flow_item *item;
    1335                 :          0 :         const struct rte_flow_item *inner1 = NULL;
    1336                 :          0 :         const struct rte_flow_item *inner2 = NULL;
    1337                 :            : 
    1338                 :          0 :         items1 = merge_entry->pre_ct_parent->rule.items;
    1339                 :          0 :         items2 = merge_entry->post_ct_parent->rule.items;
    1340                 :          0 :         is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner1);
    1341                 :          0 :         is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner2);
    1342                 :            : 
    1343         [ #  # ]:          0 :         if (is_tun_flow_1) {
    1344         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1345                 :            :                         /* Outer layer */
    1346         [ #  # ]:          0 :                         for (item = items1; item != inner1; item++, index++) {
    1347         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
    1348                 :          0 :                                         items2++;
    1349                 :            :                         }
    1350                 :            : 
    1351                 :            :                         /* Copy the remainning outer layer items */
    1352         [ #  # ]:          0 :                         for (item = items2; item != inner2; item++, index++) {
    1353                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1354                 :          0 :                                 *merge_item = *item;
    1355                 :            :                         }
    1356                 :            : 
    1357                 :            :                         /* Inner layer */
    1358         [ #  # ]:          0 :                         for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1359         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, inner2, NULL, merge_entry))
    1360                 :          0 :                                         items2++;
    1361                 :            :                         }
    1362                 :            : 
    1363                 :            :                         /* Copy the remainning inner layer items */
    1364         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1365                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1366                 :          0 :                                 *merge_item = *item;
    1367                 :            :                         }
    1368                 :            :                 } else {
    1369         [ #  # ]:          0 :                         for (item = items1; item != inner1; item++, index++) {
    1370         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
    1371                 :          0 :                                         items2++;
    1372                 :            :                         }
    1373                 :            : 
    1374                 :            :                         /* Copy the remainning items */
    1375         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1376                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1377                 :          0 :                                 *merge_item = *item;
    1378                 :            :                         }
    1379                 :            : 
    1380                 :            :                         /* Copy the inner layer items */
    1381         [ #  # ]:          0 :                         for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1382                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1383                 :          0 :                                 *merge_item = *item;
    1384                 :            :                         }
    1385                 :            :                 }
    1386                 :            :         } else {
    1387         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1388         [ #  # ]:          0 :                         for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1389         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
    1390                 :          0 :                                         items2++;
    1391                 :            :                         }
    1392                 :            : 
    1393                 :            :                         /* Copy the remainning items */
    1394         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1395                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1396                 :          0 :                                 *merge_item = *item;
    1397                 :            :                         }
    1398                 :            :                 } else {
    1399         [ #  # ]:          0 :                         for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1400         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
    1401                 :          0 :                                         items2++;
    1402                 :            :                         }
    1403                 :            : 
    1404                 :            :                         /* Copy the remainning items */
    1405         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1406                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1407                 :          0 :                                 *merge_item = *item;
    1408                 :            :                         }
    1409                 :            :                 }
    1410                 :            :         }
    1411                 :          0 : }
    1412                 :            : 
    1413                 :            : static void
    1414                 :          0 : nfp_ct_merge_actions(struct nfp_ct_merge_entry *merge_entry)
    1415                 :            : {
    1416                 :            :         struct rte_flow_action *action;
    1417                 :            :         struct rte_flow_action *merge_actions;
    1418                 :            : 
    1419                 :          0 :         merge_actions = merge_entry->rule.actions;
    1420                 :            : 
    1421                 :          0 :         action = merge_entry->pre_ct_parent->rule.actions;
    1422         [ #  # ]:          0 :         for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1423         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK ||
    1424                 :            :                                 action->type == RTE_FLOW_ACTION_TYPE_JUMP)
    1425                 :          0 :                         continue;
    1426                 :            : 
    1427                 :          0 :                 *merge_actions = *action;
    1428                 :          0 :                 merge_actions++;
    1429                 :            :         }
    1430                 :            : 
    1431                 :          0 :         action = merge_entry->post_ct_parent->rule.actions;
    1432         [ #  # ]:          0 :         for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1433                 :          0 :                 *merge_actions = *action;
    1434                 :          0 :                 merge_actions++;
    1435                 :            :         }
    1436                 :          0 : }
    1437                 :            : 
    1438                 :            : static bool
    1439                 :          0 : nfp_ct_do_flow_merge(struct nfp_ct_zone_entry *ze,
    1440                 :            :                 struct nfp_ct_flow_entry *pre_ct_entry,
    1441                 :            :                 struct nfp_ct_flow_entry *post_ct_entry)
    1442                 :            : {
    1443                 :            :         bool ret;
    1444                 :            :         uint64_t new_cookie[2];
    1445                 :          0 :         uint8_t cnt_same_item = 0;
    1446                 :          0 :         uint8_t cnt_same_action = 0;
    1447                 :            :         struct nfp_ct_merge_entry *merge_entry;
    1448                 :            : 
    1449         [ #  # ]:          0 :         if (pre_ct_entry->dev != post_ct_entry->dev)
    1450                 :            :                 return true;
    1451                 :            : 
    1452                 :          0 :         ret = nfp_ct_merge_items_check(pre_ct_entry->rule.items,
    1453                 :            :                         post_ct_entry->rule.items, &cnt_same_item);
    1454         [ #  # ]:          0 :         if (!ret)
    1455                 :            :                 return true;
    1456                 :            : 
    1457                 :          0 :         ret = nfp_ct_merge_actions_check(pre_ct_entry->rule.actions,
    1458                 :            :                         post_ct_entry->rule.items, &cnt_same_action);
    1459         [ #  # ]:          0 :         if (!ret)
    1460                 :            :                 return true;
    1461                 :            : 
    1462                 :          0 :         new_cookie[0] = pre_ct_entry->cookie;
    1463                 :          0 :         new_cookie[1] = post_ct_entry->cookie;
    1464                 :          0 :         merge_entry = nfp_ct_merge_table_search(ze, (char *)&new_cookie, sizeof(uint64_t) * 2);
    1465         [ #  # ]:          0 :         if (merge_entry != NULL)
    1466                 :            :                 return true;
    1467                 :            : 
    1468                 :          0 :         merge_entry = rte_zmalloc("ct_merge_entry", sizeof(*merge_entry), 0);
    1469         [ #  # ]:          0 :         if (merge_entry == NULL) {
    1470                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct merge entry failed.");
    1471                 :          0 :                 return false;
    1472                 :            :         }
    1473                 :            : 
    1474                 :          0 :         merge_entry->ze = ze;
    1475                 :          0 :         merge_entry->pre_ct_parent = pre_ct_entry;
    1476                 :          0 :         merge_entry->post_ct_parent = post_ct_entry;
    1477         [ #  # ]:          0 :         rte_memcpy(merge_entry->cookie, new_cookie, sizeof(new_cookie));
    1478                 :          0 :         merge_entry->rule.items_cnt = pre_ct_entry->rule.items_cnt +
    1479                 :          0 :                         post_ct_entry->rule.items_cnt - cnt_same_item - 1;
    1480                 :          0 :         merge_entry->rule.actions_cnt = pre_ct_entry->rule.actions_cnt +
    1481                 :          0 :                         post_ct_entry->rule.actions_cnt - cnt_same_action - 1;
    1482                 :            : 
    1483                 :          0 :         merge_entry->rule.items = rte_zmalloc("ct_flow_item",
    1484                 :          0 :                         sizeof(struct rte_flow_item) * merge_entry->rule.items_cnt, 0);
    1485         [ #  # ]:          0 :         if (merge_entry->rule.items == NULL) {
    1486                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc items for merged flow.");
    1487                 :          0 :                 goto merge_exit;
    1488                 :            :         }
    1489                 :            : 
    1490                 :          0 :         merge_entry->rule.actions = rte_zmalloc("ct_flow_action",
    1491                 :          0 :                         sizeof(struct rte_flow_action) * merge_entry->rule.actions_cnt, 0);
    1492         [ #  # ]:          0 :         if (merge_entry->rule.actions == NULL) {
    1493                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc actions for merged flow.");
    1494                 :          0 :                 goto free_items;
    1495                 :            :         }
    1496                 :            : 
    1497                 :          0 :         nfp_ct_merge_items(merge_entry);
    1498                 :          0 :         nfp_ct_merge_actions(merge_entry);
    1499                 :            : 
    1500                 :            :         /* Add this entry to the pre_ct and post_ct lists */
    1501         [ #  # ]:          0 :         LIST_INSERT_HEAD(&pre_ct_entry->children, merge_entry, pre_ct_list);
    1502         [ #  # ]:          0 :         LIST_INSERT_HEAD(&post_ct_entry->children, merge_entry, post_ct_list);
    1503                 :            : 
    1504                 :          0 :         ret = nfp_ct_merge_table_add(ze, merge_entry);
    1505         [ #  # ]:          0 :         if (!ret) {
    1506                 :          0 :                 PMD_DRV_LOG(ERR, "Add into ct merge table failed.");
    1507                 :          0 :                 goto free_actions;
    1508                 :            :         }
    1509                 :            : 
    1510                 :            :         /* Send to firmware */
    1511                 :          0 :         ret = nfp_ct_offload_add(pre_ct_entry->dev, merge_entry);
    1512         [ #  # ]:          0 :         if (ret != 0) {
    1513                 :          0 :                 PMD_DRV_LOG(ERR, "Send the merged flow to firmware failed.");
    1514                 :          0 :                 goto merge_table_del;
    1515                 :            :         }
    1516                 :            : 
    1517                 :            :         return true;
    1518                 :            : 
    1519                 :            : merge_table_del:
    1520                 :          0 :         nfp_ct_merge_table_delete(ze, merge_entry);
    1521                 :          0 : free_actions:
    1522                 :          0 :         rte_free(merge_entry->rule.actions);
    1523                 :          0 : free_items:
    1524                 :          0 :         rte_free(merge_entry->rule.items);
    1525                 :          0 : merge_exit:
    1526         [ #  # ]:          0 :         LIST_REMOVE(merge_entry, post_ct_list);
    1527         [ #  # ]:          0 :         LIST_REMOVE(merge_entry, pre_ct_list);
    1528                 :          0 :         rte_free(merge_entry);
    1529                 :            : 
    1530                 :          0 :         return ret;
    1531                 :            : }
    1532                 :            : 
    1533                 :            : static bool
    1534                 :          0 : nfp_ct_merge_flow_entries(struct nfp_ct_flow_entry *fe,
    1535                 :            :                 struct nfp_ct_zone_entry *ze_src,
    1536                 :            :                 struct nfp_ct_zone_entry *ze_dst)
    1537                 :            : {
    1538                 :            :         bool ret;
    1539                 :            :         struct nfp_ct_flow_entry *fe_tmp;
    1540                 :            : 
    1541         [ #  # ]:          0 :         if (fe->type == CT_TYPE_PRE_CT) {
    1542         [ #  # ]:          0 :                 LIST_FOREACH(fe_tmp, &ze_src->post_ct_list, post_ct_list) {
    1543                 :          0 :                         ret = nfp_ct_do_flow_merge(ze_dst, fe, fe_tmp);
    1544         [ #  # ]:          0 :                         if (!ret) {
    1545                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge for ct pre flow failed.");
    1546                 :          0 :                                 return false;
    1547                 :            :                         }
    1548                 :            :                 }
    1549                 :            :         } else {
    1550         [ #  # ]:          0 :                 LIST_FOREACH(fe_tmp, &ze_src->pre_ct_list, pre_ct_list) {
    1551                 :          0 :                         ret = nfp_ct_do_flow_merge(ze_dst, fe_tmp, fe);
    1552         [ #  # ]:          0 :                         if (!ret) {
    1553                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge for ct post flow failed.");
    1554                 :          0 :                                 return false;
    1555                 :            :                         }
    1556                 :            :                 }
    1557                 :            :         }
    1558                 :            : 
    1559                 :            :         return true;
    1560                 :            : }
    1561                 :            : 
    1562                 :            : static bool
    1563                 :          0 : nfp_flow_handle_pre_ct(const struct rte_flow_item *ct_item,
    1564                 :            :                 struct rte_eth_dev *dev,
    1565                 :            :                 const struct rte_flow_item items[],
    1566                 :            :                 const struct rte_flow_action actions[],
    1567                 :            :                 uint64_t cookie)
    1568                 :            : {
    1569                 :            :         bool ret;
    1570                 :            :         struct nfp_flow_priv *priv;
    1571                 :            :         struct nfp_ct_zone_entry *ze;
    1572                 :            :         struct nfp_ct_flow_entry *fe;
    1573                 :          0 :         const struct ct_data *ct = ct_item->spec;
    1574                 :            :         struct nfp_flower_representor *representor;
    1575                 :            : 
    1576                 :          0 :         representor = dev->data->dev_private;
    1577                 :          0 :         priv = representor->app_fw_flower->flow_priv;
    1578                 :          0 :         ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, false);
    1579         [ #  # ]:          0 :         if (ze == NULL) {
    1580                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct zone entry.");
    1581                 :          0 :                 return false;
    1582                 :            :         }
    1583                 :            : 
    1584                 :            :         /* Add entry to pre_ct_list */
    1585                 :          0 :         fe = nfp_ct_flow_entry_get(ze, dev, items, actions, cookie);
    1586         [ #  # ]:          0 :         if (fe == NULL) {
    1587                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct flow entry.");
    1588                 :          0 :                 goto ct_zone_entry_free;
    1589                 :            :         }
    1590                 :            : 
    1591                 :          0 :         fe->type = CT_TYPE_PRE_CT;
    1592         [ #  # ]:          0 :         LIST_INSERT_HEAD(&ze->pre_ct_list, fe, pre_ct_list);
    1593                 :            : 
    1594                 :          0 :         ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1595         [ #  # ]:          0 :         if (!ret) {
    1596                 :          0 :                 PMD_DRV_LOG(ERR, "Merge ct flow entries failed.");
    1597                 :          0 :                 goto ct_flow_entry_free;
    1598                 :            :         }
    1599                 :            : 
    1600                 :            :         /* Need to check and merge with tables in the wc_zone as well */
    1601         [ #  # ]:          0 :         if (priv->ct_zone_wc != NULL) {
    1602                 :          0 :                 ret = nfp_ct_merge_flow_entries(fe, priv->ct_zone_wc, ze);
    1603         [ #  # ]:          0 :                 if (!ret) {
    1604                 :          0 :                         PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed.");
    1605                 :          0 :                         goto ct_flow_entry_free;
    1606                 :            :                 }
    1607                 :            :         }
    1608                 :            : 
    1609                 :            :         return true;
    1610                 :            : 
    1611                 :          0 : ct_flow_entry_free:
    1612                 :          0 :         nfp_ct_flow_entry_destroy(fe);
    1613                 :            : 
    1614                 :          0 : ct_zone_entry_free:
    1615                 :          0 :         nfp_ct_zone_entry_free(ze, false);
    1616                 :            : 
    1617                 :          0 :         return false;
    1618                 :            : }
    1619                 :            : 
    1620                 :            : static bool
    1621                 :          0 : nfp_flow_handle_post_ct(const struct rte_flow_item *ct_item,
    1622                 :            :                 struct rte_eth_dev *dev,
    1623                 :            :                 const struct rte_flow_item items[],
    1624                 :            :                 const struct rte_flow_action actions[],
    1625                 :            :                 uint64_t cookie)
    1626                 :            : {
    1627                 :            :         bool ret;
    1628                 :            :         void *next_data;
    1629                 :          0 :         uint32_t iter = 0;
    1630                 :            :         const void *next_key;
    1631                 :            :         bool wildcard = false;
    1632                 :            :         struct nfp_flow_priv *priv;
    1633                 :            :         struct nfp_ct_zone_entry *ze;
    1634                 :            :         struct nfp_ct_flow_entry *fe;
    1635                 :            :         struct nfp_flower_representor *representor;
    1636                 :          0 :         const struct ct_data *ct = ct_item->spec;
    1637                 :          0 :         const struct ct_data *ct_mask = ct_item->mask;
    1638                 :            : 
    1639         [ #  # ]:          0 :         if (ct_mask->ct_zone == 0) {
    1640                 :            :                 wildcard = true;
    1641         [ #  # ]:          0 :         } else if (ct_mask->ct_zone != UINT16_MAX) {
    1642                 :          0 :                 PMD_DRV_LOG(ERR, "Partially wildcard ct_zone is not supported.");
    1643                 :          0 :                 return false;
    1644                 :            :         }
    1645                 :            : 
    1646                 :          0 :         representor = dev->data->dev_private;
    1647                 :          0 :         priv = representor->app_fw_flower->flow_priv;
    1648                 :          0 :         ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, wildcard);
    1649         [ #  # ]:          0 :         if (ze == NULL) {
    1650                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct zone entry.");
    1651                 :          0 :                 return false;
    1652                 :            :         }
    1653                 :            : 
    1654                 :            :         /* Add entry to post_ct_list */
    1655                 :          0 :         fe = nfp_ct_flow_entry_get(ze, dev, items, actions, cookie);
    1656         [ #  # ]:          0 :         if (fe == NULL) {
    1657                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct flow entry.");
    1658                 :          0 :                 goto ct_zone_entry_free;
    1659                 :            :         }
    1660                 :            : 
    1661                 :          0 :         fe->type = CT_TYPE_POST_CT;
    1662         [ #  # ]:          0 :         LIST_INSERT_HEAD(&ze->post_ct_list, fe, post_ct_list);
    1663                 :            : 
    1664         [ #  # ]:          0 :         if (wildcard) {
    1665         [ #  # ]:          0 :                 while (rte_hash_iterate(priv->ct_zone_table, &next_key, &next_data, &iter) >= 0) {
    1666                 :          0 :                         ze = (struct nfp_ct_zone_entry *)next_data;
    1667                 :          0 :                         ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1668         [ #  # ]:          0 :                         if (!ret) {
    1669                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed.");
    1670                 :          0 :                                 break;
    1671                 :            :                         }
    1672                 :            :                 }
    1673                 :            :         } else {
    1674                 :          0 :                 ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1675                 :            :         }
    1676                 :            : 
    1677         [ #  # ]:          0 :         if (!ret)
    1678                 :          0 :                 goto ct_flow_entry_free;
    1679                 :            : 
    1680                 :            :         return true;
    1681                 :            : 
    1682                 :            : ct_flow_entry_free:
    1683                 :          0 :         nfp_ct_flow_entry_destroy(fe);
    1684                 :            : 
    1685                 :          0 : ct_zone_entry_free:
    1686                 :          0 :         nfp_ct_zone_entry_free(ze, wildcard);
    1687                 :            : 
    1688                 :          0 :         return false;
    1689                 :            : }
    1690                 :            : 
    1691                 :            : struct rte_flow *
    1692                 :          0 : nfp_ct_flow_setup(struct rte_eth_dev *dev,
    1693                 :            :                 const struct rte_flow_item items[],
    1694                 :            :                 const struct rte_flow_action actions[],
    1695                 :            :                 const struct rte_flow_item *ct_item,
    1696                 :            :                 bool validate_flag,
    1697                 :            :                 uint64_t cookie)
    1698                 :            : {
    1699                 :            :         const struct ct_data *ct;
    1700                 :            : 
    1701         [ #  # ]:          0 :         if (ct_item == NULL)
    1702                 :            :                 return NULL;
    1703                 :            : 
    1704         [ #  # ]:          0 :         ct = ct_item->spec;
    1705                 :            : 
    1706                 :            :         if (is_ct_commit_flow(ct)) {
    1707                 :          0 :                 return nfp_flow_process(dev, &items[1], actions,
    1708                 :            :                                 validate_flag, cookie, false, false);
    1709                 :            :         }
    1710                 :            : 
    1711                 :            :         if (is_post_ct_flow(ct)) {
    1712         [ #  # ]:          0 :                 if (nfp_flow_handle_post_ct(ct_item, dev, &items[1],
    1713                 :            :                                 actions, cookie)) {
    1714                 :          0 :                         return nfp_flow_process(dev, &items[1], actions,
    1715                 :            :                                         validate_flag, cookie, false, false);
    1716                 :            :                 }
    1717                 :            : 
    1718                 :          0 :                 PMD_DRV_LOG(ERR, "Handle NFP post ct flow failed.");
    1719                 :          0 :                 return NULL;
    1720                 :            :         }
    1721                 :            : 
    1722         [ #  # ]:          0 :         if (is_pre_ct_flow(ct, actions)) {
    1723         [ #  # ]:          0 :                 if (nfp_flow_handle_pre_ct(ct_item, dev, &items[1],
    1724                 :            :                                 actions, cookie)) {
    1725                 :          0 :                         return nfp_flow_process(dev, &items[1], actions,
    1726                 :            :                                         validate_flag, cookie, false, false);
    1727                 :            :                 }
    1728                 :            : 
    1729                 :          0 :                 PMD_DRV_LOG(ERR, "Handle NFP pre ct flow failed.");
    1730                 :          0 :                 return NULL;
    1731                 :            :         }
    1732                 :            : 
    1733                 :          0 :         PMD_DRV_LOG(ERR, "Unsupported ct flow type.");
    1734                 :          0 :         return NULL;
    1735                 :            : }
    1736                 :            : 
    1737                 :            : static inline void
    1738                 :          0 : nfp_ct_flow_stats_update(struct nfp_flow_priv *priv,
    1739                 :            :                 struct nfp_ct_merge_entry *m_ent)
    1740                 :            : {
    1741                 :            :         uint32_t ctx_id;
    1742                 :            :         struct nfp_fl_stats *merge_stats;
    1743                 :            : 
    1744                 :          0 :         ctx_id = m_ent->ctx_id;
    1745                 :          0 :         merge_stats = &priv->stats[ctx_id];
    1746                 :            : 
    1747                 :          0 :         m_ent->pre_ct_parent->stats.bytes  += merge_stats->bytes;
    1748                 :          0 :         m_ent->pre_ct_parent->stats.pkts   += merge_stats->pkts;
    1749                 :          0 :         m_ent->post_ct_parent->stats.bytes += merge_stats->bytes;
    1750                 :          0 :         m_ent->post_ct_parent->stats.pkts  += merge_stats->pkts;
    1751                 :            : 
    1752                 :          0 :         merge_stats->bytes = 0;
    1753                 :          0 :         merge_stats->pkts = 0;
    1754                 :          0 : }
    1755                 :            : 
    1756                 :            : struct nfp_fl_stats *
    1757                 :          0 : nfp_ct_flow_stats_get(struct nfp_flow_priv *priv,
    1758                 :            :                 struct nfp_ct_map_entry *me)
    1759                 :            : {
    1760                 :            :         struct nfp_ct_merge_entry *m_ent;
    1761                 :            : 
    1762                 :          0 :         rte_spinlock_lock(&priv->stats_lock);
    1763                 :            : 
    1764         [ #  # ]:          0 :         if (me->fe->type == CT_TYPE_PRE_CT) {
    1765         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &me->fe->children, pre_ct_list)
    1766                 :          0 :                         nfp_ct_flow_stats_update(priv, m_ent);
    1767                 :            :         } else {
    1768         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &me->fe->children, post_ct_list)
    1769                 :          0 :                         nfp_ct_flow_stats_update(priv, m_ent);
    1770                 :            :         }
    1771                 :            : 
    1772                 :            :         rte_spinlock_unlock(&priv->stats_lock);
    1773                 :            : 
    1774                 :          0 :         return &me->fe->stats;
    1775                 :            : }

Generated by: LCOV version 1.14