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 719 0.0 %
Date: 2024-01-22 15:35:40 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 nfp_flower_representor *repr;
      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 nfp_flower_representor *repr,
     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                 :            : 
     676                 :          0 :         fe = rte_zmalloc("ct_flow_entry", sizeof(*fe), 0);
     677         [ #  # ]:          0 :         if (fe == NULL) {
     678                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct_flow entry");
     679                 :          0 :                 return NULL;
     680                 :            :         }
     681                 :            : 
     682                 :          0 :         fe->ze = ze;
     683                 :          0 :         fe->repr = repr;
     684                 :          0 :         fe->cookie = cookie;
     685                 :          0 :         LIST_INIT(&fe->children);
     686                 :            : 
     687         [ #  # ]:          0 :         for (loop = 0; (items + loop)->type != RTE_FLOW_ITEM_TYPE_END; loop++)
     688                 :          0 :                 item_cnt++;
     689         [ #  # ]:          0 :         for (loop = 0; (actions + loop)->type != RTE_FLOW_ACTION_TYPE_END; loop++)
     690                 :          0 :                 action_cnt++;
     691                 :            : 
     692                 :          0 :         fe->rule.items = rte_zmalloc("ct_flow_item",
     693                 :            :                         sizeof(struct rte_flow_item) * item_cnt, 0);
     694         [ #  # ]:          0 :         if (fe->rule.items == NULL) {
     695                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct flow items");
     696                 :          0 :                 goto free_flow_entry;
     697                 :            :         }
     698                 :            : 
     699                 :          0 :         fe->rule.actions = rte_zmalloc("ct_flow_action",
     700                 :            :                         sizeof(struct rte_flow_action) * action_cnt, 0);
     701         [ #  # ]:          0 :         if (fe->rule.actions == NULL) {
     702                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc ct flow actions");
     703                 :          0 :                 goto free_flow_item;
     704                 :            :         }
     705                 :            : 
     706                 :            :         /* Deep copy of items */
     707                 :          0 :         ret = nfp_ct_flow_items_copy(items, fe->rule.items, item_cnt);
     708         [ #  # ]:          0 :         if (!ret) {
     709                 :          0 :                 PMD_DRV_LOG(ERR, "Could not deep copy ct flow items");
     710                 :          0 :                 goto free_flow_action;
     711                 :            :         }
     712                 :            : 
     713                 :            :         /* Deep copy of actions */
     714                 :          0 :         ret = nfp_ct_flow_actions_copy(actions, fe->rule.actions, action_cnt);
     715         [ #  # ]:          0 :         if (!ret) {
     716                 :          0 :                 PMD_DRV_LOG(ERR, "Could not deep copy ct flow actions");
     717                 :          0 :                 goto free_copied_items;
     718                 :            :         }
     719                 :            : 
     720                 :          0 :         fe->rule.items_cnt = item_cnt;
     721                 :          0 :         fe->rule.actions_cnt = action_cnt;
     722                 :            : 
     723                 :            :         /* Now add a ct map entry */
     724                 :          0 :         me = rte_zmalloc("ct_map_entry", sizeof(*me), 0);
     725         [ #  # ]:          0 :         if (me == NULL) {
     726                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct map entry failed");
     727                 :          0 :                 goto free_copied_actions;
     728                 :            :         }
     729                 :            : 
     730                 :          0 :         me->cookie = fe->cookie;
     731                 :          0 :         me->fe = fe;
     732                 :            : 
     733                 :          0 :         priv = repr->app_fw_flower->flow_priv;
     734                 :          0 :         ret = nfp_ct_map_table_add(priv, me);
     735         [ #  # ]:          0 :         if (!ret) {
     736                 :          0 :                 PMD_DRV_LOG(ERR, "Add into ct map table failed");
     737                 :          0 :                 goto free_map_entry;
     738                 :            :         }
     739                 :            : 
     740                 :            :         return fe;
     741                 :            : 
     742                 :            : free_map_entry:
     743                 :            :         nfp_ct_map_entry_destroy(me);
     744                 :          0 : free_copied_actions:
     745                 :          0 :         nfp_ct_flow_actions_free(fe->rule.actions, action_cnt);
     746                 :          0 : free_copied_items:
     747                 :          0 :         nfp_ct_flow_items_free(fe->rule.items, item_cnt);
     748                 :          0 : free_flow_action:
     749                 :          0 :         rte_free(fe->rule.actions);
     750                 :          0 : free_flow_item:
     751                 :          0 :         rte_free(fe->rule.items);
     752                 :          0 : free_flow_entry:
     753                 :          0 :         rte_free(fe);
     754                 :            : 
     755                 :          0 :         return NULL;
     756                 :            : }
     757                 :            : 
     758                 :            : static void
     759                 :          0 : nfp_flow_children_merge_free(struct nfp_ct_flow_entry *fe)
     760                 :            : {
     761                 :            :         struct nfp_ct_merge_entry *m_ent;
     762                 :            : 
     763      [ #  #  # ]:          0 :         switch (fe->type) {
     764                 :          0 :         case CT_TYPE_PRE_CT:
     765         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, pre_ct_list)
     766                 :          0 :                         nfp_ct_merge_entry_destroy(m_ent);
     767                 :            :                 break;
     768                 :          0 :         case CT_TYPE_POST_CT:
     769         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, post_ct_list)
     770                 :          0 :                         nfp_ct_merge_entry_destroy(m_ent);
     771                 :            :                 break;
     772                 :            :         default:
     773                 :            :                 break;
     774                 :            :         }
     775                 :          0 : }
     776                 :            : 
     777                 :            : static void
     778                 :          0 : nfp_ct_flow_entry_destroy_partly(struct nfp_ct_flow_entry *fe)
     779                 :            : {
     780                 :            :         struct nfp_ct_map_entry *me;
     781                 :            : 
     782         [ #  # ]:          0 :         if (!LIST_EMPTY(&fe->children))
     783                 :          0 :                 nfp_flow_children_merge_free(fe);
     784                 :            : 
     785                 :          0 :         me = nfp_ct_map_table_search(fe->ze->priv, (char *)&fe->cookie, sizeof(uint64_t));
     786         [ #  # ]:          0 :         if (me != NULL) {
     787                 :          0 :                 nfp_ct_map_table_delete(fe->ze->priv, me);
     788                 :            :                 nfp_ct_map_entry_destroy(me);
     789                 :            :         }
     790                 :            : 
     791                 :          0 :         nfp_ct_flow_actions_free(fe->rule.actions, fe->rule.actions_cnt);
     792                 :          0 :         nfp_ct_flow_items_free(fe->rule.items, fe->rule.items_cnt);
     793                 :          0 :         rte_free(fe->rule.actions);
     794                 :          0 :         rte_free(fe->rule.items);
     795                 :          0 :         rte_free(fe);
     796                 :          0 : }
     797                 :            : 
     798                 :            : static void
     799                 :          0 : nfp_ct_flow_entry_destroy(struct nfp_ct_flow_entry *fe)
     800                 :            : {
     801         [ #  # ]:          0 :         LIST_REMOVE(fe, pre_ct_list);
     802         [ #  # ]:          0 :         LIST_REMOVE(fe, post_ct_list);
     803                 :            : 
     804                 :          0 :         nfp_ct_flow_entry_destroy_partly(fe);
     805                 :          0 : }
     806                 :            : 
     807                 :            : static struct nfp_ct_zone_entry *
     808                 :          0 : nfp_ct_zone_table_search(struct nfp_flow_priv *priv,
     809                 :            :                 char *hash_data,
     810                 :            :                 uint32_t hash_len)
     811                 :            : {
     812                 :            :         int index;
     813                 :            :         uint32_t hash_key;
     814                 :            :         struct nfp_ct_zone_entry *ze;
     815                 :            : 
     816                 :          0 :         hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
     817                 :          0 :         index = rte_hash_lookup_data(priv->ct_zone_table, &hash_key, (void **)&ze);
     818         [ #  # ]:          0 :         if (index < 0) {
     819                 :          0 :                 PMD_DRV_LOG(DEBUG, "Data NOT found in the ct_zone table");
     820                 :          0 :                 return NULL;
     821                 :            :         }
     822                 :            : 
     823                 :          0 :         return ze;
     824                 :            : }
     825                 :            : 
     826                 :            : static bool
     827                 :          0 : nfp_ct_zone_table_add(struct nfp_flow_priv *priv,
     828                 :            :                 struct nfp_ct_zone_entry *ze)
     829                 :            : {
     830                 :            :         int ret;
     831                 :            :         uint32_t hash_key;
     832                 :            : 
     833                 :          0 :         hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
     834                 :          0 :         ret = rte_hash_add_key_data(priv->ct_zone_table, &hash_key, ze);
     835         [ #  # ]:          0 :         if (ret != 0) {
     836                 :          0 :                 PMD_DRV_LOG(ERR, "Add to the ct_zone table failed");
     837                 :          0 :                 return false;
     838                 :            :         }
     839                 :            : 
     840                 :            :         return true;
     841                 :            : }
     842                 :            : 
     843                 :            : static void
     844                 :          0 : nfp_ct_zone_table_delete(struct nfp_flow_priv *priv,
     845                 :            :                 struct nfp_ct_zone_entry *ze)
     846                 :            : {
     847                 :            :         int ret;
     848                 :            :         uint32_t hash_key;
     849                 :            : 
     850                 :          0 :         hash_key = rte_jhash(ze, sizeof(uint32_t), priv->hash_seed);
     851                 :          0 :         ret = rte_hash_del_key(priv->ct_zone_table, &hash_key);
     852         [ #  # ]:          0 :         if (ret < 0)
     853                 :          0 :                 PMD_DRV_LOG(ERR, "Delete from the ct_zone table failed");
     854                 :          0 : }
     855                 :            : 
     856                 :            : static bool
     857                 :          0 : nfp_ct_zone_entry_init(struct nfp_ct_zone_entry *ze,
     858                 :            :                 struct nfp_flow_priv *priv,
     859                 :            :                 uint32_t zone,
     860                 :            :                 bool wildcard)
     861                 :            : {
     862                 :            :         char hash_name[RTE_HASH_NAMESIZE];
     863                 :          0 :         struct rte_hash_parameters ct_merge_hash_params = {
     864                 :            :                 .entries    = 1000,
     865                 :            :                 .hash_func  = rte_jhash,
     866                 :          0 :                 .socket_id  = rte_socket_id(),
     867                 :            :                 .key_len    = sizeof(uint32_t),
     868                 :            :                 .extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
     869                 :            :         };
     870                 :            : 
     871         [ #  # ]:          0 :         if (wildcard) {
     872                 :          0 :                 ct_merge_hash_params.name = "ct_wc_merge_table";
     873                 :            :         } else {
     874                 :          0 :                 snprintf(hash_name, sizeof(hash_name), "ct_%d_merge_table", ze->zone);
     875                 :          0 :                 ct_merge_hash_params.name = hash_name;
     876                 :            :         }
     877                 :            : 
     878                 :          0 :         ct_merge_hash_params.hash_func_init_val = priv->hash_seed;
     879                 :          0 :         ze->ct_merge_table = rte_hash_create(&ct_merge_hash_params);
     880         [ #  # ]:          0 :         if (ze->ct_merge_table == NULL) {
     881                 :          0 :                 PMD_DRV_LOG(ERR, "ct merge table creation failed");
     882                 :          0 :                 return false;
     883                 :            :         }
     884                 :            : 
     885                 :          0 :         ze->zone = zone;
     886                 :          0 :         ze->priv = priv;
     887                 :          0 :         LIST_INIT(&ze->pre_ct_list);
     888                 :          0 :         LIST_INIT(&ze->post_ct_list);
     889                 :            : 
     890                 :          0 :         return true;
     891                 :            : }
     892                 :            : 
     893                 :            : static void
     894                 :          0 : nfp_ct_zone_entry_destroy(struct nfp_ct_zone_entry *ze)
     895                 :            : {
     896                 :            :         struct nfp_ct_flow_entry *fe;
     897                 :            : 
     898         [ #  # ]:          0 :         if (ze == NULL)
     899                 :            :                 return;
     900                 :            : 
     901                 :          0 :         rte_hash_free(ze->ct_merge_table);
     902                 :            : 
     903         [ #  # ]:          0 :         LIST_FOREACH(fe, &ze->pre_ct_list, pre_ct_list)
     904                 :          0 :                 nfp_ct_flow_entry_destroy(fe);
     905                 :            : 
     906         [ #  # ]:          0 :         LIST_FOREACH(fe, &ze->post_ct_list, post_ct_list)
     907                 :          0 :                 nfp_ct_flow_entry_destroy(fe);
     908                 :            : 
     909                 :          0 :         rte_free(ze);
     910                 :            : }
     911                 :            : 
     912                 :            : static struct nfp_ct_zone_entry *
     913                 :          0 : nfp_ct_zone_entry_get(struct nfp_flow_priv *priv,
     914                 :            :                 uint32_t zone,
     915                 :            :                 bool wildcard)
     916                 :            : {
     917                 :            :         bool is_ok;
     918                 :            :         struct nfp_ct_zone_entry *ze;
     919                 :            : 
     920         [ #  # ]:          0 :         if (wildcard) {
     921         [ #  # ]:          0 :                 if (priv->ct_zone_wc != NULL)
     922                 :            :                         return priv->ct_zone_wc;
     923                 :            : 
     924                 :          0 :                 ze = rte_zmalloc("ct_zone_wc", sizeof(*ze), 0);
     925         [ #  # ]:          0 :                 if (ze == NULL) {
     926                 :          0 :                         PMD_DRV_LOG(ERR, "Could not alloc ct_zone_wc entry");
     927                 :          0 :                         return NULL;
     928                 :            :                 }
     929                 :            : 
     930                 :          0 :                 is_ok = nfp_ct_zone_entry_init(ze, priv, zone, true);
     931         [ #  # ]:          0 :                 if (!is_ok) {
     932                 :          0 :                         PMD_DRV_LOG(ERR, "Init ct zone wc entry failed");
     933                 :          0 :                         goto free_ct_zone_entry;
     934                 :            :                 }
     935                 :            : 
     936                 :          0 :                 priv->ct_zone_wc = ze;
     937                 :            :         } else {
     938                 :          0 :                 ze = nfp_ct_zone_table_search(priv, (char *)&zone, sizeof(uint32_t));
     939         [ #  # ]:          0 :                 if (ze != NULL)
     940                 :            :                         return ze;
     941                 :            : 
     942                 :          0 :                 ze = rte_zmalloc("ct_zone_entry", sizeof(*ze), 0);
     943         [ #  # ]:          0 :                 if (ze == NULL) {
     944                 :          0 :                         PMD_DRV_LOG(ERR, "Could not alloc ct_zone entry");
     945                 :          0 :                         return NULL;
     946                 :            :                 }
     947                 :            : 
     948                 :          0 :                 is_ok = nfp_ct_zone_entry_init(ze, priv, zone, false);
     949         [ #  # ]:          0 :                 if (!is_ok) {
     950                 :          0 :                         PMD_DRV_LOG(ERR, "Init ct zone entry failed");
     951                 :          0 :                         goto free_ct_zone_entry;
     952                 :            :                 }
     953                 :            : 
     954                 :          0 :                 is_ok = nfp_ct_zone_table_add(priv, ze);
     955         [ #  # ]:          0 :                 if (!is_ok) {
     956                 :          0 :                         PMD_DRV_LOG(ERR, "Add into ct zone table failed");
     957                 :          0 :                         goto free_ct_zone_entry;
     958                 :            :                 }
     959                 :            :         }
     960                 :            : 
     961                 :            :         return ze;
     962                 :            : 
     963                 :          0 : free_ct_zone_entry:
     964                 :          0 :         nfp_ct_zone_entry_destroy(ze);
     965                 :            : 
     966                 :          0 :         return NULL;
     967                 :            : }
     968                 :            : 
     969                 :            : static void
     970                 :          0 : nfp_ct_zone_entry_free(struct nfp_ct_zone_entry *ze,
     971                 :            :                 bool wildcard)
     972                 :            : {
     973   [ #  #  #  # ]:          0 :         if (LIST_EMPTY(&ze->pre_ct_list) && LIST_EMPTY(&ze->post_ct_list)) {
     974         [ #  # ]:          0 :                 if (!wildcard)
     975                 :          0 :                         nfp_ct_zone_table_delete(ze->priv, ze);
     976                 :            : 
     977                 :          0 :                 nfp_ct_zone_entry_destroy(ze);
     978                 :            :         }
     979                 :          0 : }
     980                 :            : 
     981                 :            : static int
     982                 :          0 : nfp_ct_offload_add(struct nfp_flower_representor *repr,
     983                 :            :                 struct nfp_ct_merge_entry *merge_entry)
     984                 :            : {
     985                 :            :         int ret;
     986                 :            :         uint64_t cookie;
     987                 :            :         struct rte_flow *nfp_flow;
     988                 :            :         struct nfp_flow_priv *priv;
     989                 :            :         const struct rte_flow_item *items;
     990                 :            :         const struct rte_flow_action *actions;
     991                 :            : 
     992                 :          0 :         cookie = rte_rand();
     993                 :          0 :         items = merge_entry->rule.items;
     994                 :          0 :         actions = merge_entry->rule.actions;
     995                 :          0 :         nfp_flow = nfp_flow_process(repr, items, actions, false, cookie, true, true);
     996         [ #  # ]:          0 :         if (nfp_flow == NULL) {
     997                 :          0 :                 PMD_DRV_LOG(ERR, "Process the merged flow rule failed.");
     998                 :          0 :                 return -EINVAL;
     999                 :            :         }
    1000                 :            : 
    1001         [ #  # ]:          0 :         merge_entry->ctx_id = rte_be_to_cpu_32(nfp_flow->payload.meta->host_ctx_id);
    1002                 :            : 
    1003                 :            :         /* Add the flow to hardware */
    1004                 :          0 :         priv = repr->app_fw_flower->flow_priv;
    1005                 :          0 :         ret = nfp_flower_cmsg_flow_add(repr->app_fw_flower, nfp_flow);
    1006         [ #  # ]:          0 :         if (ret != 0) {
    1007                 :          0 :                 PMD_DRV_LOG(ERR, "Add the merged flow to firmware failed.");
    1008                 :          0 :                 goto flow_teardown;
    1009                 :            :         }
    1010                 :            : 
    1011                 :            :         /* Add the flow to flow hash table */
    1012                 :          0 :         ret = nfp_flow_table_add_merge(priv, nfp_flow);
    1013         [ #  # ]:          0 :         if (ret != 0) {
    1014                 :          0 :                 PMD_DRV_LOG(ERR, "Add the merged flow to flow table failed.");
    1015                 :          0 :                 goto flow_teardown;
    1016                 :            :         }
    1017                 :            : 
    1018                 :          0 :         merge_entry->compiled_rule = nfp_flow;
    1019                 :            : 
    1020                 :          0 :         return 0;
    1021                 :            : 
    1022                 :          0 : flow_teardown:
    1023                 :          0 :         nfp_flow_teardown(priv, nfp_flow, false);
    1024                 :          0 :         nfp_flow_free(nfp_flow);
    1025                 :            : 
    1026                 :          0 :         return ret;
    1027                 :            : }
    1028                 :            : 
    1029                 :            : int
    1030                 :          0 : nfp_ct_offload_del(struct rte_eth_dev *dev,
    1031                 :            :                 struct nfp_ct_map_entry *me,
    1032                 :            :                 struct rte_flow_error *error)
    1033                 :            : {
    1034                 :            :         int ret;
    1035                 :            :         struct nfp_ct_flow_entry *fe;
    1036                 :            :         struct nfp_ct_merge_entry *m_ent;
    1037                 :            : 
    1038                 :          0 :         fe = me->fe;
    1039                 :            : 
    1040         [ #  # ]:          0 :         if (fe->type == CT_TYPE_PRE_CT) {
    1041         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, pre_ct_list) {
    1042         [ #  # ]:          0 :                         if (m_ent->compiled_rule != NULL) {
    1043                 :          0 :                                 ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
    1044         [ #  # ]:          0 :                                 if (ret != 0) {
    1045                 :          0 :                                         PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item");
    1046                 :          0 :                                         return -EINVAL;
    1047                 :            :                                 }
    1048                 :          0 :                                 m_ent->compiled_rule = NULL;
    1049                 :            :                         }
    1050                 :            : 
    1051                 :          0 :                         m_ent->pre_ct_parent = NULL;
    1052         [ #  # ]:          0 :                         LIST_REMOVE(m_ent, pre_ct_list);
    1053         [ #  # ]:          0 :                         if (m_ent->post_ct_parent == NULL)
    1054                 :          0 :                                 nfp_ct_merge_entry_destroy(m_ent);
    1055                 :            :                 }
    1056                 :            :         } else {
    1057         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &fe->children, post_ct_list) {
    1058         [ #  # ]:          0 :                         if (m_ent->compiled_rule != NULL) {
    1059                 :          0 :                                 ret = nfp_flow_destroy(dev, m_ent->compiled_rule, error);
    1060         [ #  # ]:          0 :                                 if (ret != 0) {
    1061                 :          0 :                                         PMD_DRV_LOG(ERR, "Could not alloc ct_flow_item");
    1062                 :          0 :                                         return -EINVAL;
    1063                 :            :                                 }
    1064                 :          0 :                                 m_ent->compiled_rule = NULL;
    1065                 :            :                         }
    1066                 :            : 
    1067                 :          0 :                         m_ent->post_ct_parent = NULL;
    1068         [ #  # ]:          0 :                         LIST_REMOVE(m_ent, post_ct_list);
    1069         [ #  # ]:          0 :                         if (m_ent->pre_ct_parent == NULL)
    1070                 :          0 :                                 nfp_ct_merge_entry_destroy(m_ent);
    1071                 :            :                 }
    1072                 :            :         }
    1073                 :            : 
    1074                 :          0 :         nfp_ct_flow_entry_destroy_partly(fe);
    1075                 :            : 
    1076                 :          0 :         return 0;
    1077                 :            : }
    1078                 :            : 
    1079                 :            : static inline bool
    1080                 :          0 : is_item_check_pass(const struct rte_flow_item *item1,
    1081                 :            :                 const struct rte_flow_item *item2,
    1082                 :            :                 uint8_t *cnt_same)
    1083                 :            : {
    1084                 :            :         bool pass;
    1085                 :            :         uint32_t i;
    1086                 :            :         size_t size;
    1087                 :          0 :         const char *key1 = item1->spec;
    1088                 :          0 :         const char *key2 = item2->spec;
    1089                 :          0 :         const char *mask1 = item1->mask;
    1090                 :          0 :         const char *mask2 = item2->mask;
    1091                 :            : 
    1092         [ #  # ]:          0 :         if (item1->type != item2->type)
    1093                 :            :                 return true;
    1094                 :            : 
    1095                 :          0 :         pass = nfp_flow_item_conf_size_get(item1->type, &size);
    1096         [ #  # ]:          0 :         if (!pass)
    1097                 :            :                 return false;
    1098                 :            : 
    1099         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1100         [ #  # ]:          0 :                 if ((key1[i] & mask1[i] & mask2[i]) ^ (key2[i] & mask1[i] & mask2[i]))
    1101                 :            :                         return false;
    1102                 :            :         }
    1103                 :            : 
    1104                 :          0 :         *cnt_same = *cnt_same + 1;
    1105                 :            : 
    1106                 :          0 :         return true;
    1107                 :            : }
    1108                 :            : 
    1109                 :            : static bool
    1110                 :          0 : nfp_ct_merge_items_check(struct rte_flow_item *items1,
    1111                 :            :                 struct rte_flow_item *items2,
    1112                 :            :                 uint8_t *cnt_same)
    1113                 :            : {
    1114                 :            :         bool pass;
    1115                 :            :         bool is_tun_flow_1;
    1116                 :            :         bool is_tun_flow_2;
    1117                 :            :         const struct rte_flow_item *item1;
    1118                 :            :         const struct rte_flow_item *item2;
    1119                 :          0 :         const struct rte_flow_item *inner_item1 = NULL;
    1120                 :          0 :         const struct rte_flow_item *inner_item2 = NULL;
    1121                 :            : 
    1122                 :          0 :         is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner_item1);
    1123                 :          0 :         is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner_item2);
    1124                 :            : 
    1125         [ #  # ]:          0 :         if (is_tun_flow_1) {
    1126         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1127                 :            :                         /* Outer layer */
    1128         [ #  # ]:          0 :                         for (item1 = items1; item1 != inner_item1; item1++) {
    1129         [ #  # ]:          0 :                                 for (item2 = items2; item2 != inner_item2; item2++) {
    1130                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1131         [ #  # ]:          0 :                                         if (!pass)
    1132                 :            :                                                 return false;
    1133                 :            :                                 }
    1134                 :            :                         }
    1135                 :            :                         /* Inner layer */
    1136         [ #  # ]:          0 :                         for (item1 = inner_item1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1137         [ #  # ]:          0 :                                 for (item2 = inner_item2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1138                 :          0 :                                                 item2++) {
    1139                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1140         [ #  # ]:          0 :                                         if (!pass)
    1141                 :            :                                                 return false;
    1142                 :            :                                 }
    1143                 :            :                         }
    1144                 :            :                 } else {
    1145         [ #  # ]:          0 :                         for (item1 = items1; item1 != inner_item1; item1++) {
    1146         [ #  # ]:          0 :                                 for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1147                 :          0 :                                                 item2++) {
    1148                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1149         [ #  # ]:          0 :                                         if (!pass)
    1150                 :            :                                                 return false;
    1151                 :            :                                 }
    1152                 :            :                         }
    1153                 :            :                 }
    1154                 :            :         } else {
    1155         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1156         [ #  # ]:          0 :                         for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1157         [ #  # ]:          0 :                                 for (item2 = items2; item2 != inner_item2; item2++) {
    1158                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1159         [ #  # ]:          0 :                                         if (!pass)
    1160                 :            :                                                 return false;
    1161                 :            :                                 }
    1162                 :            :                         }
    1163                 :            :                 } else {
    1164         [ #  # ]:          0 :                         for (item1 = items1; item1->type != RTE_FLOW_ITEM_TYPE_END; item1++) {
    1165         [ #  # ]:          0 :                                 for (item2 = items2; item2->type != RTE_FLOW_ITEM_TYPE_END;
    1166                 :          0 :                                                 item2++) {
    1167                 :          0 :                                         pass = is_item_check_pass(item1, item2, cnt_same);
    1168         [ #  # ]:          0 :                                         if (!pass)
    1169                 :            :                                                 return false;
    1170                 :            :                                 }
    1171                 :            :                         }
    1172                 :            :                 }
    1173                 :            :         }
    1174                 :            : 
    1175                 :            :         return true;
    1176                 :            : }
    1177                 :            : 
    1178                 :            : static inline bool
    1179                 :            : is_action_pattern_check_pass(struct rte_flow_item *items,
    1180                 :            :                 enum rte_flow_item_type type)
    1181                 :            : {
    1182                 :            :         struct rte_flow_item *item;
    1183                 :            : 
    1184   [ #  #  #  #  :          0 :         for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
          #  #  #  #  #  
                #  #  # ]
    1185   [ #  #  #  #  :          0 :                 if (item->type == type)
          #  #  #  #  #  
                #  #  # ]
    1186                 :            :                         return false;
    1187                 :            :         }
    1188                 :            : 
    1189                 :            :         return true;
    1190                 :            : }
    1191                 :            : 
    1192                 :            : static bool
    1193                 :          0 : nfp_ct_merge_action_check(struct rte_flow_action *action,
    1194                 :            :                 struct rte_flow_item *items)
    1195                 :            : {
    1196                 :            :         bool pass = true;
    1197                 :            : 
    1198   [ #  #  #  #  :          0 :         switch (action->type) {
                      # ]
    1199                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:    /* FALLTHROUGH */
    1200                 :            :         case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
    1201                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_ETH);
    1202                 :            :                 break;
    1203                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:   /* FALLTHROUGH */
    1204                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:   /* FALLTHROUGH */
    1205                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
    1206                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV4);
    1207                 :            :                 break;
    1208                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:   /* FALLTHROUGH */
    1209                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:   /* FALLTHROUGH */
    1210                 :            :         case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:
    1211                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_IPV6);
    1212                 :            :                 break;
    1213                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:    /* FALLTHROUGH */
    1214                 :            :         case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    1215                 :            :                 pass = is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_UDP);
    1216                 :          0 :                 pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_TCP);
    1217                 :          0 :                 pass |= is_action_pattern_check_pass(items, RTE_FLOW_ITEM_TYPE_SCTP);
    1218                 :          0 :                 break;
    1219                 :            :         default:
    1220                 :            :                 break;
    1221                 :            :         }
    1222                 :            : 
    1223                 :          0 :         return pass;
    1224                 :            : }
    1225                 :            : 
    1226                 :            : static bool
    1227                 :          0 : nfp_ct_merge_actions_check(struct rte_flow_action *actions,
    1228                 :            :                 struct rte_flow_item *items,
    1229                 :            :                 uint8_t *cnt_same)
    1230                 :            : {
    1231                 :            :         bool pass = true;
    1232                 :            :         struct rte_flow_action *action;
    1233                 :            : 
    1234         [ #  # ]:          0 :         for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1235      [ #  #  # ]:          0 :                 switch (action->type) {
    1236                 :          0 :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:    /* FALLTHROUGH */
    1237                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:    /* FALLTHROUGH */
    1238                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:   /* FALLTHROUGH */
    1239                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:   /* FALLTHROUGH */
    1240                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:  /* FALLTHROUGH */
    1241                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:   /* FALLTHROUGH */
    1242                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:   /* FALLTHROUGH */
    1243                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP:  /* FALLTHROUGH */
    1244                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:     /* FALLTHROUGH */
    1245                 :            :                 case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
    1246                 :          0 :                         pass = nfp_ct_merge_action_check(action, items);
    1247                 :          0 :                         break;
    1248                 :          0 :                 case RTE_FLOW_ACTION_TYPE_CONNTRACK: /* FALLTHROUGH */
    1249                 :            :                 case RTE_FLOW_ACTION_TYPE_JUMP:      /* FALLTHROUGH */
    1250                 :            :                 case RTE_FLOW_ACTION_TYPE_COUNT:     /* FALLTHROUGH */
    1251                 :            :                 case RTE_FLOW_ACTION_TYPE_DROP:      /* FALLTHROUGH */
    1252                 :            :                 case RTE_FLOW_ACTION_TYPE_VOID:
    1253                 :          0 :                         *cnt_same = *cnt_same + 1;
    1254                 :          0 :                         break;
    1255                 :            :                 default:
    1256                 :            :                         pass = false;
    1257                 :            :                         break;
    1258                 :            :                 }
    1259                 :            :         }
    1260                 :            : 
    1261                 :          0 :         return pass;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : static void
    1265                 :          0 : nfp_ct_merge_item_real(const struct rte_flow_item *item_src,
    1266                 :            :                 struct rte_flow_item *item_dst)
    1267                 :            : {
    1268                 :            :         uint32_t i;
    1269                 :            :         char *key_dst;
    1270                 :            :         char *mask_dst;
    1271                 :          0 :         size_t size = 0;
    1272                 :            :         const char *key_src;
    1273                 :            :         const char *mask_src;
    1274                 :            : 
    1275                 :          0 :         key_src = item_src->spec;
    1276                 :          0 :         mask_src = item_src->mask;
    1277                 :          0 :         key_dst = (char *)(ptrdiff_t)item_dst->spec;
    1278                 :          0 :         mask_dst = (char *)(ptrdiff_t)item_dst->mask;
    1279                 :          0 :         nfp_flow_item_conf_size_get(item_src->type, &size);
    1280                 :            : 
    1281         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1282                 :          0 :                 key_dst[i] |= key_src[i];
    1283                 :          0 :                 mask_dst[i] |= mask_src[i];
    1284                 :            :         }
    1285                 :          0 : }
    1286                 :            : 
    1287                 :            : static bool
    1288                 :          0 : nfp_ct_merge_item(uint32_t index,
    1289                 :            :                 const struct rte_flow_item *item1,
    1290                 :            :                 const struct rte_flow_item *item2_start,
    1291                 :            :                 const struct rte_flow_item *item2_end,
    1292                 :            :                 struct nfp_ct_merge_entry *merge_entry)
    1293                 :            : {
    1294                 :            :         struct rte_flow_item *item;
    1295                 :            :         const struct rte_flow_item *item2;
    1296                 :            : 
    1297                 :            :         /* Copy to the merged items */
    1298                 :          0 :         item = &merge_entry->rule.items[index];
    1299                 :          0 :         *item = *item1;
    1300                 :            : 
    1301                 :            :         item2 = item2_start;
    1302         [ #  # ]:          0 :         if (item2_end != NULL) {
    1303         [ #  # ]:          0 :                 for (; item2 != item2_end; item2++) {
    1304         [ #  # ]:          0 :                         if (item1->type == item2->type) {
    1305                 :          0 :                                 nfp_ct_merge_item_real(item2, item);
    1306                 :          0 :                                 return true;
    1307                 :            :                         }
    1308                 :            :                 }
    1309                 :            :         } else {
    1310         [ #  # ]:          0 :                 for (; item2->type != RTE_FLOW_ITEM_TYPE_END; item2++) {
    1311         [ #  # ]:          0 :                         if (item1->type == item2->type) {
    1312                 :          0 :                                 nfp_ct_merge_item_real(item2, item);
    1313                 :          0 :                                 return true;
    1314                 :            :                         }
    1315                 :            :                 }
    1316                 :            :         }
    1317                 :            : 
    1318                 :            :         return false;
    1319                 :            : }
    1320                 :            : 
    1321                 :            : static void
    1322                 :          0 : nfp_ct_merge_items(struct nfp_ct_merge_entry *merge_entry)
    1323                 :            : {
    1324                 :            :         uint32_t index = 0;
    1325                 :            :         bool is_tun_flow_1;
    1326                 :            :         bool is_tun_flow_2;
    1327                 :            :         struct rte_flow_item *items1;
    1328                 :            :         struct rte_flow_item *items2;
    1329                 :            :         struct rte_flow_item *merge_item;
    1330                 :            :         const struct rte_flow_item *item;
    1331                 :          0 :         const struct rte_flow_item *inner1 = NULL;
    1332                 :          0 :         const struct rte_flow_item *inner2 = NULL;
    1333                 :            : 
    1334                 :          0 :         items1 = merge_entry->pre_ct_parent->rule.items;
    1335                 :          0 :         items2 = merge_entry->post_ct_parent->rule.items;
    1336                 :          0 :         is_tun_flow_1 = nfp_flow_inner_item_get(items1, &inner1);
    1337                 :          0 :         is_tun_flow_2 = nfp_flow_inner_item_get(items2, &inner2);
    1338                 :            : 
    1339         [ #  # ]:          0 :         if (is_tun_flow_1) {
    1340         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1341                 :            :                         /* Outer layer */
    1342         [ #  # ]:          0 :                         for (item = items1; item != inner1; item++, index++) {
    1343         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
    1344                 :          0 :                                         items2++;
    1345                 :            :                         }
    1346                 :            : 
    1347                 :            :                         /* Copy the remainning outer layer items */
    1348         [ #  # ]:          0 :                         for (item = items2; item != inner2; item++, index++) {
    1349                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1350                 :          0 :                                 *merge_item = *item;
    1351                 :            :                         }
    1352                 :            : 
    1353                 :            :                         /* Inner layer */
    1354         [ #  # ]:          0 :                         for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1355         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, inner2, NULL, merge_entry))
    1356                 :          0 :                                         items2++;
    1357                 :            :                         }
    1358                 :            : 
    1359                 :            :                         /* Copy the remainning inner layer items */
    1360         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1361                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1362                 :          0 :                                 *merge_item = *item;
    1363                 :            :                         }
    1364                 :            :                 } else {
    1365         [ #  # ]:          0 :                         for (item = items1; item != inner1; item++, index++) {
    1366         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
    1367                 :          0 :                                         items2++;
    1368                 :            :                         }
    1369                 :            : 
    1370                 :            :                         /* Copy the remainning items */
    1371         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1372                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1373                 :          0 :                                 *merge_item = *item;
    1374                 :            :                         }
    1375                 :            : 
    1376                 :            :                         /* Copy the inner layer items */
    1377         [ #  # ]:          0 :                         for (item = inner1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1378                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1379                 :          0 :                                 *merge_item = *item;
    1380                 :            :                         }
    1381                 :            :                 }
    1382                 :            :         } else {
    1383         [ #  # ]:          0 :                 if (is_tun_flow_2) {
    1384         [ #  # ]:          0 :                         for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1385         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, inner2, merge_entry))
    1386                 :          0 :                                         items2++;
    1387                 :            :                         }
    1388                 :            : 
    1389                 :            :                         /* Copy the remainning items */
    1390         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1391                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1392                 :          0 :                                 *merge_item = *item;
    1393                 :            :                         }
    1394                 :            :                 } else {
    1395         [ #  # ]:          0 :                         for (item = items1; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1396         [ #  # ]:          0 :                                 if (nfp_ct_merge_item(index, item, items2, NULL, merge_entry))
    1397                 :          0 :                                         items2++;
    1398                 :            :                         }
    1399                 :            : 
    1400                 :            :                         /* Copy the remainning items */
    1401         [ #  # ]:          0 :                         for (item = items2; item->type != RTE_FLOW_ITEM_TYPE_END; item++, index++) {
    1402                 :          0 :                                 merge_item = &merge_entry->rule.items[index];
    1403                 :          0 :                                 *merge_item = *item;
    1404                 :            :                         }
    1405                 :            :                 }
    1406                 :            :         }
    1407                 :          0 : }
    1408                 :            : 
    1409                 :            : static void
    1410                 :          0 : nfp_ct_merge_actions(struct nfp_ct_merge_entry *merge_entry)
    1411                 :            : {
    1412                 :            :         struct rte_flow_action *action;
    1413                 :            :         struct rte_flow_action *merge_actions;
    1414                 :            : 
    1415                 :          0 :         merge_actions = merge_entry->rule.actions;
    1416                 :            : 
    1417                 :          0 :         action = merge_entry->pre_ct_parent->rule.actions;
    1418         [ #  # ]:          0 :         for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1419         [ #  # ]:          0 :                 if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK ||
    1420                 :            :                                 action->type == RTE_FLOW_ACTION_TYPE_JUMP)
    1421                 :          0 :                         continue;
    1422                 :            : 
    1423                 :          0 :                 *merge_actions = *action;
    1424                 :          0 :                 merge_actions++;
    1425                 :            :         }
    1426                 :            : 
    1427                 :          0 :         action = merge_entry->post_ct_parent->rule.actions;
    1428         [ #  # ]:          0 :         for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
    1429                 :          0 :                 *merge_actions = *action;
    1430                 :          0 :                 merge_actions++;
    1431                 :            :         }
    1432                 :          0 : }
    1433                 :            : 
    1434                 :            : static bool
    1435                 :          0 : nfp_ct_do_flow_merge(struct nfp_ct_zone_entry *ze,
    1436                 :            :                 struct nfp_ct_flow_entry *pre_ct_entry,
    1437                 :            :                 struct nfp_ct_flow_entry *post_ct_entry)
    1438                 :            : {
    1439                 :            :         bool ret;
    1440                 :            :         uint64_t new_cookie[2];
    1441                 :          0 :         uint8_t cnt_same_item = 0;
    1442                 :          0 :         uint8_t cnt_same_action = 0;
    1443                 :            :         struct nfp_ct_merge_entry *merge_entry;
    1444                 :            : 
    1445         [ #  # ]:          0 :         if (pre_ct_entry->repr != post_ct_entry->repr)
    1446                 :            :                 return true;
    1447                 :            : 
    1448                 :          0 :         ret = nfp_ct_merge_items_check(pre_ct_entry->rule.items,
    1449                 :            :                         post_ct_entry->rule.items, &cnt_same_item);
    1450         [ #  # ]:          0 :         if (!ret)
    1451                 :            :                 return true;
    1452                 :            : 
    1453                 :          0 :         ret = nfp_ct_merge_actions_check(pre_ct_entry->rule.actions,
    1454                 :            :                         post_ct_entry->rule.items, &cnt_same_action);
    1455         [ #  # ]:          0 :         if (!ret)
    1456                 :            :                 return true;
    1457                 :            : 
    1458                 :          0 :         new_cookie[0] = pre_ct_entry->cookie;
    1459                 :          0 :         new_cookie[1] = post_ct_entry->cookie;
    1460                 :          0 :         merge_entry = nfp_ct_merge_table_search(ze, (char *)&new_cookie, sizeof(uint64_t) * 2);
    1461         [ #  # ]:          0 :         if (merge_entry != NULL)
    1462                 :            :                 return true;
    1463                 :            : 
    1464                 :          0 :         merge_entry = rte_zmalloc("ct_merge_entry", sizeof(*merge_entry), 0);
    1465         [ #  # ]:          0 :         if (merge_entry == NULL) {
    1466                 :          0 :                 PMD_DRV_LOG(ERR, "Malloc memory for ct merge entry failed");
    1467                 :          0 :                 return false;
    1468                 :            :         }
    1469                 :            : 
    1470                 :          0 :         merge_entry->ze = ze;
    1471                 :          0 :         merge_entry->pre_ct_parent = pre_ct_entry;
    1472                 :          0 :         merge_entry->post_ct_parent = post_ct_entry;
    1473         [ #  # ]:          0 :         rte_memcpy(merge_entry->cookie, new_cookie, sizeof(new_cookie));
    1474                 :          0 :         merge_entry->rule.items_cnt = pre_ct_entry->rule.items_cnt +
    1475                 :          0 :                         post_ct_entry->rule.items_cnt - cnt_same_item - 1;
    1476                 :          0 :         merge_entry->rule.actions_cnt = pre_ct_entry->rule.actions_cnt +
    1477                 :          0 :                         post_ct_entry->rule.actions_cnt - cnt_same_action - 1;
    1478                 :            : 
    1479                 :          0 :         merge_entry->rule.items = rte_zmalloc("ct_flow_item",
    1480                 :          0 :                         sizeof(struct rte_flow_item) * merge_entry->rule.items_cnt, 0);
    1481         [ #  # ]:          0 :         if (merge_entry->rule.items == NULL) {
    1482                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc items for merged flow");
    1483                 :          0 :                 goto merge_exit;
    1484                 :            :         }
    1485                 :            : 
    1486                 :          0 :         merge_entry->rule.actions = rte_zmalloc("ct_flow_action",
    1487                 :          0 :                         sizeof(struct rte_flow_action) * merge_entry->rule.actions_cnt, 0);
    1488         [ #  # ]:          0 :         if (merge_entry->rule.actions == NULL) {
    1489                 :          0 :                 PMD_DRV_LOG(ERR, "Could not alloc actions for merged flow");
    1490                 :          0 :                 goto free_items;
    1491                 :            :         }
    1492                 :            : 
    1493                 :          0 :         nfp_ct_merge_items(merge_entry);
    1494                 :          0 :         nfp_ct_merge_actions(merge_entry);
    1495                 :            : 
    1496                 :            :         /* Add this entry to the pre_ct and post_ct lists */
    1497         [ #  # ]:          0 :         LIST_INSERT_HEAD(&pre_ct_entry->children, merge_entry, pre_ct_list);
    1498         [ #  # ]:          0 :         LIST_INSERT_HEAD(&post_ct_entry->children, merge_entry, post_ct_list);
    1499                 :            : 
    1500                 :          0 :         ret = nfp_ct_merge_table_add(ze, merge_entry);
    1501         [ #  # ]:          0 :         if (!ret) {
    1502                 :          0 :                 PMD_DRV_LOG(ERR, "Add into ct merge table failed");
    1503                 :          0 :                 goto free_actions;
    1504                 :            :         }
    1505                 :            : 
    1506                 :            :         /* Send to firmware */
    1507                 :          0 :         ret = nfp_ct_offload_add(pre_ct_entry->repr, merge_entry);
    1508         [ #  # ]:          0 :         if (ret != 0) {
    1509                 :          0 :                 PMD_DRV_LOG(ERR, "Send the merged flow to firmware failed");
    1510                 :          0 :                 goto merge_table_del;
    1511                 :            :         }
    1512                 :            : 
    1513                 :            :         return true;
    1514                 :            : 
    1515                 :            : merge_table_del:
    1516                 :          0 :         nfp_ct_merge_table_delete(ze, merge_entry);
    1517                 :          0 : free_actions:
    1518                 :          0 :         rte_free(merge_entry->rule.actions);
    1519                 :          0 : free_items:
    1520                 :          0 :         rte_free(merge_entry->rule.items);
    1521                 :          0 : merge_exit:
    1522         [ #  # ]:          0 :         LIST_REMOVE(merge_entry, post_ct_list);
    1523         [ #  # ]:          0 :         LIST_REMOVE(merge_entry, pre_ct_list);
    1524                 :          0 :         rte_free(merge_entry);
    1525                 :            : 
    1526                 :          0 :         return ret;
    1527                 :            : }
    1528                 :            : 
    1529                 :            : static bool
    1530                 :          0 : nfp_ct_merge_flow_entries(struct nfp_ct_flow_entry *fe,
    1531                 :            :                 struct nfp_ct_zone_entry *ze_src,
    1532                 :            :                 struct nfp_ct_zone_entry *ze_dst)
    1533                 :            : {
    1534                 :            :         bool ret;
    1535                 :            :         struct nfp_ct_flow_entry *fe_tmp;
    1536                 :            : 
    1537         [ #  # ]:          0 :         if (fe->type == CT_TYPE_PRE_CT) {
    1538         [ #  # ]:          0 :                 LIST_FOREACH(fe_tmp, &ze_src->post_ct_list, post_ct_list) {
    1539                 :          0 :                         ret = nfp_ct_do_flow_merge(ze_dst, fe, fe_tmp);
    1540         [ #  # ]:          0 :                         if (!ret) {
    1541                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge for ct pre flow failed");
    1542                 :          0 :                                 return false;
    1543                 :            :                         }
    1544                 :            :                 }
    1545                 :            :         } else {
    1546         [ #  # ]:          0 :                 LIST_FOREACH(fe_tmp, &ze_src->pre_ct_list, pre_ct_list) {
    1547                 :          0 :                         ret = nfp_ct_do_flow_merge(ze_dst, fe_tmp, fe);
    1548         [ #  # ]:          0 :                         if (!ret) {
    1549                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge for ct post flow failed");
    1550                 :          0 :                                 return false;
    1551                 :            :                         }
    1552                 :            :                 }
    1553                 :            :         }
    1554                 :            : 
    1555                 :            :         return true;
    1556                 :            : }
    1557                 :            : 
    1558                 :            : static bool
    1559                 :          0 : nfp_flow_handle_pre_ct(const struct rte_flow_item *ct_item,
    1560                 :            :                 struct nfp_flower_representor *representor,
    1561                 :            :                 const struct rte_flow_item items[],
    1562                 :            :                 const struct rte_flow_action actions[],
    1563                 :            :                 uint64_t cookie)
    1564                 :            : {
    1565                 :            :         bool ret;
    1566                 :            :         struct nfp_flow_priv *priv;
    1567                 :            :         struct nfp_ct_zone_entry *ze;
    1568                 :            :         struct nfp_ct_flow_entry *fe;
    1569                 :          0 :         const struct ct_data *ct = ct_item->spec;
    1570                 :            : 
    1571                 :          0 :         priv = representor->app_fw_flower->flow_priv;
    1572                 :          0 :         ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, false);
    1573         [ #  # ]:          0 :         if (ze == NULL) {
    1574                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct zone entry");
    1575                 :          0 :                 return false;
    1576                 :            :         }
    1577                 :            : 
    1578                 :            :         /* Add entry to pre_ct_list */
    1579                 :          0 :         fe = nfp_ct_flow_entry_get(ze, representor, items, actions, cookie);
    1580         [ #  # ]:          0 :         if (fe == NULL) {
    1581                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct flow entry");
    1582                 :          0 :                 goto ct_zone_entry_free;
    1583                 :            :         }
    1584                 :            : 
    1585                 :          0 :         fe->type = CT_TYPE_PRE_CT;
    1586         [ #  # ]:          0 :         LIST_INSERT_HEAD(&ze->pre_ct_list, fe, pre_ct_list);
    1587                 :            : 
    1588                 :          0 :         ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1589         [ #  # ]:          0 :         if (!ret) {
    1590                 :          0 :                 PMD_DRV_LOG(ERR, "Merge ct flow entries failed");
    1591                 :          0 :                 goto ct_flow_entry_free;
    1592                 :            :         }
    1593                 :            : 
    1594                 :            :         /* Need to check and merge with tables in the wc_zone as well */
    1595         [ #  # ]:          0 :         if (priv->ct_zone_wc != NULL) {
    1596                 :          0 :                 ret = nfp_ct_merge_flow_entries(fe, priv->ct_zone_wc, ze);
    1597         [ #  # ]:          0 :                 if (!ret) {
    1598                 :          0 :                         PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed");
    1599                 :          0 :                         goto ct_flow_entry_free;
    1600                 :            :                 }
    1601                 :            :         }
    1602                 :            : 
    1603                 :            :         return true;
    1604                 :            : 
    1605                 :          0 : ct_flow_entry_free:
    1606                 :          0 :         nfp_ct_flow_entry_destroy(fe);
    1607                 :            : 
    1608                 :          0 : ct_zone_entry_free:
    1609                 :          0 :         nfp_ct_zone_entry_free(ze, false);
    1610                 :            : 
    1611                 :          0 :         return false;
    1612                 :            : }
    1613                 :            : 
    1614                 :            : static bool
    1615                 :          0 : nfp_flow_handle_post_ct(const struct rte_flow_item *ct_item,
    1616                 :            :                 struct nfp_flower_representor *representor,
    1617                 :            :                 const struct rte_flow_item items[],
    1618                 :            :                 const struct rte_flow_action actions[],
    1619                 :            :                 uint64_t cookie)
    1620                 :            : {
    1621                 :            :         bool ret;
    1622                 :            :         void *next_data;
    1623                 :          0 :         uint32_t iter = 0;
    1624                 :            :         const void *next_key;
    1625                 :            :         bool wildcard = false;
    1626                 :            :         struct nfp_flow_priv *priv;
    1627                 :            :         struct nfp_ct_zone_entry *ze;
    1628                 :            :         struct nfp_ct_flow_entry *fe;
    1629                 :          0 :         const struct ct_data *ct = ct_item->spec;
    1630                 :          0 :         const struct ct_data *ct_mask = ct_item->mask;
    1631                 :            : 
    1632         [ #  # ]:          0 :         if (ct_mask->ct_zone == 0) {
    1633                 :            :                 wildcard = true;
    1634         [ #  # ]:          0 :         } else if (ct_mask->ct_zone != UINT16_MAX) {
    1635                 :          0 :                 PMD_DRV_LOG(ERR, "Partially wildcard ct_zone is not supported");
    1636                 :          0 :                 return false;
    1637                 :            :         }
    1638                 :            : 
    1639                 :          0 :         priv = representor->app_fw_flower->flow_priv;
    1640                 :          0 :         ze = nfp_ct_zone_entry_get(priv, ct->ct_zone, wildcard);
    1641         [ #  # ]:          0 :         if (ze == NULL) {
    1642                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct zone entry");
    1643                 :          0 :                 return false;
    1644                 :            :         }
    1645                 :            : 
    1646                 :            :         /* Add entry to post_ct_list */
    1647                 :          0 :         fe = nfp_ct_flow_entry_get(ze, representor, items, actions, cookie);
    1648         [ #  # ]:          0 :         if (fe == NULL) {
    1649                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get ct flow entry");
    1650                 :          0 :                 goto ct_zone_entry_free;
    1651                 :            :         }
    1652                 :            : 
    1653                 :          0 :         fe->type = CT_TYPE_POST_CT;
    1654         [ #  # ]:          0 :         LIST_INSERT_HEAD(&ze->post_ct_list, fe, post_ct_list);
    1655                 :            : 
    1656         [ #  # ]:          0 :         if (wildcard) {
    1657         [ #  # ]:          0 :                 while (rte_hash_iterate(priv->ct_zone_table, &next_key, &next_data, &iter) >= 0) {
    1658                 :          0 :                         ze = (struct nfp_ct_zone_entry *)next_data;
    1659                 :          0 :                         ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1660         [ #  # ]:          0 :                         if (!ret) {
    1661                 :          0 :                                 PMD_DRV_LOG(ERR, "Merge ct flow entries wildcast failed");
    1662                 :          0 :                                 break;
    1663                 :            :                         }
    1664                 :            :                 }
    1665                 :            :         } else {
    1666                 :          0 :                 ret = nfp_ct_merge_flow_entries(fe, ze, ze);
    1667                 :            :         }
    1668                 :            : 
    1669         [ #  # ]:          0 :         if (!ret)
    1670                 :          0 :                 goto ct_flow_entry_free;
    1671                 :            : 
    1672                 :            :         return true;
    1673                 :            : 
    1674                 :            : ct_flow_entry_free:
    1675                 :          0 :         nfp_ct_flow_entry_destroy(fe);
    1676                 :            : 
    1677                 :          0 : ct_zone_entry_free:
    1678                 :          0 :         nfp_ct_zone_entry_free(ze, wildcard);
    1679                 :            : 
    1680                 :          0 :         return false;
    1681                 :            : }
    1682                 :            : 
    1683                 :            : struct rte_flow *
    1684                 :          0 : nfp_ct_flow_setup(struct nfp_flower_representor *representor,
    1685                 :            :                 const struct rte_flow_item items[],
    1686                 :            :                 const struct rte_flow_action actions[],
    1687                 :            :                 const struct rte_flow_item *ct_item,
    1688                 :            :                 bool validate_flag,
    1689                 :            :                 uint64_t cookie)
    1690                 :            : {
    1691                 :            :         const struct ct_data *ct;
    1692                 :            : 
    1693         [ #  # ]:          0 :         if (ct_item == NULL)
    1694                 :            :                 return NULL;
    1695                 :            : 
    1696         [ #  # ]:          0 :         ct = ct_item->spec;
    1697                 :            : 
    1698                 :            :         if (is_ct_commit_flow(ct)) {
    1699                 :          0 :                 return nfp_flow_process(representor, &items[1], actions,
    1700                 :            :                                 validate_flag, cookie, false, false);
    1701                 :            :         }
    1702                 :            : 
    1703                 :            :         if (is_post_ct_flow(ct)) {
    1704         [ #  # ]:          0 :                 if (nfp_flow_handle_post_ct(ct_item, representor, &items[1],
    1705                 :            :                                 actions, cookie)) {
    1706                 :          0 :                         return nfp_flow_process(representor, &items[1], actions,
    1707                 :            :                                         validate_flag, cookie, false, false);
    1708                 :            :                 }
    1709                 :            : 
    1710                 :          0 :                 PMD_DRV_LOG(ERR, "Handle nfp post ct flow failed.");
    1711                 :          0 :                 return NULL;
    1712                 :            :         }
    1713                 :            : 
    1714         [ #  # ]:          0 :         if (is_pre_ct_flow(ct, actions)) {
    1715         [ #  # ]:          0 :                 if (nfp_flow_handle_pre_ct(ct_item, representor, &items[1],
    1716                 :            :                                 actions, cookie)) {
    1717                 :          0 :                         return nfp_flow_process(representor, &items[1], actions,
    1718                 :            :                                         validate_flag, cookie, false, false);
    1719                 :            :                 }
    1720                 :            : 
    1721                 :          0 :                 PMD_DRV_LOG(ERR, "Handle nfp pre ct flow failed.");
    1722                 :          0 :                 return NULL;
    1723                 :            :         }
    1724                 :            : 
    1725                 :          0 :         PMD_DRV_LOG(ERR, "Unsupported ct flow type.");
    1726                 :          0 :         return NULL;
    1727                 :            : }
    1728                 :            : 
    1729                 :            : static inline void
    1730                 :          0 : nfp_ct_flow_stats_update(struct nfp_flow_priv *priv,
    1731                 :            :                 struct nfp_ct_merge_entry *m_ent)
    1732                 :            : {
    1733                 :            :         uint32_t ctx_id;
    1734                 :            :         struct nfp_fl_stats *merge_stats;
    1735                 :            : 
    1736                 :          0 :         ctx_id = m_ent->ctx_id;
    1737                 :          0 :         merge_stats = &priv->stats[ctx_id];
    1738                 :            : 
    1739                 :          0 :         m_ent->pre_ct_parent->stats.bytes  += merge_stats->bytes;
    1740                 :          0 :         m_ent->pre_ct_parent->stats.pkts   += merge_stats->pkts;
    1741                 :          0 :         m_ent->post_ct_parent->stats.bytes += merge_stats->bytes;
    1742                 :          0 :         m_ent->post_ct_parent->stats.pkts  += merge_stats->pkts;
    1743                 :            : 
    1744                 :          0 :         merge_stats->bytes = 0;
    1745                 :          0 :         merge_stats->pkts = 0;
    1746                 :          0 : }
    1747                 :            : 
    1748                 :            : struct nfp_fl_stats *
    1749                 :          0 : nfp_ct_flow_stats_get(struct nfp_flow_priv *priv,
    1750                 :            :                 struct nfp_ct_map_entry *me)
    1751                 :            : {
    1752                 :            :         struct nfp_ct_merge_entry *m_ent;
    1753                 :            : 
    1754                 :          0 :         rte_spinlock_lock(&priv->stats_lock);
    1755                 :            : 
    1756         [ #  # ]:          0 :         if (me->fe->type == CT_TYPE_PRE_CT) {
    1757         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &me->fe->children, pre_ct_list)
    1758                 :          0 :                         nfp_ct_flow_stats_update(priv, m_ent);
    1759                 :            :         } else {
    1760         [ #  # ]:          0 :                 LIST_FOREACH(m_ent, &me->fe->children, post_ct_list)
    1761                 :          0 :                         nfp_ct_flow_stats_update(priv, m_ent);
    1762                 :            :         }
    1763                 :            : 
    1764                 :            :         rte_spinlock_unlock(&priv->stats_lock);
    1765                 :            : 
    1766                 :          0 :         return &me->fe->stats;
    1767                 :            : }

Generated by: LCOV version 1.14