LCOV - code coverage report
Current view: top level - lib/pipeline - rte_table_action.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 990 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 33 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 1372 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2018 Intel Corporation
       3                 :            :  */
       4                 :            : #include <stdlib.h>
       5                 :            : #include <string.h>
       6                 :            : 
       7                 :            : #include <rte_common.h>
       8                 :            : #include <rte_byteorder.h>
       9                 :            : #include <rte_cycles.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : #include <rte_memcpy.h>
      12                 :            : #include <rte_ether.h>
      13                 :            : #include <rte_ip.h>
      14                 :            : #include <rte_tcp.h>
      15                 :            : #include <rte_udp.h>
      16                 :            : #include <rte_vxlan.h>
      17                 :            : #include <rte_cryptodev.h>
      18                 :            : 
      19                 :            : #include "rte_table_action.h"
      20                 :            : 
      21                 :            : #define rte_htons rte_cpu_to_be_16
      22                 :            : #define rte_htonl rte_cpu_to_be_32
      23                 :            : 
      24                 :            : #define rte_ntohs rte_be_to_cpu_16
      25                 :            : #define rte_ntohl rte_be_to_cpu_32
      26                 :            : 
      27                 :            : /**
      28                 :            :  * RTE_TABLE_ACTION_FWD
      29                 :            :  */
      30                 :            : #define fwd_data rte_pipeline_table_entry
      31                 :            : 
      32                 :            : static int
      33                 :            : fwd_apply(struct fwd_data *data,
      34                 :            :         struct rte_table_action_fwd_params *p)
      35                 :            : {
      36                 :          0 :         data->action = p->action;
      37                 :            : 
      38         [ #  # ]:          0 :         if (p->action == RTE_PIPELINE_ACTION_PORT)
      39                 :          0 :                 data->port_id = p->id;
      40                 :            : 
      41         [ #  # ]:          0 :         if (p->action == RTE_PIPELINE_ACTION_TABLE)
      42                 :          0 :                 data->table_id = p->id;
      43                 :            : 
      44                 :            :         return 0;
      45                 :            : }
      46                 :            : 
      47                 :            : /**
      48                 :            :  * RTE_TABLE_ACTION_LB
      49                 :            :  */
      50                 :            : static int
      51                 :            : lb_cfg_check(struct rte_table_action_lb_config *cfg)
      52                 :            : {
      53         [ #  # ]:          0 :         if ((cfg == NULL) ||
      54   [ #  #  #  # ]:          0 :                 (cfg->key_size < RTE_TABLE_ACTION_LB_KEY_SIZE_MIN) ||
      55                 :            :                 (cfg->key_size > RTE_TABLE_ACTION_LB_KEY_SIZE_MAX) ||
      56                 :          0 :                 (!rte_is_power_of_2(cfg->key_size)) ||
      57         [ #  # ]:          0 :                 (cfg->f_hash == NULL))
      58                 :            :                 return -1;
      59                 :            : 
      60                 :            :         return 0;
      61                 :            : }
      62                 :            : 
      63                 :            : struct __rte_packed_begin lb_data {
      64                 :            :         uint32_t out[RTE_TABLE_ACTION_LB_TABLE_SIZE];
      65                 :            : } __rte_packed_end;
      66                 :            : 
      67                 :            : static int
      68                 :            : lb_apply(struct lb_data *data,
      69                 :            :         struct rte_table_action_lb_params *p)
      70                 :            : {
      71                 :          0 :         memcpy(data->out, p->out, sizeof(data->out));
      72                 :            : 
      73                 :            :         return 0;
      74                 :            : }
      75                 :            : 
      76                 :            : static __rte_always_inline void
      77                 :            : pkt_work_lb(struct rte_mbuf *mbuf,
      78                 :            :         struct lb_data *data,
      79                 :            :         struct rte_table_action_lb_config *cfg)
      80                 :            : {
      81                 :          0 :         uint8_t *pkt_key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, cfg->key_offset);
      82                 :          0 :         uint32_t *out = RTE_MBUF_METADATA_UINT32_PTR(mbuf, cfg->out_offset);
      83                 :            :         uint64_t digest, pos;
      84                 :            :         uint32_t out_val;
      85                 :            : 
      86                 :          0 :         digest = cfg->f_hash(pkt_key,
      87                 :          0 :                 cfg->key_mask,
      88                 :            :                 cfg->key_size,
      89                 :            :                 cfg->seed);
      90                 :          0 :         pos = digest & (RTE_TABLE_ACTION_LB_TABLE_SIZE - 1);
      91                 :          0 :         out_val = data->out[pos];
      92                 :            : 
      93                 :          0 :         *out = out_val;
      94                 :          0 : }
      95                 :            : 
      96                 :            : /**
      97                 :            :  * RTE_TABLE_ACTION_MTR
      98                 :            :  */
      99                 :            : static int
     100                 :            : mtr_cfg_check(struct rte_table_action_mtr_config *mtr)
     101                 :            : {
     102         [ #  # ]:          0 :         if ((mtr->alg == RTE_TABLE_ACTION_METER_SRTCM) ||
     103         [ #  # ]:          0 :                 ((mtr->n_tc != 1) && (mtr->n_tc != 4)) ||
     104         [ #  # ]:          0 :                 (mtr->n_bytes_enabled != 0))
     105                 :            :                 return -ENOTSUP;
     106                 :            :         return 0;
     107                 :            : }
     108                 :            : 
     109                 :            : struct mtr_trtcm_data {
     110                 :            :         struct rte_meter_trtcm trtcm;
     111                 :            :         uint64_t stats[RTE_COLORS];
     112                 :            : };
     113                 :            : 
     114                 :            : #define MTR_TRTCM_DATA_METER_PROFILE_ID_GET(data)          \
     115                 :            :         (((data)->stats[RTE_COLOR_GREEN] & 0xF8LLU) >> 3)
     116                 :            : 
     117                 :            : static void
     118                 :            : mtr_trtcm_data_meter_profile_id_set(struct mtr_trtcm_data *data,
     119                 :            :         uint32_t profile_id)
     120                 :            : {
     121                 :          0 :         data->stats[RTE_COLOR_GREEN] &= ~0xF8LLU;
     122                 :          0 :         data->stats[RTE_COLOR_GREEN] |= (profile_id % 32) << 3;
     123                 :            : }
     124                 :            : 
     125                 :            : #define MTR_TRTCM_DATA_POLICER_ACTION_DROP_GET(data, color)\
     126                 :            :         (((data)->stats[(color)] & 4LLU) >> 2)
     127                 :            : 
     128                 :            : #define MTR_TRTCM_DATA_POLICER_ACTION_COLOR_GET(data, color)\
     129                 :            :         ((enum rte_color)((data)->stats[(color)] & 3LLU))
     130                 :            : 
     131                 :            : static void
     132                 :            : mtr_trtcm_data_policer_action_set(struct mtr_trtcm_data *data,
     133                 :            :         enum rte_color color,
     134                 :            :         enum rte_table_action_policer action)
     135                 :            : {
     136                 :          0 :         if (action == RTE_TABLE_ACTION_POLICER_DROP) {
     137                 :          0 :                 data->stats[color] |= 4LLU;
     138                 :            :         } else {
     139                 :          0 :                 data->stats[color] &= ~7LLU;
     140                 :          0 :                 data->stats[color] |= color & 3LLU;
     141                 :            :         }
     142                 :            : }
     143                 :            : 
     144                 :            : static uint64_t
     145                 :            : mtr_trtcm_data_stats_get(struct mtr_trtcm_data *data,
     146                 :            :         enum rte_color color)
     147                 :            : {
     148                 :          0 :         return data->stats[color] >> 8;
     149                 :            : }
     150                 :            : 
     151                 :            : static void
     152                 :            : mtr_trtcm_data_stats_reset(struct mtr_trtcm_data *data,
     153                 :            :         enum rte_color color)
     154                 :            : {
     155                 :          0 :         data->stats[color] &= 0xFFLU;
     156                 :          0 : }
     157                 :            : 
     158                 :            : #define MTR_TRTCM_DATA_STATS_INC(data, color)              \
     159                 :            :         ((data)->stats[(color)] += (1LLU << 8))
     160                 :            : 
     161                 :            : static size_t
     162                 :            : mtr_data_size(struct rte_table_action_mtr_config *mtr)
     163                 :            : {
     164                 :          0 :         return mtr->n_tc * sizeof(struct mtr_trtcm_data);
     165                 :            : }
     166                 :            : 
     167                 :            : struct dscp_table_entry_data {
     168                 :            :         enum rte_color color;
     169                 :            :         uint16_t tc;
     170                 :            :         uint16_t tc_queue;
     171                 :            : };
     172                 :            : 
     173                 :            : struct dscp_table_data {
     174                 :            :         struct dscp_table_entry_data entry[64];
     175                 :            : };
     176                 :            : 
     177                 :            : struct meter_profile_data {
     178                 :            :         struct rte_meter_trtcm_profile profile;
     179                 :            :         uint32_t profile_id;
     180                 :            :         int valid;
     181                 :            : };
     182                 :            : 
     183                 :            : static struct meter_profile_data *
     184                 :            : meter_profile_data_find(struct meter_profile_data *mp,
     185                 :            :         uint32_t mp_size,
     186                 :            :         uint32_t profile_id)
     187                 :            : {
     188                 :            :         uint32_t i;
     189                 :            : 
     190   [ #  #  #  #  :          0 :         for (i = 0; i < mp_size; i++) {
             #  #  #  # ]
     191                 :          0 :                 struct meter_profile_data *mp_data = &mp[i];
     192                 :            : 
     193   [ #  #  #  #  :          0 :                 if (mp_data->valid && (mp_data->profile_id == profile_id))
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     194                 :            :                         return mp_data;
     195                 :            :         }
     196                 :            : 
     197                 :            :         return NULL;
     198                 :            : }
     199                 :            : 
     200                 :            : static struct meter_profile_data *
     201                 :            : meter_profile_data_find_unused(struct meter_profile_data *mp,
     202                 :            :         uint32_t mp_size)
     203                 :            : {
     204                 :            :         uint32_t i;
     205                 :            : 
     206         [ #  # ]:          0 :         for (i = 0; i < mp_size; i++) {
     207                 :          0 :                 struct meter_profile_data *mp_data = &mp[i];
     208                 :            : 
     209         [ #  # ]:          0 :                 if (!mp_data->valid)
     210                 :            :                         return mp_data;
     211                 :            :         }
     212                 :            : 
     213                 :            :         return NULL;
     214                 :            : }
     215                 :            : 
     216                 :            : static int
     217                 :          0 : mtr_apply_check(struct rte_table_action_mtr_params *p,
     218                 :            :         struct rte_table_action_mtr_config *cfg,
     219                 :            :         struct meter_profile_data *mp,
     220                 :            :         uint32_t mp_size)
     221                 :            : {
     222                 :            :         uint32_t i;
     223                 :            : 
     224         [ #  # ]:          0 :         if (p->tc_mask > RTE_LEN2MASK(cfg->n_tc, uint32_t))
     225                 :            :                 return -EINVAL;
     226                 :            : 
     227         [ #  # ]:          0 :         for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) {
     228                 :            :                 struct rte_table_action_mtr_tc_params *p_tc = &p->mtr[i];
     229                 :            :                 struct meter_profile_data *mp_data;
     230                 :            : 
     231         [ #  # ]:          0 :                 if ((p->tc_mask & (1LLU << i)) == 0)
     232                 :          0 :                         continue;
     233                 :            : 
     234                 :          0 :                 mp_data = meter_profile_data_find(mp,
     235                 :            :                         mp_size,
     236                 :            :                         p_tc->meter_profile_id);
     237         [ #  # ]:          0 :                 if (!mp_data)
     238                 :            :                         return -EINVAL;
     239                 :            :         }
     240                 :            : 
     241                 :            :         return 0;
     242                 :            : }
     243                 :            : 
     244                 :            : static int
     245                 :          0 : mtr_apply(struct mtr_trtcm_data *data,
     246                 :            :         struct rte_table_action_mtr_params *p,
     247                 :            :         struct rte_table_action_mtr_config *cfg,
     248                 :            :         struct meter_profile_data *mp,
     249                 :            :         uint32_t mp_size)
     250                 :            : {
     251                 :            :         uint32_t i;
     252                 :            :         int status;
     253                 :            : 
     254                 :            :         /* Check input arguments */
     255                 :          0 :         status = mtr_apply_check(p, cfg, mp, mp_size);
     256         [ #  # ]:          0 :         if (status)
     257                 :            :                 return status;
     258                 :            : 
     259                 :            :         /* Apply */
     260         [ #  # ]:          0 :         for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) {
     261                 :            :                 struct rte_table_action_mtr_tc_params *p_tc = &p->mtr[i];
     262                 :          0 :                 struct mtr_trtcm_data *data_tc = &data[i];
     263                 :            :                 struct meter_profile_data *mp_data;
     264                 :            : 
     265         [ #  # ]:          0 :                 if ((p->tc_mask & (1LLU << i)) == 0)
     266                 :          0 :                         continue;
     267                 :            : 
     268                 :            :                 /* Find profile */
     269                 :          0 :                 mp_data = meter_profile_data_find(mp,
     270                 :            :                         mp_size,
     271                 :            :                         p_tc->meter_profile_id);
     272         [ #  # ]:          0 :                 if (!mp_data)
     273                 :            :                         return -EINVAL;
     274                 :            : 
     275                 :            :                 memset(data_tc, 0, sizeof(*data_tc));
     276                 :            : 
     277                 :            :                 /* Meter object */
     278                 :          0 :                 status = rte_meter_trtcm_config(&data_tc->trtcm,
     279                 :            :                         &mp_data->profile);
     280         [ #  # ]:          0 :                 if (status)
     281                 :          0 :                         return status;
     282                 :            : 
     283                 :            :                 /* Meter profile */
     284                 :          0 :                 mtr_trtcm_data_meter_profile_id_set(data_tc,
     285                 :          0 :                         mp_data - mp);
     286                 :            : 
     287                 :            :                 /* Policer actions */
     288         [ #  # ]:          0 :                 mtr_trtcm_data_policer_action_set(data_tc,
     289                 :            :                         RTE_COLOR_GREEN,
     290                 :            :                         p_tc->policer[RTE_COLOR_GREEN]);
     291                 :            : 
     292         [ #  # ]:          0 :                 mtr_trtcm_data_policer_action_set(data_tc,
     293                 :            :                         RTE_COLOR_YELLOW,
     294                 :            :                         p_tc->policer[RTE_COLOR_YELLOW]);
     295                 :            : 
     296         [ #  # ]:          0 :                 mtr_trtcm_data_policer_action_set(data_tc,
     297                 :            :                         RTE_COLOR_RED,
     298                 :            :                         p_tc->policer[RTE_COLOR_RED]);
     299                 :            :         }
     300                 :            : 
     301                 :            :         return 0;
     302                 :            : }
     303                 :            : 
     304                 :            : static __rte_always_inline uint64_t
     305                 :            : pkt_work_mtr(struct rte_mbuf *mbuf,
     306                 :            :         struct mtr_trtcm_data *data,
     307                 :            :         struct dscp_table_data *dscp_table,
     308                 :            :         struct meter_profile_data *mp,
     309                 :            :         uint64_t time,
     310                 :            :         uint32_t dscp,
     311                 :            :         uint16_t total_length)
     312                 :            : {
     313                 :            :         uint64_t drop_mask;
     314                 :            :         struct dscp_table_entry_data *dscp_entry = &dscp_table->entry[dscp];
     315                 :            :         enum rte_color color_in, color_meter, color_policer;
     316                 :            :         uint32_t tc, mp_id;
     317                 :            : 
     318                 :          0 :         tc = dscp_entry->tc;
     319                 :          0 :         color_in = dscp_entry->color;
     320                 :          0 :         data += tc;
     321                 :          0 :         mp_id = MTR_TRTCM_DATA_METER_PROFILE_ID_GET(data);
     322                 :            : 
     323                 :            :         /* Meter */
     324                 :          0 :         color_meter = rte_meter_trtcm_color_aware_check(
     325                 :            :                 &data->trtcm,
     326                 :          0 :                 &mp[mp_id].profile,
     327                 :            :                 time,
     328                 :            :                 total_length,
     329                 :            :                 color_in);
     330                 :            : 
     331                 :            :         /* Stats */
     332                 :          0 :         MTR_TRTCM_DATA_STATS_INC(data, color_meter);
     333                 :            : 
     334                 :            :         /* Police */
     335                 :          0 :         drop_mask = MTR_TRTCM_DATA_POLICER_ACTION_DROP_GET(data, color_meter);
     336                 :          0 :         color_policer =
     337                 :          0 :                 MTR_TRTCM_DATA_POLICER_ACTION_COLOR_GET(data, color_meter);
     338                 :          0 :         rte_mbuf_sched_color_set(mbuf, (uint8_t)color_policer);
     339                 :            : 
     340                 :            :         return drop_mask;
     341                 :            : }
     342                 :            : 
     343                 :            : /**
     344                 :            :  * RTE_TABLE_ACTION_TM
     345                 :            :  */
     346                 :            : static int
     347                 :            : tm_cfg_check(struct rte_table_action_tm_config *tm)
     348                 :            : {
     349         [ #  # ]:          0 :         if ((tm->n_subports_per_port == 0) ||
     350         [ #  # ]:          0 :                 (rte_is_power_of_2(tm->n_subports_per_port) == 0) ||
     351                 :          0 :                 (tm->n_subports_per_port > UINT16_MAX) ||
     352         [ #  # ]:          0 :                 (tm->n_pipes_per_subport == 0) ||
     353                 :            :                 (rte_is_power_of_2(tm->n_pipes_per_subport) == 0))
     354                 :            :                 return -ENOTSUP;
     355                 :            : 
     356                 :            :         return 0;
     357                 :            : }
     358                 :            : 
     359                 :            : struct __rte_packed_begin tm_data {
     360                 :            :         uint32_t queue_id;
     361                 :            :         uint32_t reserved;
     362                 :            : } __rte_packed_end;
     363                 :            : 
     364                 :            : static int
     365                 :            : tm_apply_check(struct rte_table_action_tm_params *p,
     366                 :            :         struct rte_table_action_tm_config *cfg)
     367                 :            : {
     368                 :          0 :         if ((p->subport_id >= cfg->n_subports_per_port) ||
     369         [ #  # ]:          0 :                 (p->pipe_id >= cfg->n_pipes_per_subport))
     370                 :            :                 return -EINVAL;
     371                 :            : 
     372                 :            :         return 0;
     373                 :            : }
     374                 :            : 
     375                 :            : static int
     376                 :            : tm_apply(struct tm_data *data,
     377                 :            :         struct rte_table_action_tm_params *p,
     378                 :            :         struct rte_table_action_tm_config *cfg)
     379                 :            : {
     380                 :            :         int status;
     381                 :            : 
     382                 :            :         /* Check input arguments */
     383                 :            :         status = tm_apply_check(p, cfg);
     384                 :            :         if (status)
     385                 :            :                 return status;
     386                 :            : 
     387                 :            :         /* Apply */
     388                 :          0 :         data->queue_id = p->subport_id <<
     389                 :          0 :                                 (rte_ctz32(cfg->n_pipes_per_subport) + 4) |
     390                 :          0 :                                 p->pipe_id << 4;
     391                 :            : 
     392                 :          0 :         return 0;
     393                 :            : }
     394                 :            : 
     395                 :            : static __rte_always_inline void
     396                 :            : pkt_work_tm(struct rte_mbuf *mbuf,
     397                 :            :         struct tm_data *data,
     398                 :            :         struct dscp_table_data *dscp_table,
     399                 :            :         uint32_t dscp)
     400                 :            : {
     401                 :            :         struct dscp_table_entry_data *dscp_entry = &dscp_table->entry[dscp];
     402                 :          0 :         uint32_t queue_id = data->queue_id |
     403                 :          0 :                                 dscp_entry->tc_queue;
     404                 :          0 :         rte_mbuf_sched_set(mbuf, queue_id, dscp_entry->tc,
     405                 :          0 :                                 (uint8_t)dscp_entry->color);
     406                 :          0 : }
     407                 :            : 
     408                 :            : /**
     409                 :            :  * RTE_TABLE_ACTION_ENCAP
     410                 :            :  */
     411                 :            : static int
     412                 :            : encap_valid(enum rte_table_action_encap_type encap)
     413                 :            : {
     414                 :          0 :         switch (encap) {
     415                 :            :         case RTE_TABLE_ACTION_ENCAP_ETHER:
     416                 :            :         case RTE_TABLE_ACTION_ENCAP_VLAN:
     417                 :            :         case RTE_TABLE_ACTION_ENCAP_QINQ:
     418                 :            :         case RTE_TABLE_ACTION_ENCAP_MPLS:
     419                 :            :         case RTE_TABLE_ACTION_ENCAP_PPPOE:
     420                 :            :         case RTE_TABLE_ACTION_ENCAP_VXLAN:
     421                 :            :         case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
     422                 :            :                 return 1;
     423                 :            :         default:
     424                 :            :                 return 0;
     425                 :            :         }
     426                 :            : }
     427                 :            : 
     428                 :            : static int
     429                 :            : encap_cfg_check(struct rte_table_action_encap_config *encap)
     430                 :            : {
     431   [ #  #  #  # ]:          0 :         if ((encap->encap_mask == 0) ||
     432                 :            :                 (rte_popcount64(encap->encap_mask) != 1))
     433                 :            :                 return -ENOTSUP;
     434                 :            : 
     435                 :            :         return 0;
     436                 :            : }
     437                 :            : 
     438                 :            : struct encap_ether_data {
     439                 :            :         struct rte_ether_hdr ether;
     440                 :            : };
     441                 :            : 
     442                 :            : #define VLAN(pcp, dei, vid)                                \
     443                 :            :         ((uint16_t)((((uint64_t)(pcp)) & 0x7LLU) << 13) |  \
     444                 :            :         ((((uint64_t)(dei)) & 0x1LLU) << 12) |             \
     445                 :            :         (((uint64_t)(vid)) & 0xFFFLLU))                    \
     446                 :            : 
     447                 :            : struct encap_vlan_data {
     448                 :            :         struct rte_ether_hdr ether;
     449                 :            :         struct rte_vlan_hdr vlan;
     450                 :            : };
     451                 :            : 
     452                 :            : struct encap_qinq_data {
     453                 :            :         struct rte_ether_hdr ether;
     454                 :            :         struct rte_vlan_hdr svlan;
     455                 :            :         struct rte_vlan_hdr cvlan;
     456                 :            : };
     457                 :            : 
     458                 :            : #define ETHER_TYPE_MPLS_UNICAST                            0x8847
     459                 :            : 
     460                 :            : #define ETHER_TYPE_MPLS_MULTICAST                          0x8848
     461                 :            : 
     462                 :            : #define MPLS(label, tc, s, ttl)                            \
     463                 :            :         ((uint32_t)(((((uint64_t)(label)) & 0xFFFFFLLU) << 12) |\
     464                 :            :         ((((uint64_t)(tc)) & 0x7LLU) << 9) |               \
     465                 :            :         ((((uint64_t)(s)) & 0x1LLU) << 8) |                \
     466                 :            :         (((uint64_t)(ttl)) & 0xFFLLU)))
     467                 :            : 
     468                 :            : struct __rte_aligned(2) __rte_packed_begin encap_mpls_data {
     469                 :            :         struct rte_ether_hdr ether;
     470                 :            :         uint32_t mpls[RTE_TABLE_ACTION_MPLS_LABELS_MAX];
     471                 :            :         uint32_t mpls_count;
     472                 :            : } __rte_packed_end;
     473                 :            : 
     474                 :            : #define PPP_PROTOCOL_IP                                    0x0021
     475                 :            : 
     476                 :            : struct pppoe_ppp_hdr {
     477                 :            :         uint16_t ver_type_code;
     478                 :            :         uint16_t session_id;
     479                 :            :         uint16_t length;
     480                 :            :         uint16_t protocol;
     481                 :            : };
     482                 :            : 
     483                 :            : struct encap_pppoe_data {
     484                 :            :         struct rte_ether_hdr ether;
     485                 :            :         struct pppoe_ppp_hdr pppoe_ppp;
     486                 :            : };
     487                 :            : 
     488                 :            : #define IP_PROTO_UDP                                       17
     489                 :            : 
     490                 :            : struct __rte_aligned(2) __rte_packed_begin encap_vxlan_ipv4_data {
     491                 :            :         struct rte_ether_hdr ether;
     492                 :            :         struct rte_ipv4_hdr ipv4;
     493                 :            :         struct rte_udp_hdr udp;
     494                 :            :         struct rte_vxlan_hdr vxlan;
     495                 :            : } __rte_packed_end;
     496                 :            : 
     497                 :            : struct __rte_aligned(2) __rte_packed_begin encap_vxlan_ipv4_vlan_data {
     498                 :            :         struct rte_ether_hdr ether;
     499                 :            :         struct rte_vlan_hdr vlan;
     500                 :            :         struct rte_ipv4_hdr ipv4;
     501                 :            :         struct rte_udp_hdr udp;
     502                 :            :         struct rte_vxlan_hdr vxlan;
     503                 :            : } __rte_packed_end;
     504                 :            : 
     505                 :            : struct __rte_aligned(2) __rte_packed_begin encap_vxlan_ipv6_data {
     506                 :            :         struct rte_ether_hdr ether;
     507                 :            :         struct rte_ipv6_hdr ipv6;
     508                 :            :         struct rte_udp_hdr udp;
     509                 :            :         struct rte_vxlan_hdr vxlan;
     510                 :            : } __rte_packed_end;
     511                 :            : 
     512                 :            : struct __rte_aligned(2) __rte_packed_begin encap_vxlan_ipv6_vlan_data {
     513                 :            :         struct rte_ether_hdr ether;
     514                 :            :         struct rte_vlan_hdr vlan;
     515                 :            :         struct rte_ipv6_hdr ipv6;
     516                 :            :         struct rte_udp_hdr udp;
     517                 :            :         struct rte_vxlan_hdr vxlan;
     518                 :            : } __rte_packed_end;
     519                 :            : 
     520                 :            : struct __rte_aligned(2) __rte_packed_begin encap_qinq_pppoe_data {
     521                 :            :         struct rte_ether_hdr ether;
     522                 :            :         struct rte_vlan_hdr svlan;
     523                 :            :         struct rte_vlan_hdr cvlan;
     524                 :            :         struct pppoe_ppp_hdr pppoe_ppp;
     525                 :            : } __rte_packed_end;
     526                 :            : 
     527                 :            : static size_t
     528                 :          0 : encap_data_size(struct rte_table_action_encap_config *encap)
     529                 :            : {
     530   [ #  #  #  #  :          0 :         switch (encap->encap_mask) {
             #  #  #  # ]
     531                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER:
     532                 :            :                 return sizeof(struct encap_ether_data);
     533                 :            : 
     534                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN:
     535                 :          0 :                 return sizeof(struct encap_vlan_data);
     536                 :            : 
     537                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ:
     538                 :          0 :                 return sizeof(struct encap_qinq_data);
     539                 :            : 
     540                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS:
     541                 :          0 :                 return sizeof(struct encap_mpls_data);
     542                 :            : 
     543                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE:
     544                 :          0 :                 return sizeof(struct encap_pppoe_data);
     545                 :            : 
     546                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN:
     547         [ #  # ]:          0 :                 if (encap->vxlan.ip_version)
     548         [ #  # ]:          0 :                         if (encap->vxlan.vlan)
     549                 :            :                                 return sizeof(struct encap_vxlan_ipv4_vlan_data);
     550                 :            :                         else
     551                 :          0 :                                 return sizeof(struct encap_vxlan_ipv4_data);
     552                 :            :                 else
     553         [ #  # ]:          0 :                         if (encap->vxlan.vlan)
     554                 :            :                                 return sizeof(struct encap_vxlan_ipv6_vlan_data);
     555                 :            :                         else
     556                 :          0 :                                 return sizeof(struct encap_vxlan_ipv6_data);
     557                 :            : 
     558                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
     559                 :          0 :                         return sizeof(struct encap_qinq_pppoe_data);
     560                 :            : 
     561                 :          0 :         default:
     562                 :          0 :                 return 0;
     563                 :            :         }
     564                 :            : }
     565                 :            : 
     566                 :            : static int
     567                 :            : encap_apply_check(struct rte_table_action_encap_params *p,
     568                 :            :         struct rte_table_action_encap_config *cfg)
     569                 :            : {
     570                 :          0 :         if ((encap_valid(p->type) == 0) ||
     571         [ #  # ]:          0 :                 ((cfg->encap_mask & (1LLU << p->type)) == 0))
     572                 :            :                 return -EINVAL;
     573                 :            : 
     574         [ #  # ]:          0 :         switch (p->type) {
     575                 :            :         case RTE_TABLE_ACTION_ENCAP_ETHER:
     576                 :            :                 return 0;
     577                 :            : 
     578                 :            :         case RTE_TABLE_ACTION_ENCAP_VLAN:
     579                 :            :                 return 0;
     580                 :            : 
     581                 :            :         case RTE_TABLE_ACTION_ENCAP_QINQ:
     582                 :            :                 return 0;
     583                 :            : 
     584                 :          0 :         case RTE_TABLE_ACTION_ENCAP_MPLS:
     585         [ #  # ]:          0 :                 if ((p->mpls.mpls_count == 0) ||
     586                 :            :                         (p->mpls.mpls_count > RTE_TABLE_ACTION_MPLS_LABELS_MAX))
     587                 :            :                         return -EINVAL;
     588                 :            : 
     589                 :            :                 return 0;
     590                 :            : 
     591                 :            :         case RTE_TABLE_ACTION_ENCAP_PPPOE:
     592                 :            :                 return 0;
     593                 :            : 
     594                 :            :         case RTE_TABLE_ACTION_ENCAP_VXLAN:
     595                 :            :                 return 0;
     596                 :            : 
     597                 :            :         case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
     598                 :            :                 return 0;
     599                 :            : 
     600                 :            :         default:
     601                 :            :                 return -EINVAL;
     602                 :            :         }
     603                 :            : }
     604                 :            : 
     605                 :            : static int
     606                 :            : encap_ether_apply(void *data,
     607                 :            :         struct rte_table_action_encap_params *p,
     608                 :            :         struct rte_table_action_common_config *common_cfg)
     609                 :            : {
     610                 :            :         struct encap_ether_data *d = data;
     611         [ #  # ]:          0 :         uint16_t ethertype = (common_cfg->ip_version) ?
     612                 :            :                 RTE_ETHER_TYPE_IPV4 :
     613                 :            :                 RTE_ETHER_TYPE_IPV6;
     614                 :            : 
     615                 :            :         /* Ethernet */
     616                 :            :         rte_ether_addr_copy(&p->ether.ether.da, &d->ether.dst_addr);
     617                 :            :         rte_ether_addr_copy(&p->ether.ether.sa, &d->ether.src_addr);
     618         [ #  # ]:          0 :         d->ether.ether_type = rte_htons(ethertype);
     619                 :            : 
     620                 :            :         return 0;
     621                 :            : }
     622                 :            : 
     623                 :            : static int
     624                 :          0 : encap_vlan_apply(void *data,
     625                 :            :         struct rte_table_action_encap_params *p,
     626                 :            :         struct rte_table_action_common_config *common_cfg)
     627                 :            : {
     628                 :            :         struct encap_vlan_data *d = data;
     629         [ #  # ]:          0 :         uint16_t ethertype = (common_cfg->ip_version) ?
     630                 :            :                 RTE_ETHER_TYPE_IPV4 :
     631                 :            :                 RTE_ETHER_TYPE_IPV6;
     632                 :            : 
     633                 :            :         /* Ethernet */
     634                 :            :         rte_ether_addr_copy(&p->vlan.ether.da, &d->ether.dst_addr);
     635                 :            :         rte_ether_addr_copy(&p->vlan.ether.sa, &d->ether.src_addr);
     636                 :          0 :         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_VLAN);
     637                 :            : 
     638                 :            :         /* VLAN */
     639         [ #  # ]:          0 :         d->vlan.vlan_tci = rte_htons(VLAN(p->vlan.vlan.pcp,
     640                 :            :                 p->vlan.vlan.dei,
     641                 :            :                 p->vlan.vlan.vid));
     642         [ #  # ]:          0 :         d->vlan.eth_proto = rte_htons(ethertype);
     643                 :            : 
     644                 :          0 :         return 0;
     645                 :            : }
     646                 :            : 
     647                 :            : static int
     648                 :          0 : encap_qinq_apply(void *data,
     649                 :            :         struct rte_table_action_encap_params *p,
     650                 :            :         struct rte_table_action_common_config *common_cfg)
     651                 :            : {
     652                 :            :         struct encap_qinq_data *d = data;
     653         [ #  # ]:          0 :         uint16_t ethertype = (common_cfg->ip_version) ?
     654                 :            :                 RTE_ETHER_TYPE_IPV4 :
     655                 :            :                 RTE_ETHER_TYPE_IPV6;
     656                 :            : 
     657                 :            :         /* Ethernet */
     658                 :            :         rte_ether_addr_copy(&p->qinq.ether.da, &d->ether.dst_addr);
     659                 :            :         rte_ether_addr_copy(&p->qinq.ether.sa, &d->ether.src_addr);
     660                 :          0 :         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_QINQ);
     661                 :            : 
     662                 :            :         /* SVLAN */
     663         [ #  # ]:          0 :         d->svlan.vlan_tci = rte_htons(VLAN(p->qinq.svlan.pcp,
     664                 :            :                 p->qinq.svlan.dei,
     665                 :            :                 p->qinq.svlan.vid));
     666                 :          0 :         d->svlan.eth_proto = rte_htons(RTE_ETHER_TYPE_VLAN);
     667                 :            : 
     668                 :            :         /* CVLAN */
     669         [ #  # ]:          0 :         d->cvlan.vlan_tci = rte_htons(VLAN(p->qinq.cvlan.pcp,
     670                 :            :                 p->qinq.cvlan.dei,
     671                 :            :                 p->qinq.cvlan.vid));
     672         [ #  # ]:          0 :         d->cvlan.eth_proto = rte_htons(ethertype);
     673                 :            : 
     674                 :          0 :         return 0;
     675                 :            : }
     676                 :            : 
     677                 :            : static int
     678         [ #  # ]:          0 : encap_qinq_pppoe_apply(void *data,
     679                 :            :         struct rte_table_action_encap_params *p)
     680                 :            : {
     681                 :            :         struct encap_qinq_pppoe_data *d = data;
     682                 :            : 
     683                 :            :         /* Ethernet */
     684                 :            :         rte_ether_addr_copy(&p->qinq.ether.da, &d->ether.dst_addr);
     685                 :            :         rte_ether_addr_copy(&p->qinq.ether.sa, &d->ether.src_addr);
     686                 :          0 :         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_VLAN);
     687                 :            : 
     688                 :            :         /* SVLAN */
     689         [ #  # ]:          0 :         d->svlan.vlan_tci = rte_htons(VLAN(p->qinq.svlan.pcp,
     690                 :            :                 p->qinq.svlan.dei,
     691                 :            :                 p->qinq.svlan.vid));
     692                 :          0 :         d->svlan.eth_proto = rte_htons(RTE_ETHER_TYPE_VLAN);
     693                 :            : 
     694                 :            :         /* CVLAN */
     695         [ #  # ]:          0 :         d->cvlan.vlan_tci = rte_htons(VLAN(p->qinq.cvlan.pcp,
     696                 :            :                 p->qinq.cvlan.dei,
     697                 :            :                 p->qinq.cvlan.vid));
     698                 :          0 :         d->cvlan.eth_proto = rte_htons(RTE_ETHER_TYPE_PPPOE_SESSION);
     699                 :            : 
     700                 :            :         /* PPPoE and PPP*/
     701                 :          0 :         d->pppoe_ppp.ver_type_code = rte_htons(0x1100);
     702         [ #  # ]:          0 :         d->pppoe_ppp.session_id = rte_htons(p->qinq_pppoe.pppoe.session_id);
     703                 :          0 :         d->pppoe_ppp.length = 0; /* not pre-computed */
     704                 :          0 :         d->pppoe_ppp.protocol = rte_htons(PPP_PROTOCOL_IP);
     705                 :            : 
     706                 :          0 :         return 0;
     707                 :            : }
     708                 :            : 
     709                 :            : static int
     710                 :          0 : encap_mpls_apply(void *data,
     711                 :            :         struct rte_table_action_encap_params *p)
     712                 :            : {
     713                 :            :         struct encap_mpls_data *d = data;
     714         [ #  # ]:          0 :         uint16_t ethertype = (p->mpls.unicast) ?
     715                 :            :                 ETHER_TYPE_MPLS_UNICAST :
     716                 :            :                 ETHER_TYPE_MPLS_MULTICAST;
     717                 :            :         uint32_t i;
     718                 :            : 
     719                 :            :         /* Ethernet */
     720                 :            :         rte_ether_addr_copy(&p->mpls.ether.da, &d->ether.dst_addr);
     721                 :            :         rte_ether_addr_copy(&p->mpls.ether.sa, &d->ether.src_addr);
     722         [ #  # ]:          0 :         d->ether.ether_type = rte_htons(ethertype);
     723                 :            : 
     724                 :            :         /* MPLS */
     725         [ #  # ]:          0 :         for (i = 0; i < p->mpls.mpls_count - 1; i++)
     726         [ #  # ]:          0 :                 d->mpls[i] = rte_htonl(MPLS(p->mpls.mpls[i].label,
     727                 :            :                         p->mpls.mpls[i].tc,
     728                 :            :                         0,
     729                 :            :                         p->mpls.mpls[i].ttl));
     730                 :            : 
     731         [ #  # ]:          0 :         d->mpls[i] = rte_htonl(MPLS(p->mpls.mpls[i].label,
     732                 :            :                 p->mpls.mpls[i].tc,
     733                 :            :                 1,
     734                 :            :                 p->mpls.mpls[i].ttl));
     735                 :            : 
     736                 :          0 :         d->mpls_count = p->mpls.mpls_count;
     737                 :          0 :         return 0;
     738                 :            : }
     739                 :            : 
     740                 :            : static int
     741                 :            : encap_pppoe_apply(void *data,
     742                 :            :         struct rte_table_action_encap_params *p)
     743                 :            : {
     744                 :            :         struct encap_pppoe_data *d = data;
     745                 :            : 
     746                 :            :         /* Ethernet */
     747                 :            :         rte_ether_addr_copy(&p->pppoe.ether.da, &d->ether.dst_addr);
     748                 :            :         rte_ether_addr_copy(&p->pppoe.ether.sa, &d->ether.src_addr);
     749                 :          0 :         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_PPPOE_SESSION);
     750                 :            : 
     751                 :            :         /* PPPoE and PPP*/
     752                 :          0 :         d->pppoe_ppp.ver_type_code = rte_htons(0x1100);
     753         [ #  # ]:          0 :         d->pppoe_ppp.session_id = rte_htons(p->pppoe.pppoe.session_id);
     754                 :          0 :         d->pppoe_ppp.length = 0; /* not pre-computed */
     755                 :          0 :         d->pppoe_ppp.protocol = rte_htons(PPP_PROTOCOL_IP);
     756                 :            : 
     757                 :            :         return 0;
     758                 :            : }
     759                 :            : 
     760                 :            : static int
     761                 :          0 : encap_vxlan_apply(void *data,
     762                 :            :         struct rte_table_action_encap_params *p,
     763                 :            :         struct rte_table_action_encap_config *cfg)
     764                 :            : {
     765         [ #  # ]:          0 :         if ((p->vxlan.vxlan.vni > 0xFFFFFF) ||
     766   [ #  #  #  #  :          0 :                 (cfg->vxlan.ip_version && (p->vxlan.ipv4.dscp > 0x3F)) ||
                   #  # ]
     767   [ #  #  #  # ]:          0 :                 (!cfg->vxlan.ip_version && (p->vxlan.ipv6.flow_label > 0xFFFFF)) ||
     768         [ #  # ]:          0 :                 (!cfg->vxlan.ip_version && (p->vxlan.ipv6.dscp > 0x3F)) ||
     769   [ #  #  #  # ]:          0 :                 (cfg->vxlan.vlan && (p->vxlan.vlan.vid > 0xFFF)))
     770                 :            :                 return -1;
     771                 :            : 
     772         [ #  # ]:          0 :         if (cfg->vxlan.ip_version)
     773         [ #  # ]:          0 :                 if (cfg->vxlan.vlan) {
     774                 :            :                         struct encap_vxlan_ipv4_vlan_data *d = data;
     775                 :            : 
     776                 :            :                         /* Ethernet */
     777                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.da,
     778                 :            :                                         &d->ether.dst_addr);
     779                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.sa,
     780                 :            :                                         &d->ether.src_addr);
     781                 :          0 :                         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_VLAN);
     782                 :            : 
     783                 :            :                         /* VLAN */
     784         [ #  # ]:          0 :                         d->vlan.vlan_tci = rte_htons(VLAN(p->vxlan.vlan.pcp,
     785                 :            :                                 p->vxlan.vlan.dei,
     786                 :            :                                 p->vxlan.vlan.vid));
     787                 :          0 :                         d->vlan.eth_proto = rte_htons(RTE_ETHER_TYPE_IPV4);
     788                 :            : 
     789                 :            :                         /* IPv4*/
     790                 :          0 :                         d->ipv4.version_ihl = 0x45;
     791                 :          0 :                         d->ipv4.type_of_service = p->vxlan.ipv4.dscp << 2;
     792                 :          0 :                         d->ipv4.total_length = 0; /* not pre-computed */
     793                 :          0 :                         d->ipv4.packet_id = 0;
     794                 :          0 :                         d->ipv4.fragment_offset = 0;
     795                 :          0 :                         d->ipv4.time_to_live = p->vxlan.ipv4.ttl;
     796                 :          0 :                         d->ipv4.next_proto_id = IP_PROTO_UDP;
     797                 :          0 :                         d->ipv4.hdr_checksum = 0;
     798         [ #  # ]:          0 :                         d->ipv4.src_addr = rte_htonl(p->vxlan.ipv4.sa);
     799         [ #  # ]:          0 :                         d->ipv4.dst_addr = rte_htonl(p->vxlan.ipv4.da);
     800                 :            : 
     801         [ #  # ]:          0 :                         d->ipv4.hdr_checksum = rte_ipv4_cksum(&d->ipv4);
     802                 :            : 
     803                 :            :                         /* UDP */
     804         [ #  # ]:          0 :                         d->udp.src_port = rte_htons(p->vxlan.udp.sp);
     805         [ #  # ]:          0 :                         d->udp.dst_port = rte_htons(p->vxlan.udp.dp);
     806                 :          0 :                         d->udp.dgram_len = 0; /* not pre-computed */
     807                 :          0 :                         d->udp.dgram_cksum = 0;
     808                 :            : 
     809                 :            :                         /* VXLAN */
     810                 :          0 :                         d->vxlan.vx_flags = rte_htonl(0x08000000);
     811         [ #  # ]:          0 :                         d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8);
     812                 :            : 
     813                 :          0 :                         return 0;
     814                 :            :                 } else {
     815                 :            :                         struct encap_vxlan_ipv4_data *d = data;
     816                 :            : 
     817                 :            :                         /* Ethernet */
     818                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.da,
     819                 :            :                                         &d->ether.dst_addr);
     820                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.sa,
     821                 :            :                                         &d->ether.src_addr);
     822                 :          0 :                         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_IPV4);
     823                 :            : 
     824                 :            :                         /* IPv4*/
     825                 :          0 :                         d->ipv4.version_ihl = 0x45;
     826                 :          0 :                         d->ipv4.type_of_service = p->vxlan.ipv4.dscp << 2;
     827                 :          0 :                         d->ipv4.total_length = 0; /* not pre-computed */
     828                 :          0 :                         d->ipv4.packet_id = 0;
     829                 :          0 :                         d->ipv4.fragment_offset = 0;
     830                 :          0 :                         d->ipv4.time_to_live = p->vxlan.ipv4.ttl;
     831                 :          0 :                         d->ipv4.next_proto_id = IP_PROTO_UDP;
     832                 :          0 :                         d->ipv4.hdr_checksum = 0;
     833         [ #  # ]:          0 :                         d->ipv4.src_addr = rte_htonl(p->vxlan.ipv4.sa);
     834         [ #  # ]:          0 :                         d->ipv4.dst_addr = rte_htonl(p->vxlan.ipv4.da);
     835                 :            : 
     836         [ #  # ]:          0 :                         d->ipv4.hdr_checksum = rte_ipv4_cksum(&d->ipv4);
     837                 :            : 
     838                 :            :                         /* UDP */
     839         [ #  # ]:          0 :                         d->udp.src_port = rte_htons(p->vxlan.udp.sp);
     840         [ #  # ]:          0 :                         d->udp.dst_port = rte_htons(p->vxlan.udp.dp);
     841                 :          0 :                         d->udp.dgram_len = 0; /* not pre-computed */
     842                 :          0 :                         d->udp.dgram_cksum = 0;
     843                 :            : 
     844                 :            :                         /* VXLAN */
     845                 :          0 :                         d->vxlan.vx_flags = rte_htonl(0x08000000);
     846         [ #  # ]:          0 :                         d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8);
     847                 :            : 
     848                 :          0 :                         return 0;
     849                 :            :                 }
     850                 :            :         else
     851         [ #  # ]:          0 :                 if (cfg->vxlan.vlan) {
     852                 :            :                         struct encap_vxlan_ipv6_vlan_data *d = data;
     853                 :            : 
     854                 :            :                         /* Ethernet */
     855                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.da,
     856                 :            :                                         &d->ether.dst_addr);
     857                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.sa,
     858                 :            :                                         &d->ether.src_addr);
     859                 :          0 :                         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_VLAN);
     860                 :            : 
     861                 :            :                         /* VLAN */
     862         [ #  # ]:          0 :                         d->vlan.vlan_tci = rte_htons(VLAN(p->vxlan.vlan.pcp,
     863                 :            :                                 p->vxlan.vlan.dei,
     864                 :            :                                 p->vxlan.vlan.vid));
     865                 :          0 :                         d->vlan.eth_proto = rte_htons(RTE_ETHER_TYPE_IPV6);
     866                 :            : 
     867                 :            :                         /* IPv6*/
     868         [ #  # ]:          0 :                         d->ipv6.vtc_flow = rte_htonl((6 << 28) |
     869                 :            :                                 (p->vxlan.ipv6.dscp << 22) |
     870                 :            :                                 p->vxlan.ipv6.flow_label);
     871                 :          0 :                         d->ipv6.payload_len = 0; /* not pre-computed */
     872                 :          0 :                         d->ipv6.proto = IP_PROTO_UDP;
     873                 :          0 :                         d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
     874                 :          0 :                         d->ipv6.src_addr = p->vxlan.ipv6.sa;
     875                 :          0 :                         d->ipv6.dst_addr = p->vxlan.ipv6.da;
     876                 :            : 
     877                 :            :                         /* UDP */
     878         [ #  # ]:          0 :                         d->udp.src_port = rte_htons(p->vxlan.udp.sp);
     879         [ #  # ]:          0 :                         d->udp.dst_port = rte_htons(p->vxlan.udp.dp);
     880                 :          0 :                         d->udp.dgram_len = 0; /* not pre-computed */
     881                 :          0 :                         d->udp.dgram_cksum = 0;
     882                 :            : 
     883                 :            :                         /* VXLAN */
     884                 :          0 :                         d->vxlan.vx_flags = rte_htonl(0x08000000);
     885         [ #  # ]:          0 :                         d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8);
     886                 :            : 
     887                 :          0 :                         return 0;
     888                 :            :                 } else {
     889                 :            :                         struct encap_vxlan_ipv6_data *d = data;
     890                 :            : 
     891                 :            :                         /* Ethernet */
     892                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.da,
     893                 :            :                                         &d->ether.dst_addr);
     894                 :            :                         rte_ether_addr_copy(&p->vxlan.ether.sa,
     895                 :            :                                         &d->ether.src_addr);
     896                 :          0 :                         d->ether.ether_type = rte_htons(RTE_ETHER_TYPE_IPV6);
     897                 :            : 
     898                 :            :                         /* IPv6*/
     899         [ #  # ]:          0 :                         d->ipv6.vtc_flow = rte_htonl((6 << 28) |
     900                 :            :                                 (p->vxlan.ipv6.dscp << 22) |
     901                 :            :                                 p->vxlan.ipv6.flow_label);
     902                 :          0 :                         d->ipv6.payload_len = 0; /* not pre-computed */
     903                 :          0 :                         d->ipv6.proto = IP_PROTO_UDP;
     904                 :          0 :                         d->ipv6.hop_limits = p->vxlan.ipv6.hop_limit;
     905                 :          0 :                         d->ipv6.src_addr = p->vxlan.ipv6.sa;
     906                 :          0 :                         d->ipv6.dst_addr = p->vxlan.ipv6.da;
     907                 :            : 
     908                 :            :                         /* UDP */
     909         [ #  # ]:          0 :                         d->udp.src_port = rte_htons(p->vxlan.udp.sp);
     910         [ #  # ]:          0 :                         d->udp.dst_port = rte_htons(p->vxlan.udp.dp);
     911                 :          0 :                         d->udp.dgram_len = 0; /* not pre-computed */
     912                 :          0 :                         d->udp.dgram_cksum = 0;
     913                 :            : 
     914                 :            :                         /* VXLAN */
     915                 :          0 :                         d->vxlan.vx_flags = rte_htonl(0x08000000);
     916         [ #  # ]:          0 :                         d->vxlan.vx_vni = rte_htonl(p->vxlan.vxlan.vni << 8);
     917                 :            : 
     918                 :          0 :                         return 0;
     919                 :            :                 }
     920                 :            : }
     921                 :            : 
     922                 :            : static int
     923         [ #  # ]:          0 : encap_apply(void *data,
     924                 :            :         struct rte_table_action_encap_params *p,
     925                 :            :         struct rte_table_action_encap_config *cfg,
     926                 :            :         struct rte_table_action_common_config *common_cfg)
     927                 :            : {
     928                 :            :         int status;
     929                 :            : 
     930                 :            :         /* Check input arguments */
     931                 :            :         status = encap_apply_check(p, cfg);
     932                 :            :         if (status)
     933                 :            :                 return status;
     934                 :            : 
     935   [ #  #  #  #  :          0 :         switch (p->type) {
                #  #  # ]
     936                 :            :         case RTE_TABLE_ACTION_ENCAP_ETHER:
     937                 :          0 :                 return encap_ether_apply(data, p, common_cfg);
     938                 :            : 
     939                 :          0 :         case RTE_TABLE_ACTION_ENCAP_VLAN:
     940                 :          0 :                 return encap_vlan_apply(data, p, common_cfg);
     941                 :            : 
     942                 :          0 :         case RTE_TABLE_ACTION_ENCAP_QINQ:
     943                 :          0 :                 return encap_qinq_apply(data, p, common_cfg);
     944                 :            : 
     945                 :          0 :         case RTE_TABLE_ACTION_ENCAP_MPLS:
     946                 :          0 :                 return encap_mpls_apply(data, p);
     947                 :            : 
     948                 :            :         case RTE_TABLE_ACTION_ENCAP_PPPOE:
     949                 :          0 :                 return encap_pppoe_apply(data, p);
     950                 :            : 
     951                 :          0 :         case RTE_TABLE_ACTION_ENCAP_VXLAN:
     952                 :          0 :                 return encap_vxlan_apply(data, p, cfg);
     953                 :            : 
     954                 :          0 :         case RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
     955                 :          0 :                 return encap_qinq_pppoe_apply(data, p);
     956                 :            : 
     957                 :            :         default:
     958                 :            :                 return -EINVAL;
     959                 :            :         }
     960                 :            : }
     961                 :            : 
     962                 :            : static __rte_always_inline uint16_t
     963                 :            : encap_vxlan_ipv4_checksum_update(uint16_t cksum0,
     964                 :            :         uint16_t total_length)
     965                 :            : {
     966                 :            :         int32_t cksum1;
     967                 :            : 
     968                 :            :         cksum1 = cksum0;
     969                 :          0 :         cksum1 = ~cksum1 & 0xFFFF;
     970                 :            : 
     971                 :            :         /* Add total length (one's complement logic) */
     972                 :          0 :         cksum1 += total_length;
     973                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
     974                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
     975                 :            : 
     976                 :          0 :         return (uint16_t)(~cksum1);
     977                 :            : }
     978                 :            : 
     979                 :            : static __rte_always_inline void *
     980                 :            : encap(void *dst, const void *src, size_t n)
     981                 :            : {
     982   [ #  #  #  #  :          0 :         dst = ((uint8_t *) dst) - n;
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     983                 :            :         return rte_memcpy(dst, src, n);
     984                 :            : }
     985                 :            : 
     986                 :            : static __rte_always_inline void
     987                 :            : pkt_work_encap_vxlan_ipv4(struct rte_mbuf *mbuf,
     988                 :            :         struct encap_vxlan_ipv4_data *vxlan_tbl,
     989                 :            :         struct rte_table_action_encap_config *cfg)
     990                 :            : {
     991                 :          0 :         uint32_t ether_offset = cfg->vxlan.data_offset;
     992                 :          0 :         void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset);
     993                 :            :         struct encap_vxlan_ipv4_data *vxlan_pkt;
     994                 :            :         uint16_t ether_length, ipv4_total_length, ipv4_hdr_cksum, udp_length;
     995                 :            : 
     996                 :          0 :         ether_length = (uint16_t)mbuf->pkt_len;
     997                 :          0 :         ipv4_total_length = ether_length +
     998                 :            :                 (sizeof(struct rte_vxlan_hdr) +
     999                 :            :                 sizeof(struct rte_udp_hdr) +
    1000                 :            :                 sizeof(struct rte_ipv4_hdr));
    1001                 :          0 :         ipv4_hdr_cksum = encap_vxlan_ipv4_checksum_update(vxlan_tbl->ipv4.hdr_checksum,
    1002   [ #  #  #  #  :          0 :                 rte_htons(ipv4_total_length));
          #  #  #  #  #  
                #  #  # ]
    1003   [ #  #  #  #  :          0 :         udp_length = ether_length +
          #  #  #  #  #  
                #  #  # ]
    1004                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1005                 :            :                 sizeof(struct rte_udp_hdr));
    1006                 :            : 
    1007                 :            :         vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl));
    1008   [ #  #  #  #  :          0 :         vxlan_pkt->ipv4.total_length = rte_htons(ipv4_total_length);
          #  #  #  #  #  
                #  #  # ]
    1009                 :          0 :         vxlan_pkt->ipv4.hdr_checksum = ipv4_hdr_cksum;
    1010   [ #  #  #  #  :          0 :         vxlan_pkt->udp.dgram_len = rte_htons(udp_length);
          #  #  #  #  #  
                #  #  # ]
    1011                 :            : 
    1012                 :          0 :         mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt));
    1013                 :          0 :         mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt);
    1014                 :          0 : }
    1015                 :            : 
    1016                 :            : static __rte_always_inline void
    1017                 :            : pkt_work_encap_vxlan_ipv4_vlan(struct rte_mbuf *mbuf,
    1018                 :            :         struct encap_vxlan_ipv4_vlan_data *vxlan_tbl,
    1019                 :            :         struct rte_table_action_encap_config *cfg)
    1020                 :            : {
    1021                 :          0 :         uint32_t ether_offset = cfg->vxlan.data_offset;
    1022                 :          0 :         void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset);
    1023                 :            :         struct encap_vxlan_ipv4_vlan_data *vxlan_pkt;
    1024                 :            :         uint16_t ether_length, ipv4_total_length, ipv4_hdr_cksum, udp_length;
    1025                 :            : 
    1026                 :          0 :         ether_length = (uint16_t)mbuf->pkt_len;
    1027                 :          0 :         ipv4_total_length = ether_length +
    1028                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1029                 :            :                 sizeof(struct rte_udp_hdr) +
    1030                 :            :                 sizeof(struct rte_ipv4_hdr));
    1031                 :          0 :         ipv4_hdr_cksum = encap_vxlan_ipv4_checksum_update(vxlan_tbl->ipv4.hdr_checksum,
    1032   [ #  #  #  #  :          0 :                 rte_htons(ipv4_total_length));
          #  #  #  #  #  
                #  #  # ]
    1033   [ #  #  #  #  :          0 :         udp_length = ether_length +
          #  #  #  #  #  
                #  #  # ]
    1034                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1035                 :            :                 sizeof(struct rte_udp_hdr));
    1036                 :            : 
    1037                 :            :         vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl));
    1038   [ #  #  #  #  :          0 :         vxlan_pkt->ipv4.total_length = rte_htons(ipv4_total_length);
          #  #  #  #  #  
                #  #  # ]
    1039                 :          0 :         vxlan_pkt->ipv4.hdr_checksum = ipv4_hdr_cksum;
    1040   [ #  #  #  #  :          0 :         vxlan_pkt->udp.dgram_len = rte_htons(udp_length);
          #  #  #  #  #  
                #  #  # ]
    1041                 :            : 
    1042                 :          0 :         mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt));
    1043                 :          0 :         mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt);
    1044                 :          0 : }
    1045                 :            : 
    1046                 :            : static __rte_always_inline void
    1047                 :            : pkt_work_encap_vxlan_ipv6(struct rte_mbuf *mbuf,
    1048                 :            :         struct encap_vxlan_ipv6_data *vxlan_tbl,
    1049                 :            :         struct rte_table_action_encap_config *cfg)
    1050                 :            : {
    1051                 :          0 :         uint32_t ether_offset = cfg->vxlan.data_offset;
    1052                 :          0 :         void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset);
    1053                 :            :         struct encap_vxlan_ipv6_data *vxlan_pkt;
    1054                 :            :         uint16_t ether_length, ipv6_payload_length, udp_length;
    1055                 :            : 
    1056                 :          0 :         ether_length = (uint16_t)mbuf->pkt_len;
    1057   [ #  #  #  #  :          0 :         ipv6_payload_length = ether_length +
          #  #  #  #  #  
                #  #  # ]
    1058                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1059                 :            :                 sizeof(struct rte_udp_hdr));
    1060                 :            :         udp_length = ether_length +
    1061                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1062                 :            :                 sizeof(struct rte_udp_hdr));
    1063                 :            : 
    1064                 :            :         vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl));
    1065   [ #  #  #  #  :          0 :         vxlan_pkt->ipv6.payload_len = rte_htons(ipv6_payload_length);
          #  #  #  #  #  
                #  #  # ]
    1066   [ #  #  #  #  :          0 :         vxlan_pkt->udp.dgram_len = rte_htons(udp_length);
          #  #  #  #  #  
                #  #  # ]
    1067                 :            : 
    1068                 :          0 :         mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt));
    1069                 :          0 :         mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt);
    1070                 :          0 : }
    1071                 :            : 
    1072                 :            : static __rte_always_inline void
    1073                 :            : pkt_work_encap_vxlan_ipv6_vlan(struct rte_mbuf *mbuf,
    1074                 :            :         struct encap_vxlan_ipv6_vlan_data *vxlan_tbl,
    1075                 :            :         struct rte_table_action_encap_config *cfg)
    1076                 :            : {
    1077                 :          0 :         uint32_t ether_offset = cfg->vxlan.data_offset;
    1078                 :          0 :         void *ether = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ether_offset);
    1079                 :            :         struct encap_vxlan_ipv6_vlan_data *vxlan_pkt;
    1080                 :            :         uint16_t ether_length, ipv6_payload_length, udp_length;
    1081                 :            : 
    1082                 :          0 :         ether_length = (uint16_t)mbuf->pkt_len;
    1083   [ #  #  #  #  :          0 :         ipv6_payload_length = ether_length +
          #  #  #  #  #  
                #  #  # ]
    1084                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1085                 :            :                 sizeof(struct rte_udp_hdr));
    1086                 :            :         udp_length = ether_length +
    1087                 :            :                 (sizeof(struct rte_vxlan_hdr) +
    1088                 :            :                 sizeof(struct rte_udp_hdr));
    1089                 :            : 
    1090                 :            :         vxlan_pkt = encap(ether, vxlan_tbl, sizeof(*vxlan_tbl));
    1091   [ #  #  #  #  :          0 :         vxlan_pkt->ipv6.payload_len = rte_htons(ipv6_payload_length);
          #  #  #  #  #  
                #  #  # ]
    1092   [ #  #  #  #  :          0 :         vxlan_pkt->udp.dgram_len = rte_htons(udp_length);
          #  #  #  #  #  
                #  #  # ]
    1093                 :            : 
    1094                 :          0 :         mbuf->data_off = ether_offset - (sizeof(struct rte_mbuf) + sizeof(*vxlan_pkt));
    1095                 :          0 :         mbuf->pkt_len = mbuf->data_len = ether_length + sizeof(*vxlan_pkt);
    1096                 :          0 : }
    1097                 :            : 
    1098                 :            : static __rte_always_inline void
    1099                 :            : pkt_work_encap(struct rte_mbuf *mbuf,
    1100                 :            :         void *data,
    1101                 :            :         struct rte_table_action_encap_config *cfg,
    1102                 :            :         void *ip,
    1103                 :            :         uint16_t total_length,
    1104                 :            :         uint32_t ip_offset)
    1105                 :            : {
    1106                 :          0 :         switch (cfg->encap_mask) {
    1107                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER:
    1108                 :            :                 encap(ip, data, sizeof(struct encap_ether_data));
    1109                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
    1110                 :            :                         sizeof(struct encap_ether_data));
    1111                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length +
    1112                 :            :                         sizeof(struct encap_ether_data);
    1113                 :          0 :                 break;
    1114                 :            : 
    1115                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN:
    1116                 :            :                 encap(ip, data, sizeof(struct encap_vlan_data));
    1117                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
    1118                 :            :                         sizeof(struct encap_vlan_data));
    1119                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length +
    1120                 :            :                         sizeof(struct encap_vlan_data);
    1121                 :          0 :                 break;
    1122                 :            : 
    1123                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ:
    1124                 :            :                 encap(ip, data, sizeof(struct encap_qinq_data));
    1125                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
    1126                 :            :                         sizeof(struct encap_qinq_data));
    1127                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length +
    1128                 :            :                         sizeof(struct encap_qinq_data);
    1129                 :          0 :                 break;
    1130                 :            : 
    1131                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS:
    1132                 :            :         {
    1133                 :            :                 struct encap_mpls_data *mpls = data;
    1134                 :          0 :                 size_t size = sizeof(struct rte_ether_hdr) +
    1135   [ #  #  #  #  :          0 :                         mpls->mpls_count * 4;
          #  #  #  #  #  
                #  #  # ]
    1136                 :            : 
    1137                 :            :                 encap(ip, data, size);
    1138                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) + size);
    1139                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length + size;
    1140                 :          0 :                 break;
    1141                 :            :         }
    1142                 :            : 
    1143                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE:
    1144                 :            :         {
    1145                 :            :                 struct encap_pppoe_data *pppoe =
    1146                 :            :                         encap(ip, data, sizeof(struct encap_pppoe_data));
    1147   [ #  #  #  #  :          0 :                 pppoe->pppoe_ppp.length = rte_htons(total_length + 2);
          #  #  #  #  #  
                #  #  # ]
    1148                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
    1149                 :            :                         sizeof(struct encap_pppoe_data));
    1150                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length +
    1151                 :            :                         sizeof(struct encap_pppoe_data);
    1152                 :          0 :                 break;
    1153                 :            :         }
    1154                 :            : 
    1155                 :            :         case 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE:
    1156                 :            :         {
    1157                 :            :                 struct encap_qinq_pppoe_data *qinq_pppoe =
    1158                 :            :                         encap(ip, data, sizeof(struct encap_qinq_pppoe_data));
    1159   [ #  #  #  #  :          0 :                 qinq_pppoe->pppoe_ppp.length = rte_htons(total_length + 2);
          #  #  #  #  #  
                #  #  # ]
    1160                 :          0 :                 mbuf->data_off = ip_offset - (sizeof(struct rte_mbuf) +
    1161                 :            :                         sizeof(struct encap_qinq_pppoe_data));
    1162                 :          0 :                 mbuf->pkt_len = mbuf->data_len = total_length +
    1163                 :            :                         sizeof(struct encap_qinq_pppoe_data);
    1164                 :          0 :                 break;
    1165                 :            :         }
    1166                 :            : 
    1167                 :          0 :         case 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN:
    1168                 :            :         {
    1169   [ #  #  #  #  :          0 :                 if (cfg->vxlan.ip_version)
          #  #  #  #  #  
                #  #  # ]
    1170   [ #  #  #  #  :          0 :                         if (cfg->vxlan.vlan)
          #  #  #  #  #  
                #  #  # ]
    1171                 :            :                                 pkt_work_encap_vxlan_ipv4_vlan(mbuf, data, cfg);
    1172                 :            :                         else
    1173                 :            :                                 pkt_work_encap_vxlan_ipv4(mbuf, data, cfg);
    1174                 :            :                 else
    1175   [ #  #  #  #  :          0 :                         if (cfg->vxlan.vlan)
          #  #  #  #  #  
                #  #  # ]
    1176                 :            :                                 pkt_work_encap_vxlan_ipv6_vlan(mbuf, data, cfg);
    1177                 :            :                         else
    1178                 :            :                                 pkt_work_encap_vxlan_ipv6(mbuf, data, cfg);
    1179                 :            :         }
    1180                 :            : 
    1181                 :            :         default:
    1182                 :            :                 break;
    1183                 :            :         }
    1184                 :            : }
    1185                 :            : 
    1186                 :            : /**
    1187                 :            :  * RTE_TABLE_ACTION_NAT
    1188                 :            :  */
    1189                 :            : static int
    1190                 :            : nat_cfg_check(struct rte_table_action_nat_config *nat)
    1191                 :            : {
    1192         [ #  # ]:          0 :         if ((nat->proto != 0x06) &&
    1193                 :            :                 (nat->proto != 0x11))
    1194                 :            :                 return -ENOTSUP;
    1195                 :            : 
    1196                 :            :         return 0;
    1197                 :            : }
    1198                 :            : 
    1199                 :            : struct __rte_packed_begin nat_ipv4_data {
    1200                 :            :         uint32_t addr;
    1201                 :            :         uint16_t port;
    1202                 :            : } __rte_packed_end;
    1203                 :            : 
    1204                 :            : struct __rte_packed_begin nat_ipv6_data {
    1205                 :            :         struct rte_ipv6_addr addr;
    1206                 :            :         uint16_t port;
    1207                 :            : } __rte_packed_end;
    1208                 :            : 
    1209                 :            : static size_t
    1210                 :            : nat_data_size(struct rte_table_action_nat_config *nat __rte_unused,
    1211                 :            :         struct rte_table_action_common_config *common)
    1212                 :            : {
    1213                 :          0 :         int ip_version = common->ip_version;
    1214                 :            : 
    1215                 :            :         return (ip_version) ?
    1216                 :          0 :                 sizeof(struct nat_ipv4_data) :
    1217                 :            :                 sizeof(struct nat_ipv6_data);
    1218                 :            : }
    1219                 :            : 
    1220                 :            : static int
    1221                 :            : nat_apply_check(struct rte_table_action_nat_params *p,
    1222                 :            :         struct rte_table_action_common_config *cfg)
    1223                 :            : {
    1224   [ #  #  #  # ]:          0 :         if ((p->ip_version && (cfg->ip_version == 0)) ||
    1225         [ #  # ]:          0 :                 ((p->ip_version == 0) && cfg->ip_version))
    1226                 :            :                 return -EINVAL;
    1227                 :            : 
    1228                 :            :         return 0;
    1229                 :            : }
    1230                 :            : 
    1231                 :            : static int
    1232         [ #  # ]:          0 : nat_apply(void *data,
    1233                 :            :         struct rte_table_action_nat_params *p,
    1234                 :            :         struct rte_table_action_common_config *cfg)
    1235                 :            : {
    1236                 :            :         int status;
    1237                 :            : 
    1238                 :            :         /* Check input arguments */
    1239                 :            :         status = nat_apply_check(p, cfg);
    1240                 :            :         if (status)
    1241                 :            :                 return status;
    1242                 :            : 
    1243                 :            :         /* Apply */
    1244         [ #  # ]:          0 :         if (p->ip_version) {
    1245                 :            :                 struct nat_ipv4_data *d = data;
    1246                 :            : 
    1247         [ #  # ]:          0 :                 d->addr = rte_htonl(p->addr.ipv4);
    1248         [ #  # ]:          0 :                 d->port = rte_htons(p->port);
    1249                 :            :         } else {
    1250                 :            :                 struct nat_ipv6_data *d = data;
    1251                 :            : 
    1252                 :          0 :                 d->addr = p->addr.ipv6;
    1253         [ #  # ]:          0 :                 d->port = rte_htons(p->port);
    1254                 :            :         }
    1255                 :            : 
    1256                 :            :         return 0;
    1257                 :            : }
    1258                 :            : 
    1259                 :            : static __rte_always_inline uint16_t
    1260                 :            : nat_ipv4_checksum_update(uint16_t cksum0,
    1261                 :            :         uint32_t ip0,
    1262                 :            :         uint32_t ip1)
    1263                 :            : {
    1264                 :            :         int32_t cksum1;
    1265                 :            : 
    1266                 :            :         cksum1 = cksum0;
    1267                 :            :         cksum1 = ~cksum1 & 0xFFFF;
    1268                 :            : 
    1269                 :            :         /* Subtract ip0 (one's complement logic) */
    1270                 :          0 :         cksum1 -= (ip0 >> 16) + (ip0 & 0xFFFF);
    1271                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1272                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1273                 :            : 
    1274                 :            :         /* Add ip1 (one's complement logic) */
    1275                 :          0 :         cksum1 += (ip1 >> 16) + (ip1 & 0xFFFF);
    1276                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1277                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1278                 :            : 
    1279                 :          0 :         return (uint16_t)(~cksum1);
    1280                 :            : }
    1281                 :            : 
    1282                 :            : static __rte_always_inline uint16_t
    1283                 :            : nat_ipv4_tcp_udp_checksum_update(uint16_t cksum0,
    1284                 :            :         uint32_t ip0,
    1285                 :            :         uint32_t ip1,
    1286                 :            :         uint16_t port0,
    1287                 :            :         uint16_t port1)
    1288                 :            : {
    1289                 :            :         int32_t cksum1;
    1290                 :            : 
    1291                 :            :         cksum1 = cksum0;
    1292                 :            :         cksum1 = ~cksum1 & 0xFFFF;
    1293                 :            : 
    1294                 :            :         /* Subtract ip0 and port 0 (one's complement logic) */
    1295                 :          0 :         cksum1 -= (ip0 >> 16) + (ip0 & 0xFFFF) + port0;
    1296                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1297                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1298                 :            : 
    1299                 :            :         /* Add ip1 and port1 (one's complement logic) */
    1300                 :          0 :         cksum1 += (ip1 >> 16) + (ip1 & 0xFFFF) + port1;
    1301                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1302                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1303                 :            : 
    1304                 :          0 :         return (uint16_t)(~cksum1);
    1305                 :            : }
    1306                 :            : 
    1307                 :            : static __rte_always_inline uint16_t
    1308                 :            : nat_ipv6_tcp_udp_checksum_update(uint16_t cksum0,
    1309                 :            :         uint16_t *ip0,
    1310                 :            :         uint16_t *ip1,
    1311                 :            :         uint16_t port0,
    1312                 :            :         uint16_t port1)
    1313                 :            : {
    1314                 :            :         int32_t cksum1;
    1315                 :            : 
    1316                 :            :         cksum1 = cksum0;
    1317                 :          0 :         cksum1 = ~cksum1 & 0xFFFF;
    1318                 :            : 
    1319                 :            :         /* Subtract ip0 and port 0 (one's complement logic) */
    1320                 :          0 :         cksum1 -= ip0[0] + ip0[1] + ip0[2] + ip0[3] +
    1321                 :          0 :                 ip0[4] + ip0[5] + ip0[6] + ip0[7] + port0;
    1322                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1323                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1324                 :            : 
    1325                 :            :         /* Add ip1 and port1 (one's complement logic) */
    1326                 :          0 :         cksum1 += ip1[0] + ip1[1] + ip1[2] + ip1[3] +
    1327                 :          0 :                 ip1[4] + ip1[5] + ip1[6] + ip1[7] + port1;
    1328                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1329                 :          0 :         cksum1 = (cksum1 & 0xFFFF) + (cksum1 >> 16);
    1330                 :            : 
    1331                 :          0 :         return (uint16_t)(~cksum1);
    1332                 :            : }
    1333                 :            : 
    1334                 :            : static __rte_always_inline void
    1335                 :            : pkt_ipv4_work_nat(struct rte_ipv4_hdr *ip,
    1336                 :            :         struct nat_ipv4_data *data,
    1337                 :            :         struct rte_table_action_nat_config *cfg)
    1338                 :            : {
    1339   [ #  #  #  #  :          0 :         if (cfg->source_nat) {
          #  #  #  #  #  
                #  #  # ]
    1340   [ #  #  #  #  :          0 :                 if (cfg->proto == 0x6) {
          #  #  #  #  #  
                #  #  # ]
    1341                 :            :                         struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *) &ip[1];
    1342                 :            :                         uint16_t ip_cksum, tcp_cksum;
    1343                 :            : 
    1344                 :          0 :                         ip_cksum = nat_ipv4_checksum_update(ip->hdr_checksum,
    1345                 :            :                                 ip->src_addr,
    1346                 :            :                                 data->addr);
    1347                 :            : 
    1348                 :          0 :                         tcp_cksum = nat_ipv4_tcp_udp_checksum_update(tcp->cksum,
    1349                 :            :                                 ip->src_addr,
    1350                 :            :                                 data->addr,
    1351                 :          0 :                                 tcp->src_port,
    1352                 :          0 :                                 data->port);
    1353                 :            : 
    1354                 :          0 :                         ip->src_addr = data->addr;
    1355                 :          0 :                         ip->hdr_checksum = ip_cksum;
    1356                 :          0 :                         tcp->src_port = data->port;
    1357                 :          0 :                         tcp->cksum = tcp_cksum;
    1358                 :            :                 } else {
    1359                 :            :                         struct rte_udp_hdr *udp = (struct rte_udp_hdr *) &ip[1];
    1360                 :            :                         uint16_t ip_cksum, udp_cksum;
    1361                 :            : 
    1362                 :          0 :                         ip_cksum = nat_ipv4_checksum_update(ip->hdr_checksum,
    1363                 :            :                                 ip->src_addr,
    1364                 :            :                                 data->addr);
    1365                 :            : 
    1366                 :          0 :                         udp_cksum = nat_ipv4_tcp_udp_checksum_update(udp->dgram_cksum,
    1367                 :            :                                 ip->src_addr,
    1368                 :            :                                 data->addr,
    1369                 :          0 :                                 udp->src_port,
    1370                 :          0 :                                 data->port);
    1371                 :            : 
    1372                 :          0 :                         ip->src_addr = data->addr;
    1373                 :          0 :                         ip->hdr_checksum = ip_cksum;
    1374                 :          0 :                         udp->src_port = data->port;
    1375   [ #  #  #  #  :          0 :                         if (udp->dgram_cksum)
          #  #  #  #  #  
                #  #  # ]
    1376                 :          0 :                                 udp->dgram_cksum = udp_cksum;
    1377                 :            :                 }
    1378                 :            :         } else {
    1379   [ #  #  #  #  :          0 :                 if (cfg->proto == 0x6) {
          #  #  #  #  #  
                #  #  # ]
    1380                 :            :                         struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *) &ip[1];
    1381                 :            :                         uint16_t ip_cksum, tcp_cksum;
    1382                 :            : 
    1383                 :          0 :                         ip_cksum = nat_ipv4_checksum_update(ip->hdr_checksum,
    1384                 :            :                                 ip->dst_addr,
    1385                 :            :                                 data->addr);
    1386                 :            : 
    1387                 :          0 :                         tcp_cksum = nat_ipv4_tcp_udp_checksum_update(tcp->cksum,
    1388                 :            :                                 ip->dst_addr,
    1389                 :            :                                 data->addr,
    1390                 :          0 :                                 tcp->dst_port,
    1391                 :          0 :                                 data->port);
    1392                 :            : 
    1393                 :          0 :                         ip->dst_addr = data->addr;
    1394                 :          0 :                         ip->hdr_checksum = ip_cksum;
    1395                 :          0 :                         tcp->dst_port = data->port;
    1396                 :          0 :                         tcp->cksum = tcp_cksum;
    1397                 :            :                 } else {
    1398                 :            :                         struct rte_udp_hdr *udp = (struct rte_udp_hdr *) &ip[1];
    1399                 :            :                         uint16_t ip_cksum, udp_cksum;
    1400                 :            : 
    1401                 :          0 :                         ip_cksum = nat_ipv4_checksum_update(ip->hdr_checksum,
    1402                 :            :                                 ip->dst_addr,
    1403                 :            :                                 data->addr);
    1404                 :            : 
    1405                 :          0 :                         udp_cksum = nat_ipv4_tcp_udp_checksum_update(udp->dgram_cksum,
    1406                 :            :                                 ip->dst_addr,
    1407                 :            :                                 data->addr,
    1408                 :          0 :                                 udp->dst_port,
    1409                 :          0 :                                 data->port);
    1410                 :            : 
    1411                 :          0 :                         ip->dst_addr = data->addr;
    1412                 :          0 :                         ip->hdr_checksum = ip_cksum;
    1413                 :          0 :                         udp->dst_port = data->port;
    1414   [ #  #  #  #  :          0 :                         if (udp->dgram_cksum)
          #  #  #  #  #  
                #  #  # ]
    1415                 :          0 :                                 udp->dgram_cksum = udp_cksum;
    1416                 :            :                 }
    1417                 :            :         }
    1418                 :            : }
    1419                 :            : 
    1420                 :            : static __rte_always_inline void
    1421                 :            : pkt_ipv6_work_nat(struct rte_ipv6_hdr *ip,
    1422                 :            :         struct nat_ipv6_data *data,
    1423                 :            :         struct rte_table_action_nat_config *cfg)
    1424                 :            : {
    1425   [ #  #  #  #  :          0 :         if (cfg->source_nat) {
          #  #  #  #  #  
                #  #  # ]
    1426   [ #  #  #  #  :          0 :                 if (cfg->proto == 0x6) {
          #  #  #  #  #  
                #  #  # ]
    1427                 :            :                         struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *) &ip[1];
    1428                 :            :                         uint16_t tcp_cksum;
    1429                 :            : 
    1430                 :          0 :                         tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
    1431                 :            :                                 (uint16_t *)&ip->src_addr,
    1432                 :            :                                 (uint16_t *)&data->addr,
    1433                 :          0 :                                 tcp->src_port,
    1434                 :          0 :                                 data->port);
    1435                 :            : 
    1436                 :          0 :                         ip->src_addr = data->addr;
    1437                 :          0 :                         tcp->src_port = data->port;
    1438                 :          0 :                         tcp->cksum = tcp_cksum;
    1439                 :            :                 } else {
    1440                 :            :                         struct rte_udp_hdr *udp = (struct rte_udp_hdr *) &ip[1];
    1441                 :            :                         uint16_t udp_cksum;
    1442                 :            : 
    1443                 :          0 :                         udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
    1444                 :            :                                 (uint16_t *)&ip->src_addr,
    1445                 :            :                                 (uint16_t *)&data->addr,
    1446                 :          0 :                                 udp->src_port,
    1447                 :          0 :                                 data->port);
    1448                 :            : 
    1449                 :          0 :                         ip->src_addr = data->addr;
    1450                 :          0 :                         udp->src_port = data->port;
    1451                 :          0 :                         udp->dgram_cksum = udp_cksum;
    1452                 :            :                 }
    1453                 :            :         } else {
    1454   [ #  #  #  #  :          0 :                 if (cfg->proto == 0x6) {
          #  #  #  #  #  
                #  #  # ]
    1455                 :            :                         struct rte_tcp_hdr *tcp = (struct rte_tcp_hdr *) &ip[1];
    1456                 :            :                         uint16_t tcp_cksum;
    1457                 :            : 
    1458                 :          0 :                         tcp_cksum = nat_ipv6_tcp_udp_checksum_update(tcp->cksum,
    1459                 :            :                                 (uint16_t *)&ip->dst_addr,
    1460                 :            :                                 (uint16_t *)&data->addr,
    1461                 :          0 :                                 tcp->dst_port,
    1462                 :          0 :                                 data->port);
    1463                 :            : 
    1464                 :          0 :                         ip->dst_addr = data->addr;
    1465                 :          0 :                         tcp->dst_port = data->port;
    1466                 :          0 :                         tcp->cksum = tcp_cksum;
    1467                 :            :                 } else {
    1468                 :            :                         struct rte_udp_hdr *udp = (struct rte_udp_hdr *) &ip[1];
    1469                 :            :                         uint16_t udp_cksum;
    1470                 :            : 
    1471                 :          0 :                         udp_cksum = nat_ipv6_tcp_udp_checksum_update(udp->dgram_cksum,
    1472                 :            :                                 (uint16_t *)&ip->dst_addr,
    1473                 :            :                                 (uint16_t *)&data->addr,
    1474                 :          0 :                                 udp->dst_port,
    1475                 :          0 :                                 data->port);
    1476                 :            : 
    1477                 :          0 :                         ip->dst_addr = data->addr;
    1478                 :          0 :                         udp->dst_port = data->port;
    1479                 :          0 :                         udp->dgram_cksum = udp_cksum;
    1480                 :            :                 }
    1481                 :            :         }
    1482                 :            : }
    1483                 :            : 
    1484                 :            : /**
    1485                 :            :  * RTE_TABLE_ACTION_TTL
    1486                 :            :  */
    1487                 :            : static int
    1488                 :            : ttl_cfg_check(struct rte_table_action_ttl_config *ttl)
    1489                 :            : {
    1490         [ #  # ]:          0 :         if (ttl->drop == 0)
    1491                 :            :                 return -ENOTSUP;
    1492                 :            : 
    1493                 :            :         return 0;
    1494                 :            : }
    1495                 :            : 
    1496                 :            : struct __rte_packed_begin ttl_data {
    1497                 :            :         uint32_t n_packets;
    1498                 :            : } __rte_packed_end;
    1499                 :            : 
    1500                 :            : #define TTL_INIT(data, decrement)                         \
    1501                 :            :         ((data)->n_packets = (decrement) ? 1 : 0)
    1502                 :            : 
    1503                 :            : #define TTL_DEC_GET(data)                                  \
    1504                 :            :         ((uint8_t)((data)->n_packets & 1))
    1505                 :            : 
    1506                 :            : #define TTL_STATS_RESET(data)                             \
    1507                 :            :         ((data)->n_packets = ((data)->n_packets & 1))
    1508                 :            : 
    1509                 :            : #define TTL_STATS_READ(data)                               \
    1510                 :            :         ((data)->n_packets >> 1)
    1511                 :            : 
    1512                 :            : #define TTL_STATS_ADD(data, value)                        \
    1513                 :            :         ((data)->n_packets =                                  \
    1514                 :            :                 (((((data)->n_packets >> 1) + (value)) << 1) |    \
    1515                 :            :                 ((data)->n_packets & 1)))
    1516                 :            : 
    1517                 :            : static int
    1518                 :            : ttl_apply(void *data,
    1519                 :            :         struct rte_table_action_ttl_params *p)
    1520                 :            : {
    1521                 :            :         struct ttl_data *d = data;
    1522                 :            : 
    1523                 :          0 :         TTL_INIT(d, p->decrement);
    1524                 :            : 
    1525                 :            :         return 0;
    1526                 :            : }
    1527                 :            : 
    1528                 :            : static __rte_always_inline uint64_t
    1529                 :            : pkt_ipv4_work_ttl(struct rte_ipv4_hdr *ip,
    1530                 :            :         struct ttl_data *data)
    1531                 :            : {
    1532                 :            :         uint32_t drop;
    1533                 :          0 :         uint16_t cksum = ip->hdr_checksum;
    1534                 :          0 :         uint8_t ttl = ip->time_to_live;
    1535                 :          0 :         uint8_t ttl_diff = TTL_DEC_GET(data);
    1536                 :            : 
    1537                 :          0 :         cksum += ttl_diff;
    1538                 :          0 :         ttl -= ttl_diff;
    1539                 :            : 
    1540                 :          0 :         ip->hdr_checksum = cksum;
    1541                 :          0 :         ip->time_to_live = ttl;
    1542                 :            : 
    1543                 :          0 :         drop = (ttl == 0) ? 1 : 0;
    1544                 :          0 :         TTL_STATS_ADD(data, drop);
    1545                 :            : 
    1546                 :          0 :         return drop;
    1547                 :            : }
    1548                 :            : 
    1549                 :            : static __rte_always_inline uint64_t
    1550                 :            : pkt_ipv6_work_ttl(struct rte_ipv6_hdr *ip,
    1551                 :            :         struct ttl_data *data)
    1552                 :            : {
    1553                 :            :         uint32_t drop;
    1554                 :          0 :         uint8_t ttl = ip->hop_limits;
    1555                 :          0 :         uint8_t ttl_diff = TTL_DEC_GET(data);
    1556                 :            : 
    1557                 :          0 :         ttl -= ttl_diff;
    1558                 :            : 
    1559                 :          0 :         ip->hop_limits = ttl;
    1560                 :            : 
    1561                 :          0 :         drop = (ttl == 0) ? 1 : 0;
    1562                 :          0 :         TTL_STATS_ADD(data, drop);
    1563                 :            : 
    1564                 :          0 :         return drop;
    1565                 :            : }
    1566                 :            : 
    1567                 :            : /**
    1568                 :            :  * RTE_TABLE_ACTION_STATS
    1569                 :            :  */
    1570                 :            : static int
    1571                 :            : stats_cfg_check(struct rte_table_action_stats_config *stats)
    1572                 :            : {
    1573   [ #  #  #  # ]:          0 :         if ((stats->n_packets_enabled == 0) && (stats->n_bytes_enabled == 0))
    1574                 :            :                 return -EINVAL;
    1575                 :            : 
    1576                 :            :         return 0;
    1577                 :            : }
    1578                 :            : 
    1579                 :            : struct __rte_packed_begin stats_data {
    1580                 :            :         uint64_t n_packets;
    1581                 :            :         uint64_t n_bytes;
    1582                 :            : } __rte_packed_end;
    1583                 :            : 
    1584                 :            : static int
    1585                 :            : stats_apply(struct stats_data *data,
    1586                 :            :         struct rte_table_action_stats_params *p)
    1587                 :            : {
    1588                 :          0 :         data->n_packets = p->n_packets;
    1589                 :          0 :         data->n_bytes = p->n_bytes;
    1590                 :            : 
    1591                 :            :         return 0;
    1592                 :            : }
    1593                 :            : 
    1594                 :            : static __rte_always_inline void
    1595                 :            : pkt_work_stats(struct stats_data *data,
    1596                 :            :         uint16_t total_length)
    1597                 :            : {
    1598                 :          0 :         data->n_packets++;
    1599                 :          0 :         data->n_bytes += total_length;
    1600                 :          0 : }
    1601                 :            : 
    1602                 :            : /**
    1603                 :            :  * RTE_TABLE_ACTION_TIME
    1604                 :            :  */
    1605                 :            : struct __rte_packed_begin time_data {
    1606                 :            :         uint64_t time;
    1607                 :            : } __rte_packed_end;
    1608                 :            : 
    1609                 :            : static int
    1610                 :            : time_apply(struct time_data *data,
    1611                 :            :         struct rte_table_action_time_params *p)
    1612                 :            : {
    1613                 :          0 :         data->time = p->time;
    1614                 :            :         return 0;
    1615                 :            : }
    1616                 :            : 
    1617                 :            : static __rte_always_inline void
    1618                 :            : pkt_work_time(struct time_data *data,
    1619                 :            :         uint64_t time)
    1620                 :            : {
    1621                 :          0 :         data->time = time;
    1622                 :          0 : }
    1623                 :            : 
    1624                 :            : 
    1625                 :            : /**
    1626                 :            :  * RTE_TABLE_ACTION_CRYPTO
    1627                 :            :  */
    1628                 :            : 
    1629                 :            : #define CRYPTO_OP_MASK_CIPHER   0x1
    1630                 :            : #define CRYPTO_OP_MASK_AUTH     0x2
    1631                 :            : #define CRYPTO_OP_MASK_AEAD     0x4
    1632                 :            : 
    1633                 :            : struct crypto_op_sym_iv_aad {
    1634                 :            :         struct rte_crypto_op op;
    1635                 :            :         struct rte_crypto_sym_op sym_op;
    1636                 :            :         union {
    1637                 :            :                 struct {
    1638                 :            :                         uint8_t cipher_iv[
    1639                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX];
    1640                 :            :                         uint8_t auth_iv[
    1641                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX];
    1642                 :            :                 } cipher_auth;
    1643                 :            : 
    1644                 :            :                 struct {
    1645                 :            :                         uint8_t iv[RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX];
    1646                 :            :                         uint8_t aad[RTE_TABLE_ACTION_SYM_CRYPTO_AAD_SIZE_MAX];
    1647                 :            :                 } aead_iv_aad;
    1648                 :            : 
    1649                 :            :         } iv_aad;
    1650                 :            : };
    1651                 :            : 
    1652                 :            : struct __rte_packed_begin sym_crypto_data {
    1653                 :            : 
    1654                 :            :         union {
    1655                 :            :                 struct {
    1656                 :            : 
    1657                 :            :                         /** Length of cipher iv. */
    1658                 :            :                         uint16_t cipher_iv_len;
    1659                 :            : 
    1660                 :            :                         /** Offset from start of IP header to the cipher iv. */
    1661                 :            :                         uint16_t cipher_iv_data_offset;
    1662                 :            : 
    1663                 :            :                         /** Length of cipher iv to be updated in the mbuf. */
    1664                 :            :                         uint16_t cipher_iv_update_len;
    1665                 :            : 
    1666                 :            :                         /** Offset from start of IP header to the auth iv. */
    1667                 :            :                         uint16_t auth_iv_data_offset;
    1668                 :            : 
    1669                 :            :                         /** Length of auth iv in the mbuf. */
    1670                 :            :                         uint16_t auth_iv_len;
    1671                 :            : 
    1672                 :            :                         /** Length of auth iv to be updated in the mbuf. */
    1673                 :            :                         uint16_t auth_iv_update_len;
    1674                 :            : 
    1675                 :            :                 } cipher_auth;
    1676                 :            :                 struct {
    1677                 :            : 
    1678                 :            :                         /** Length of iv. */
    1679                 :            :                         uint16_t iv_len;
    1680                 :            : 
    1681                 :            :                         /** Offset from start of IP header to the aead iv. */
    1682                 :            :                         uint16_t iv_data_offset;
    1683                 :            : 
    1684                 :            :                         /** Length of iv to be updated in the mbuf. */
    1685                 :            :                         uint16_t iv_update_len;
    1686                 :            : 
    1687                 :            :                         /** Length of aad */
    1688                 :            :                         uint16_t aad_len;
    1689                 :            : 
    1690                 :            :                         /** Offset from start of IP header to the aad. */
    1691                 :            :                         uint16_t aad_data_offset;
    1692                 :            : 
    1693                 :            :                         /** Length of aad to updated in the mbuf. */
    1694                 :            :                         uint16_t aad_update_len;
    1695                 :            : 
    1696                 :            :                 } aead;
    1697                 :            :         };
    1698                 :            : 
    1699                 :            :         /** Offset from start of IP header to the data. */
    1700                 :            :         uint16_t data_offset;
    1701                 :            : 
    1702                 :            :         /** Digest length. */
    1703                 :            :         uint16_t digest_len;
    1704                 :            : 
    1705                 :            :         /** block size */
    1706                 :            :         uint16_t block_size;
    1707                 :            : 
    1708                 :            :         /** Mask of crypto operation */
    1709                 :            :         uint16_t op_mask;
    1710                 :            : 
    1711                 :            :         /** Session pointer. */
    1712                 :            :         struct rte_cryptodev_sym_session *session;
    1713                 :            : 
    1714                 :            :         /** Direction of crypto, encrypt or decrypt */
    1715                 :            :         uint16_t direction;
    1716                 :            : 
    1717                 :            :         /** Private data size to store cipher iv / aad. */
    1718                 :            :         uint8_t iv_aad_data[32];
    1719                 :            : 
    1720                 :            : } __rte_packed_end;
    1721                 :            : 
    1722                 :            : static int
    1723                 :          0 : sym_crypto_cfg_check(struct rte_table_action_sym_crypto_config *cfg)
    1724                 :            : {
    1725         [ #  # ]:          0 :         if (!rte_cryptodev_is_valid_dev(cfg->cryptodev_id))
    1726                 :            :                 return -EINVAL;
    1727   [ #  #  #  # ]:          0 :         if (cfg->mp_create == NULL || cfg->mp_init == NULL)
    1728                 :          0 :                 return -EINVAL;
    1729                 :            : 
    1730                 :            :         return 0;
    1731                 :            : }
    1732                 :            : 
    1733                 :            : static int
    1734                 :          0 : get_block_size(const struct rte_crypto_sym_xform *xform, uint8_t cdev_id)
    1735                 :            : {
    1736                 :            :         struct rte_cryptodev_info dev_info;
    1737                 :            :         const struct rte_cryptodev_capabilities *cap;
    1738                 :            :         uint32_t i;
    1739                 :            : 
    1740                 :          0 :         rte_cryptodev_info_get(cdev_id, &dev_info);
    1741                 :            : 
    1742         [ #  # ]:          0 :         for (i = 0; dev_info.capabilities[i].op != RTE_CRYPTO_OP_TYPE_UNDEFINED;
    1743                 :          0 :                         i++) {
    1744                 :            :                 cap = &dev_info.capabilities[i];
    1745                 :            : 
    1746         [ #  # ]:          0 :                 if (cap->sym.xform_type != xform->type)
    1747                 :          0 :                         continue;
    1748                 :            : 
    1749         [ #  # ]:          0 :                 if ((xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) &&
    1750         [ #  # ]:          0 :                                 (cap->sym.cipher.algo == xform->cipher.algo))
    1751                 :          0 :                         return cap->sym.cipher.block_size;
    1752                 :            : 
    1753         [ #  # ]:          0 :                 if ((xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) &&
    1754         [ #  # ]:          0 :                                 (cap->sym.aead.algo == xform->aead.algo))
    1755                 :          0 :                         return cap->sym.aead.block_size;
    1756                 :            : 
    1757         [ #  # ]:          0 :                 if (xform->type == RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED)
    1758                 :            :                         break;
    1759                 :            :         }
    1760                 :            : 
    1761                 :            :         return -1;
    1762                 :            : }
    1763                 :            : 
    1764                 :            : static int
    1765                 :          0 : sym_crypto_apply(struct sym_crypto_data *data,
    1766                 :            :         struct rte_table_action_sym_crypto_config *cfg,
    1767                 :            :         struct rte_table_action_sym_crypto_params *p)
    1768                 :            : {
    1769                 :            :         const struct rte_crypto_cipher_xform *cipher_xform = NULL;
    1770                 :            :         const struct rte_crypto_auth_xform *auth_xform = NULL;
    1771                 :            :         const struct rte_crypto_aead_xform *aead_xform = NULL;
    1772                 :          0 :         struct rte_crypto_sym_xform *xform = p->xform;
    1773                 :            :         struct rte_cryptodev_sym_session *session;
    1774                 :            :         int ret;
    1775                 :            : 
    1776                 :            :         memset(data, 0, sizeof(*data));
    1777                 :            : 
    1778         [ #  # ]:          0 :         while (xform) {
    1779         [ #  # ]:          0 :                 if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
    1780                 :          0 :                         cipher_xform = &xform->cipher;
    1781                 :            : 
    1782         [ #  # ]:          0 :                         if (cipher_xform->iv.length >
    1783                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX)
    1784                 :            :                                 return -ENOMEM;
    1785         [ #  # ]:          0 :                         if (cipher_xform->iv.offset !=
    1786                 :            :                                         RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET)
    1787                 :            :                                 return -EINVAL;
    1788                 :            : 
    1789                 :          0 :                         ret = get_block_size(xform, cfg->cryptodev_id);
    1790         [ #  # ]:          0 :                         if (ret < 0)
    1791                 :            :                                 return -1;
    1792                 :          0 :                         data->block_size = (uint16_t)ret;
    1793                 :          0 :                         data->op_mask |= CRYPTO_OP_MASK_CIPHER;
    1794                 :            : 
    1795                 :          0 :                         data->cipher_auth.cipher_iv_len =
    1796                 :          0 :                                         cipher_xform->iv.length;
    1797                 :          0 :                         data->cipher_auth.cipher_iv_data_offset = (uint16_t)
    1798                 :          0 :                                         p->cipher_auth.cipher_iv_update.offset;
    1799                 :          0 :                         data->cipher_auth.cipher_iv_update_len = (uint16_t)
    1800                 :          0 :                                         p->cipher_auth.cipher_iv_update.length;
    1801                 :            : 
    1802                 :          0 :                         rte_memcpy(data->iv_aad_data,
    1803                 :          0 :                                         p->cipher_auth.cipher_iv.val,
    1804         [ #  # ]:          0 :                                         p->cipher_auth.cipher_iv.length);
    1805                 :            : 
    1806                 :          0 :                         data->direction = cipher_xform->op;
    1807                 :            : 
    1808         [ #  # ]:          0 :                 } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
    1809                 :          0 :                         auth_xform = &xform->auth;
    1810         [ #  # ]:          0 :                         if (auth_xform->iv.length >
    1811                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX)
    1812                 :            :                                 return -ENOMEM;
    1813                 :          0 :                         data->op_mask |= CRYPTO_OP_MASK_AUTH;
    1814                 :            : 
    1815                 :          0 :                         data->cipher_auth.auth_iv_len = auth_xform->iv.length;
    1816                 :          0 :                         data->cipher_auth.auth_iv_data_offset = (uint16_t)
    1817                 :          0 :                                         p->cipher_auth.auth_iv_update.offset;
    1818                 :          0 :                         data->cipher_auth.auth_iv_update_len = (uint16_t)
    1819                 :          0 :                                         p->cipher_auth.auth_iv_update.length;
    1820                 :          0 :                         data->digest_len = auth_xform->digest_length;
    1821                 :            : 
    1822                 :          0 :                         data->direction = (auth_xform->op ==
    1823                 :            :                                         RTE_CRYPTO_AUTH_OP_GENERATE) ?
    1824                 :          0 :                                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
    1825                 :            :                                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
    1826                 :            : 
    1827         [ #  # ]:          0 :                 } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
    1828                 :            :                         aead_xform = &xform->aead;
    1829                 :            : 
    1830         [ #  # ]:          0 :                         if ((aead_xform->iv.length >
    1831                 :          0 :                                 RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX) || (
    1832         [ #  # ]:          0 :                                 aead_xform->aad_length >
    1833                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO_AAD_SIZE_MAX))
    1834                 :            :                                 return -EINVAL;
    1835         [ #  # ]:          0 :                         if (aead_xform->iv.offset !=
    1836                 :            :                                         RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET)
    1837                 :            :                                 return -EINVAL;
    1838                 :            : 
    1839                 :          0 :                         ret = get_block_size(xform, cfg->cryptodev_id);
    1840         [ #  # ]:          0 :                         if (ret < 0)
    1841                 :            :                                 return -1;
    1842                 :          0 :                         data->block_size = (uint16_t)ret;
    1843                 :          0 :                         data->op_mask |= CRYPTO_OP_MASK_AEAD;
    1844                 :            : 
    1845                 :          0 :                         data->digest_len = aead_xform->digest_length;
    1846                 :          0 :                         data->aead.iv_len = aead_xform->iv.length;
    1847                 :          0 :                         data->aead.aad_len = aead_xform->aad_length;
    1848                 :            : 
    1849                 :          0 :                         data->aead.iv_data_offset = (uint16_t)
    1850                 :          0 :                                         p->aead.iv_update.offset;
    1851                 :          0 :                         data->aead.iv_update_len = (uint16_t)
    1852                 :          0 :                                         p->aead.iv_update.length;
    1853                 :          0 :                         data->aead.aad_data_offset = (uint16_t)
    1854                 :          0 :                                         p->aead.aad_update.offset;
    1855                 :          0 :                         data->aead.aad_update_len = (uint16_t)
    1856                 :          0 :                                         p->aead.aad_update.length;
    1857                 :            : 
    1858                 :          0 :                         rte_memcpy(data->iv_aad_data,
    1859                 :          0 :                                         p->aead.iv.val,
    1860         [ #  # ]:          0 :                                         p->aead.iv.length);
    1861                 :            : 
    1862                 :          0 :                         rte_memcpy(data->iv_aad_data + p->aead.iv.length,
    1863                 :          0 :                                         p->aead.aad.val,
    1864         [ #  # ]:          0 :                                         p->aead.aad.length);
    1865                 :            : 
    1866                 :          0 :                         data->direction = (aead_xform->op ==
    1867                 :            :                                         RTE_CRYPTO_AEAD_OP_ENCRYPT) ?
    1868                 :          0 :                                         RTE_CRYPTO_CIPHER_OP_ENCRYPT :
    1869                 :            :                                         RTE_CRYPTO_CIPHER_OP_DECRYPT;
    1870                 :            :                 } else
    1871                 :            :                         return -EINVAL;
    1872                 :            : 
    1873                 :          0 :                 xform = xform->next;
    1874                 :            :         }
    1875                 :            : 
    1876   [ #  #  #  # ]:          0 :         if (auth_xform && auth_xform->iv.length) {
    1877         [ #  # ]:          0 :                 if (cipher_xform) {
    1878                 :          0 :                         if (auth_xform->iv.offset !=
    1879                 :          0 :                                         RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET +
    1880         [ #  # ]:          0 :                                         cipher_xform->iv.length)
    1881                 :            :                                 return -EINVAL;
    1882                 :            : 
    1883                 :          0 :                         rte_memcpy(data->iv_aad_data + cipher_xform->iv.length,
    1884                 :          0 :                                         p->cipher_auth.auth_iv.val,
    1885         [ #  # ]:          0 :                                         p->cipher_auth.auth_iv.length);
    1886                 :            :                 } else {
    1887                 :          0 :                         rte_memcpy(data->iv_aad_data,
    1888                 :          0 :                                         p->cipher_auth.auth_iv.val,
    1889         [ #  # ]:          0 :                                         p->cipher_auth.auth_iv.length);
    1890                 :            :                 }
    1891                 :            :         }
    1892                 :            : 
    1893                 :          0 :         session = rte_cryptodev_sym_session_create(cfg->cryptodev_id,
    1894                 :            :                         p->xform, cfg->mp_create);
    1895         [ #  # ]:          0 :         if (!session)
    1896                 :            :                 return -ENOMEM;
    1897                 :            : 
    1898                 :          0 :         data->data_offset = (uint16_t)p->data_offset;
    1899                 :          0 :         data->session = session;
    1900                 :            : 
    1901                 :          0 :         return 0;
    1902                 :            : }
    1903                 :            : 
    1904                 :            : static __rte_always_inline uint64_t
    1905                 :            : pkt_work_sym_crypto(struct rte_mbuf *mbuf, struct sym_crypto_data *data,
    1906                 :            :                 struct rte_table_action_sym_crypto_config *cfg,
    1907                 :            :                 uint16_t ip_offset)
    1908                 :            : {
    1909                 :          0 :         struct crypto_op_sym_iv_aad *crypto_op = (struct crypto_op_sym_iv_aad *)
    1910                 :          0 :                         RTE_MBUF_METADATA_UINT8_PTR(mbuf, cfg->op_offset);
    1911                 :            :         struct rte_crypto_op *op = &crypto_op->op;
    1912                 :            :         struct rte_crypto_sym_op *sym = op->sym;
    1913                 :          0 :         uint32_t pkt_offset = sizeof(*mbuf) + mbuf->data_off;
    1914                 :          0 :         uint32_t payload_len = pkt_offset + mbuf->data_len - data->data_offset;
    1915                 :            : 
    1916                 :          0 :         op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
    1917                 :          0 :         op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
    1918                 :          0 :         op->phys_addr = rte_mbuf_iova_get(mbuf) + cfg->op_offset - sizeof(*mbuf);
    1919                 :          0 :         op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
    1920                 :          0 :         sym->m_src = mbuf;
    1921                 :          0 :         sym->m_dst = NULL;
    1922                 :          0 :         sym->session = data->session;
    1923                 :            : 
    1924                 :            :         /** pad the packet */
    1925                 :          0 :         if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
    1926                 :          0 :                 uint32_t append_len = RTE_ALIGN_CEIL(payload_len,
    1927                 :            :                                 data->block_size) - payload_len;
    1928                 :            : 
    1929   [ #  #  #  #  :          0 :                 if (unlikely(rte_pktmbuf_append(mbuf, append_len +
          #  #  #  #  #  
                #  #  # ]
    1930                 :            :                                 data->digest_len) == NULL))
    1931                 :            :                         return 1;
    1932                 :            : 
    1933                 :            :                 payload_len += append_len;
    1934                 :            :         } else
    1935                 :          0 :                 payload_len -= data->digest_len;
    1936                 :            : 
    1937   [ #  #  #  #  :          0 :         if (data->op_mask & CRYPTO_OP_MASK_CIPHER) {
          #  #  #  #  #  
                #  #  # ]
    1938                 :            :                 /** prepare cipher op */
    1939                 :          0 :                 uint8_t *iv = crypto_op->iv_aad.cipher_auth.cipher_iv;
    1940                 :            : 
    1941                 :          0 :                 sym->cipher.data.length = payload_len;
    1942                 :          0 :                 sym->cipher.data.offset = data->data_offset - pkt_offset;
    1943                 :            : 
    1944   [ #  #  #  #  :          0 :                 if (data->cipher_auth.cipher_iv_update_len) {
          #  #  #  #  #  
                #  #  # ]
    1945                 :          0 :                         uint8_t *pkt_iv = RTE_MBUF_METADATA_UINT8_PTR(mbuf,
    1946                 :            :                                 data->cipher_auth.cipher_iv_data_offset
    1947                 :            :                                 + ip_offset);
    1948                 :            : 
    1949                 :            :                         /** For encryption, update the pkt iv field, otherwise
    1950                 :            :                          *  update the iv_aad_field
    1951                 :            :                          */
    1952   [ #  #  #  #  :          0 :                         if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
          #  #  #  #  #  
                #  #  # ]
    1953   [ #  #  #  #  :          0 :                                 rte_memcpy(pkt_iv, data->iv_aad_data,
          #  #  #  #  #  
                #  #  # ]
    1954                 :            :                                         data->cipher_auth.cipher_iv_update_len);
    1955                 :            :                         else
    1956   [ #  #  #  #  :          0 :                                 rte_memcpy(data->iv_aad_data, pkt_iv,
          #  #  #  #  #  
                #  #  # ]
    1957                 :            :                                         data->cipher_auth.cipher_iv_update_len);
    1958                 :            :                 }
    1959                 :            : 
    1960                 :            :                 /** write iv */
    1961                 :          0 :                 rte_memcpy(iv, data->iv_aad_data,
    1962   [ #  #  #  #  :          0 :                                 data->cipher_auth.cipher_iv_len);
          #  #  #  #  #  
                #  #  # ]
    1963                 :            :         }
    1964                 :            : 
    1965   [ #  #  #  #  :          0 :         if (data->op_mask & CRYPTO_OP_MASK_AUTH) {
          #  #  #  #  #  
                #  #  # ]
    1966                 :            :                 /** authentication always start from IP header. */
    1967                 :          0 :                 sym->auth.data.offset = ip_offset - pkt_offset;
    1968                 :          0 :                 sym->auth.data.length = mbuf->data_len - sym->auth.data.offset -
    1969                 :          0 :                                 data->digest_len;
    1970                 :          0 :                 sym->auth.digest.data = rte_pktmbuf_mtod_offset(mbuf,
    1971                 :            :                                 uint8_t *, rte_pktmbuf_pkt_len(mbuf) -
    1972                 :            :                                 data->digest_len);
    1973                 :          0 :                 sym->auth.digest.phys_addr = rte_pktmbuf_iova_offset(mbuf,
    1974                 :            :                                 rte_pktmbuf_pkt_len(mbuf) - data->digest_len);
    1975                 :            : 
    1976   [ #  #  #  #  :          0 :                 if (data->cipher_auth.auth_iv_update_len) {
          #  #  #  #  #  
                #  #  # ]
    1977                 :          0 :                         uint8_t *pkt_iv = RTE_MBUF_METADATA_UINT8_PTR(mbuf,
    1978                 :            :                                         data->cipher_auth.auth_iv_data_offset
    1979                 :            :                                         + ip_offset);
    1980                 :          0 :                         uint8_t *data_iv = data->iv_aad_data +
    1981                 :          0 :                                         data->cipher_auth.cipher_iv_len;
    1982                 :            : 
    1983   [ #  #  #  #  :          0 :                         if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
          #  #  #  #  #  
                #  #  # ]
    1984   [ #  #  #  #  :          0 :                                 rte_memcpy(pkt_iv, data_iv,
          #  #  #  #  #  
                #  #  # ]
    1985                 :            :                                         data->cipher_auth.auth_iv_update_len);
    1986                 :            :                         else
    1987   [ #  #  #  #  :          0 :                                 rte_memcpy(data_iv, pkt_iv,
          #  #  #  #  #  
                #  #  # ]
    1988                 :            :                                         data->cipher_auth.auth_iv_update_len);
    1989                 :            :                 }
    1990                 :            : 
    1991   [ #  #  #  #  :          0 :                 if (data->cipher_auth.auth_iv_len) {
          #  #  #  #  #  
                #  #  # ]
    1992                 :            :                         /** prepare cipher op */
    1993                 :          0 :                         uint8_t *iv = crypto_op->iv_aad.cipher_auth.auth_iv;
    1994                 :            : 
    1995                 :          0 :                         rte_memcpy(iv, data->iv_aad_data +
    1996   [ #  #  #  #  :          0 :                                         data->cipher_auth.cipher_iv_len,
          #  #  #  #  #  
                #  #  # ]
    1997                 :            :                                         data->cipher_auth.auth_iv_len);
    1998                 :            :                 }
    1999                 :            :         }
    2000                 :            : 
    2001   [ #  #  #  #  :          0 :         if (data->op_mask & CRYPTO_OP_MASK_AEAD) {
          #  #  #  #  #  
                #  #  # ]
    2002                 :          0 :                 uint8_t *iv = crypto_op->iv_aad.aead_iv_aad.iv;
    2003                 :          0 :                 uint8_t *aad = crypto_op->iv_aad.aead_iv_aad.aad;
    2004                 :            : 
    2005                 :          0 :                 sym->aead.aad.data = aad;
    2006                 :          0 :                 sym->aead.aad.phys_addr = rte_pktmbuf_iova_offset(mbuf,
    2007                 :            :                                 aad - rte_pktmbuf_mtod(mbuf, uint8_t *));
    2008                 :          0 :                 sym->aead.digest.data = rte_pktmbuf_mtod_offset(mbuf,
    2009                 :            :                                 uint8_t *, rte_pktmbuf_pkt_len(mbuf) -
    2010                 :            :                                 data->digest_len);
    2011                 :          0 :                 sym->aead.digest.phys_addr = rte_pktmbuf_iova_offset(mbuf,
    2012                 :            :                                 rte_pktmbuf_pkt_len(mbuf) - data->digest_len);
    2013                 :          0 :                 sym->aead.data.offset = data->data_offset - pkt_offset;
    2014                 :          0 :                 sym->aead.data.length = payload_len;
    2015                 :            : 
    2016   [ #  #  #  #  :          0 :                 if (data->aead.iv_update_len) {
          #  #  #  #  #  
                #  #  # ]
    2017                 :          0 :                         uint8_t *pkt_iv = RTE_MBUF_METADATA_UINT8_PTR(mbuf,
    2018                 :            :                                         data->aead.iv_data_offset + ip_offset);
    2019                 :          0 :                         uint8_t *data_iv = data->iv_aad_data;
    2020                 :            : 
    2021   [ #  #  #  #  :          0 :                         if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
          #  #  #  #  #  
                #  #  # ]
    2022   [ #  #  #  #  :          0 :                                 rte_memcpy(pkt_iv, data_iv,
          #  #  #  #  #  
                #  #  # ]
    2023                 :            :                                                 data->aead.iv_update_len);
    2024                 :            :                         else
    2025   [ #  #  #  #  :          0 :                                 rte_memcpy(data_iv, pkt_iv,
          #  #  #  #  #  
                #  #  # ]
    2026                 :            :                                         data->aead.iv_update_len);
    2027                 :            :                 }
    2028                 :            : 
    2029   [ #  #  #  #  :          0 :                 rte_memcpy(iv, data->iv_aad_data, data->aead.iv_len);
          #  #  #  #  #  
                #  #  # ]
    2030                 :            : 
    2031   [ #  #  #  #  :          0 :                 if (data->aead.aad_update_len) {
          #  #  #  #  #  
                #  #  # ]
    2032                 :          0 :                         uint8_t *pkt_aad = RTE_MBUF_METADATA_UINT8_PTR(mbuf,
    2033                 :            :                                         data->aead.aad_data_offset + ip_offset);
    2034                 :          0 :                         uint8_t *data_aad = data->iv_aad_data +
    2035                 :          0 :                                         data->aead.iv_len;
    2036                 :            : 
    2037   [ #  #  #  #  :          0 :                         if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
          #  #  #  #  #  
                #  #  # ]
    2038                 :          0 :                                 rte_memcpy(pkt_aad, data_aad,
    2039   [ #  #  #  #  :          0 :                                                 data->aead.iv_update_len);
          #  #  #  #  #  
                #  #  # ]
    2040                 :            :                         else
    2041                 :          0 :                                 rte_memcpy(data_aad, pkt_aad,
    2042   [ #  #  #  #  :          0 :                                         data->aead.iv_update_len);
          #  #  #  #  #  
                #  #  # ]
    2043                 :            :                 }
    2044                 :            : 
    2045                 :          0 :                 rte_memcpy(aad, data->iv_aad_data + data->aead.iv_len,
    2046   [ #  #  #  #  :          0 :                                         data->aead.aad_len);
          #  #  #  #  #  
                #  #  # ]
    2047                 :            :         }
    2048                 :            : 
    2049                 :            :         return 0;
    2050                 :            : }
    2051                 :            : 
    2052                 :            : /**
    2053                 :            :  * RTE_TABLE_ACTION_TAG
    2054                 :            :  */
    2055                 :            : struct __rte_packed_begin tag_data {
    2056                 :            :         uint32_t tag;
    2057                 :            : } __rte_packed_end;
    2058                 :            : 
    2059                 :            : static int
    2060                 :            : tag_apply(struct tag_data *data,
    2061                 :            :         struct rte_table_action_tag_params *p)
    2062                 :            : {
    2063                 :          0 :         data->tag = p->tag;
    2064                 :            :         return 0;
    2065                 :            : }
    2066                 :            : 
    2067                 :            : static __rte_always_inline void
    2068                 :            : pkt_work_tag(struct rte_mbuf *mbuf,
    2069                 :            :         struct tag_data *data)
    2070                 :            : {
    2071                 :          0 :         mbuf->hash.fdir.hi = data->tag;
    2072                 :          0 :         mbuf->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
    2073                 :          0 : }
    2074                 :            : 
    2075                 :            : static __rte_always_inline void
    2076                 :            : pkt4_work_tag(struct rte_mbuf *mbuf0,
    2077                 :            :         struct rte_mbuf *mbuf1,
    2078                 :            :         struct rte_mbuf *mbuf2,
    2079                 :            :         struct rte_mbuf *mbuf3,
    2080                 :            :         struct tag_data *data0,
    2081                 :            :         struct tag_data *data1,
    2082                 :            :         struct tag_data *data2,
    2083                 :            :         struct tag_data *data3)
    2084                 :            : {
    2085                 :          0 :         mbuf0->hash.fdir.hi = data0->tag;
    2086                 :          0 :         mbuf1->hash.fdir.hi = data1->tag;
    2087                 :          0 :         mbuf2->hash.fdir.hi = data2->tag;
    2088                 :          0 :         mbuf3->hash.fdir.hi = data3->tag;
    2089                 :            : 
    2090                 :          0 :         mbuf0->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
    2091                 :          0 :         mbuf1->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
    2092                 :          0 :         mbuf2->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
    2093                 :          0 :         mbuf3->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
    2094                 :          0 : }
    2095                 :            : 
    2096                 :            : /**
    2097                 :            :  * RTE_TABLE_ACTION_DECAP
    2098                 :            :  */
    2099                 :            : struct __rte_packed_begin decap_data {
    2100                 :            :         uint16_t n;
    2101                 :            : } __rte_packed_end;
    2102                 :            : 
    2103                 :            : static int
    2104                 :            : decap_apply(struct decap_data *data,
    2105                 :            :         struct rte_table_action_decap_params *p)
    2106                 :            : {
    2107                 :          0 :         data->n = p->n;
    2108                 :            :         return 0;
    2109                 :            : }
    2110                 :            : 
    2111                 :            : static __rte_always_inline void
    2112                 :            : pkt_work_decap(struct rte_mbuf *mbuf,
    2113                 :            :         struct decap_data *data)
    2114                 :            : {
    2115                 :          0 :         uint16_t data_off = mbuf->data_off;
    2116                 :          0 :         uint16_t data_len = mbuf->data_len;
    2117                 :          0 :         uint32_t pkt_len = mbuf->pkt_len;
    2118                 :          0 :         uint16_t n = data->n;
    2119                 :            : 
    2120                 :          0 :         mbuf->data_off = data_off + n;
    2121                 :          0 :         mbuf->data_len = data_len - n;
    2122                 :          0 :         mbuf->pkt_len = pkt_len - n;
    2123                 :          0 : }
    2124                 :            : 
    2125                 :            : static __rte_always_inline void
    2126                 :            : pkt4_work_decap(struct rte_mbuf *mbuf0,
    2127                 :            :         struct rte_mbuf *mbuf1,
    2128                 :            :         struct rte_mbuf *mbuf2,
    2129                 :            :         struct rte_mbuf *mbuf3,
    2130                 :            :         struct decap_data *data0,
    2131                 :            :         struct decap_data *data1,
    2132                 :            :         struct decap_data *data2,
    2133                 :            :         struct decap_data *data3)
    2134                 :            : {
    2135                 :          0 :         uint16_t data_off0 = mbuf0->data_off;
    2136                 :          0 :         uint16_t data_len0 = mbuf0->data_len;
    2137                 :          0 :         uint32_t pkt_len0 = mbuf0->pkt_len;
    2138                 :            : 
    2139                 :          0 :         uint16_t data_off1 = mbuf1->data_off;
    2140                 :          0 :         uint16_t data_len1 = mbuf1->data_len;
    2141                 :          0 :         uint32_t pkt_len1 = mbuf1->pkt_len;
    2142                 :            : 
    2143                 :          0 :         uint16_t data_off2 = mbuf2->data_off;
    2144                 :          0 :         uint16_t data_len2 = mbuf2->data_len;
    2145                 :          0 :         uint32_t pkt_len2 = mbuf2->pkt_len;
    2146                 :            : 
    2147                 :          0 :         uint16_t data_off3 = mbuf3->data_off;
    2148                 :          0 :         uint16_t data_len3 = mbuf3->data_len;
    2149                 :          0 :         uint32_t pkt_len3 = mbuf3->pkt_len;
    2150                 :            : 
    2151                 :          0 :         uint16_t n0 = data0->n;
    2152                 :          0 :         uint16_t n1 = data1->n;
    2153                 :          0 :         uint16_t n2 = data2->n;
    2154                 :          0 :         uint16_t n3 = data3->n;
    2155                 :            : 
    2156                 :          0 :         mbuf0->data_off = data_off0 + n0;
    2157                 :          0 :         mbuf0->data_len = data_len0 - n0;
    2158                 :          0 :         mbuf0->pkt_len = pkt_len0 - n0;
    2159                 :            : 
    2160                 :          0 :         mbuf1->data_off = data_off1 + n1;
    2161                 :          0 :         mbuf1->data_len = data_len1 - n1;
    2162                 :          0 :         mbuf1->pkt_len = pkt_len1 - n1;
    2163                 :            : 
    2164                 :          0 :         mbuf2->data_off = data_off2 + n2;
    2165                 :          0 :         mbuf2->data_len = data_len2 - n2;
    2166                 :          0 :         mbuf2->pkt_len = pkt_len2 - n2;
    2167                 :            : 
    2168                 :          0 :         mbuf3->data_off = data_off3 + n3;
    2169                 :          0 :         mbuf3->data_len = data_len3 - n3;
    2170                 :          0 :         mbuf3->pkt_len = pkt_len3 - n3;
    2171                 :          0 : }
    2172                 :            : 
    2173                 :            : /**
    2174                 :            :  * Action profile
    2175                 :            :  */
    2176                 :            : static int
    2177                 :            : action_valid(enum rte_table_action_type action)
    2178                 :            : {
    2179   [ #  #  #  # ]:          0 :         switch (action) {
    2180                 :            :         case RTE_TABLE_ACTION_FWD:
    2181                 :            :         case RTE_TABLE_ACTION_LB:
    2182                 :            :         case RTE_TABLE_ACTION_MTR:
    2183                 :            :         case RTE_TABLE_ACTION_TM:
    2184                 :            :         case RTE_TABLE_ACTION_ENCAP:
    2185                 :            :         case RTE_TABLE_ACTION_NAT:
    2186                 :            :         case RTE_TABLE_ACTION_TTL:
    2187                 :            :         case RTE_TABLE_ACTION_STATS:
    2188                 :            :         case RTE_TABLE_ACTION_TIME:
    2189                 :            :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2190                 :            :         case RTE_TABLE_ACTION_TAG:
    2191                 :            :         case RTE_TABLE_ACTION_DECAP:
    2192                 :            :                 return 1;
    2193                 :            :         default:
    2194                 :            :                 return 0;
    2195                 :            :         }
    2196                 :            : }
    2197                 :            : 
    2198                 :            : 
    2199                 :            : #define RTE_TABLE_ACTION_MAX                      64
    2200                 :            : 
    2201                 :            : struct ap_config {
    2202                 :            :         uint64_t action_mask;
    2203                 :            :         struct rte_table_action_common_config common;
    2204                 :            :         struct rte_table_action_lb_config lb;
    2205                 :            :         struct rte_table_action_mtr_config mtr;
    2206                 :            :         struct rte_table_action_tm_config tm;
    2207                 :            :         struct rte_table_action_encap_config encap;
    2208                 :            :         struct rte_table_action_nat_config nat;
    2209                 :            :         struct rte_table_action_ttl_config ttl;
    2210                 :            :         struct rte_table_action_stats_config stats;
    2211                 :            :         struct rte_table_action_sym_crypto_config sym_crypto;
    2212                 :            : };
    2213                 :            : 
    2214                 :            : static size_t
    2215                 :            : action_cfg_size(enum rte_table_action_type action)
    2216                 :            : {
    2217                 :            :         switch (action) {
    2218                 :            :         case RTE_TABLE_ACTION_LB:
    2219                 :            :                 return sizeof(struct rte_table_action_lb_config);
    2220                 :            :         case RTE_TABLE_ACTION_MTR:
    2221                 :            :                 return sizeof(struct rte_table_action_mtr_config);
    2222                 :            :         case RTE_TABLE_ACTION_TM:
    2223                 :            :                 return sizeof(struct rte_table_action_tm_config);
    2224                 :            :         case RTE_TABLE_ACTION_ENCAP:
    2225                 :            :                 return sizeof(struct rte_table_action_encap_config);
    2226                 :            :         case RTE_TABLE_ACTION_NAT:
    2227                 :            :                 return sizeof(struct rte_table_action_nat_config);
    2228                 :            :         case RTE_TABLE_ACTION_TTL:
    2229                 :            :                 return sizeof(struct rte_table_action_ttl_config);
    2230                 :            :         case RTE_TABLE_ACTION_STATS:
    2231                 :            :                 return sizeof(struct rte_table_action_stats_config);
    2232                 :            :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2233                 :            :                 return sizeof(struct rte_table_action_sym_crypto_config);
    2234                 :            :         default:
    2235                 :            :                 return 0;
    2236                 :            :         }
    2237                 :            : }
    2238                 :            : 
    2239                 :            : static void*
    2240                 :            : action_cfg_get(struct ap_config *ap_config,
    2241                 :            :         enum rte_table_action_type type)
    2242                 :            : {
    2243                 :          0 :         switch (type) {
    2244                 :          0 :         case RTE_TABLE_ACTION_LB:
    2245                 :          0 :                 return &ap_config->lb;
    2246                 :            : 
    2247                 :          0 :         case RTE_TABLE_ACTION_MTR:
    2248                 :          0 :                 return &ap_config->mtr;
    2249                 :            : 
    2250                 :          0 :         case RTE_TABLE_ACTION_TM:
    2251                 :          0 :                 return &ap_config->tm;
    2252                 :            : 
    2253                 :          0 :         case RTE_TABLE_ACTION_ENCAP:
    2254                 :          0 :                 return &ap_config->encap;
    2255                 :            : 
    2256                 :          0 :         case RTE_TABLE_ACTION_NAT:
    2257                 :          0 :                 return &ap_config->nat;
    2258                 :            : 
    2259                 :          0 :         case RTE_TABLE_ACTION_TTL:
    2260                 :          0 :                 return &ap_config->ttl;
    2261                 :            : 
    2262                 :          0 :         case RTE_TABLE_ACTION_STATS:
    2263                 :          0 :                 return &ap_config->stats;
    2264                 :            : 
    2265                 :          0 :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2266                 :          0 :                 return &ap_config->sym_crypto;
    2267                 :            :         default:
    2268                 :            :                 return NULL;
    2269                 :            :         }
    2270                 :            : }
    2271                 :            : 
    2272                 :            : static void
    2273   [ #  #  #  #  :          0 : action_cfg_set(struct ap_config *ap_config,
             #  #  #  #  
                      # ]
    2274                 :            :         enum rte_table_action_type type,
    2275                 :            :         void *action_cfg)
    2276                 :            : {
    2277                 :            :         void *dst = action_cfg_get(ap_config, type);
    2278                 :            : 
    2279                 :            :         if (dst)
    2280                 :            :                 memcpy(dst, action_cfg, action_cfg_size(type));
    2281                 :            : 
    2282                 :          0 :         ap_config->action_mask |= 1LLU << type;
    2283                 :          0 : }
    2284                 :            : 
    2285                 :            : struct ap_data {
    2286                 :            :         size_t offset[RTE_TABLE_ACTION_MAX];
    2287                 :            :         size_t total_size;
    2288                 :            : };
    2289                 :            : 
    2290                 :            : static size_t
    2291                 :          0 : action_data_size(enum rte_table_action_type action,
    2292                 :            :         struct ap_config *ap_config)
    2293                 :            : {
    2294   [ #  #  #  #  :          0 :         switch (action) {
          #  #  #  #  #  
                   #  # ]
    2295                 :            :         case RTE_TABLE_ACTION_FWD:
    2296                 :            :                 return sizeof(struct fwd_data);
    2297                 :            : 
    2298                 :          0 :         case RTE_TABLE_ACTION_LB:
    2299                 :          0 :                 return sizeof(struct lb_data);
    2300                 :            : 
    2301                 :          0 :         case RTE_TABLE_ACTION_MTR:
    2302                 :          0 :                 return mtr_data_size(&ap_config->mtr);
    2303                 :            : 
    2304                 :            :         case RTE_TABLE_ACTION_TM:
    2305                 :            :                 return sizeof(struct tm_data);
    2306                 :            : 
    2307                 :          0 :         case RTE_TABLE_ACTION_ENCAP:
    2308                 :          0 :                 return encap_data_size(&ap_config->encap);
    2309                 :            : 
    2310         [ #  # ]:          0 :         case RTE_TABLE_ACTION_NAT:
    2311                 :            :                 return nat_data_size(&ap_config->nat,
    2312                 :            :                         &ap_config->common);
    2313                 :            : 
    2314                 :          0 :         case RTE_TABLE_ACTION_TTL:
    2315                 :          0 :                 return sizeof(struct ttl_data);
    2316                 :            : 
    2317                 :          0 :         case RTE_TABLE_ACTION_STATS:
    2318                 :          0 :                 return sizeof(struct stats_data);
    2319                 :            : 
    2320                 :            :         case RTE_TABLE_ACTION_TIME:
    2321                 :            :                 return sizeof(struct time_data);
    2322                 :            : 
    2323                 :          0 :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2324                 :          0 :                 return (sizeof(struct sym_crypto_data));
    2325                 :            : 
    2326                 :          0 :         case RTE_TABLE_ACTION_TAG:
    2327                 :          0 :                 return sizeof(struct tag_data);
    2328                 :            : 
    2329                 :          0 :         case RTE_TABLE_ACTION_DECAP:
    2330                 :          0 :                 return sizeof(struct decap_data);
    2331                 :            : 
    2332                 :          0 :         default:
    2333                 :          0 :                 return 0;
    2334                 :            :         }
    2335                 :            : }
    2336                 :            : 
    2337                 :            : 
    2338                 :            : static void
    2339                 :          0 : action_data_offset_set(struct ap_data *ap_data,
    2340                 :            :         struct ap_config *ap_config)
    2341                 :            : {
    2342                 :          0 :         uint64_t action_mask = ap_config->action_mask;
    2343                 :            :         size_t offset;
    2344                 :            :         uint32_t action;
    2345                 :            : 
    2346                 :          0 :         memset(ap_data->offset, 0, sizeof(ap_data->offset));
    2347                 :            : 
    2348                 :            :         offset = 0;
    2349         [ #  # ]:          0 :         for (action = 0; action < RTE_TABLE_ACTION_MAX; action++)
    2350         [ #  # ]:          0 :                 if (action_mask & (1LLU << action)) {
    2351                 :          0 :                         ap_data->offset[action] = offset;
    2352                 :          0 :                         offset += action_data_size((enum rte_table_action_type)action,
    2353                 :            :                                 ap_config);
    2354                 :            :                 }
    2355                 :            : 
    2356                 :          0 :         ap_data->total_size = offset;
    2357                 :          0 : }
    2358                 :            : 
    2359                 :            : struct rte_table_action_profile {
    2360                 :            :         struct ap_config cfg;
    2361                 :            :         struct ap_data data;
    2362                 :            :         int frozen;
    2363                 :            : };
    2364                 :            : 
    2365                 :            : struct rte_table_action_profile *
    2366                 :          0 : rte_table_action_profile_create(struct rte_table_action_common_config *common)
    2367                 :            : {
    2368                 :            :         struct rte_table_action_profile *ap;
    2369                 :            : 
    2370                 :            :         /* Check input arguments */
    2371         [ #  # ]:          0 :         if (common == NULL)
    2372                 :            :                 return NULL;
    2373                 :            : 
    2374                 :            :         /* Memory allocation */
    2375                 :          0 :         ap = calloc(1, sizeof(struct rte_table_action_profile));
    2376         [ #  # ]:          0 :         if (ap == NULL)
    2377                 :            :                 return NULL;
    2378                 :            : 
    2379                 :            :         /* Initialization */
    2380                 :          0 :         memcpy(&ap->cfg.common, common, sizeof(*common));
    2381                 :            : 
    2382                 :          0 :         return ap;
    2383                 :            : }
    2384                 :            : 
    2385                 :            : 
    2386                 :            : int
    2387                 :          0 : rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
    2388                 :            :         enum rte_table_action_type type,
    2389                 :            :         void *action_config)
    2390                 :            : {
    2391                 :            :         int status;
    2392                 :            : 
    2393                 :            :         /* Check input arguments */
    2394         [ #  # ]:          0 :         if ((profile == NULL) ||
    2395         [ #  # ]:          0 :                 profile->frozen ||
    2396                 :          0 :                 (action_valid(type) == 0) ||
    2397   [ #  #  #  # ]:          0 :                 (profile->cfg.action_mask & (1LLU << type)) ||
    2398   [ #  #  #  # ]:          0 :                 ((action_cfg_size(type) == 0) && action_config) ||
    2399         [ #  # ]:          0 :                 (action_cfg_size(type) && (action_config == NULL)))
    2400                 :            :                 return -EINVAL;
    2401                 :            : 
    2402   [ #  #  #  #  :          0 :         switch (type) {
             #  #  #  #  
                      # ]
    2403                 :            :         case RTE_TABLE_ACTION_LB:
    2404                 :            :                 status = lb_cfg_check(action_config);
    2405                 :            :                 break;
    2406                 :            : 
    2407                 :            :         case RTE_TABLE_ACTION_MTR:
    2408                 :            :                 status = mtr_cfg_check(action_config);
    2409                 :            :                 break;
    2410                 :            : 
    2411                 :            :         case RTE_TABLE_ACTION_TM:
    2412                 :            :                 status = tm_cfg_check(action_config);
    2413                 :            :                 break;
    2414                 :            : 
    2415                 :            :         case RTE_TABLE_ACTION_ENCAP:
    2416                 :            :                 status = encap_cfg_check(action_config);
    2417                 :            :                 break;
    2418                 :            : 
    2419                 :            :         case RTE_TABLE_ACTION_NAT:
    2420                 :            :                 status = nat_cfg_check(action_config);
    2421                 :            :                 break;
    2422                 :            : 
    2423                 :            :         case RTE_TABLE_ACTION_TTL:
    2424                 :            :                 status = ttl_cfg_check(action_config);
    2425                 :            :                 break;
    2426                 :            : 
    2427                 :            :         case RTE_TABLE_ACTION_STATS:
    2428                 :            :                 status = stats_cfg_check(action_config);
    2429                 :            :                 break;
    2430                 :            : 
    2431                 :          0 :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2432                 :          0 :                 status = sym_crypto_cfg_check(action_config);
    2433                 :            :                 break;
    2434                 :            : 
    2435                 :            :         default:
    2436                 :            :                 status = 0;
    2437                 :            :                 break;
    2438                 :            :         }
    2439                 :            : 
    2440         [ #  # ]:          0 :         if (status)
    2441                 :          0 :                 return status;
    2442                 :            : 
    2443                 :            :         /* Action enable */
    2444                 :          0 :         action_cfg_set(&profile->cfg, type, action_config);
    2445                 :            : 
    2446                 :          0 :         return 0;
    2447                 :            : }
    2448                 :            : 
    2449                 :            : int
    2450                 :          0 : rte_table_action_profile_freeze(struct rte_table_action_profile *profile)
    2451                 :            : {
    2452         [ #  # ]:          0 :         if (profile->frozen)
    2453                 :            :                 return -EBUSY;
    2454                 :            : 
    2455                 :          0 :         profile->cfg.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
    2456                 :          0 :         action_data_offset_set(&profile->data, &profile->cfg);
    2457                 :          0 :         profile->frozen = 1;
    2458                 :            : 
    2459                 :          0 :         return 0;
    2460                 :            : }
    2461                 :            : 
    2462                 :            : int
    2463                 :          0 : rte_table_action_profile_free(struct rte_table_action_profile *profile)
    2464                 :            : {
    2465         [ #  # ]:          0 :         if (profile == NULL)
    2466                 :            :                 return 0;
    2467                 :            : 
    2468                 :          0 :         free(profile);
    2469                 :          0 :         return 0;
    2470                 :            : }
    2471                 :            : 
    2472                 :            : /**
    2473                 :            :  * Action
    2474                 :            :  */
    2475                 :            : #define METER_PROFILES_MAX                                 32
    2476                 :            : 
    2477                 :            : struct rte_table_action {
    2478                 :            :         struct ap_config cfg;
    2479                 :            :         struct ap_data data;
    2480                 :            :         struct dscp_table_data dscp_table;
    2481                 :            :         struct meter_profile_data mp[METER_PROFILES_MAX];
    2482                 :            : };
    2483                 :            : 
    2484                 :            : struct rte_table_action *
    2485                 :          0 : rte_table_action_create(struct rte_table_action_profile *profile,
    2486                 :            :         uint32_t socket_id)
    2487                 :            : {
    2488                 :            :         struct rte_table_action *action;
    2489                 :            : 
    2490                 :            :         /* Check input arguments */
    2491         [ #  # ]:          0 :         if ((profile == NULL) ||
    2492         [ #  # ]:          0 :                 (profile->frozen == 0))
    2493                 :            :                 return NULL;
    2494                 :            : 
    2495                 :            :         /* Memory allocation */
    2496                 :          0 :         action = rte_zmalloc_socket(NULL,
    2497                 :            :                 sizeof(struct rte_table_action),
    2498                 :            :                 RTE_CACHE_LINE_SIZE,
    2499                 :            :                 socket_id);
    2500         [ #  # ]:          0 :         if (action == NULL)
    2501                 :            :                 return NULL;
    2502                 :            : 
    2503                 :            :         /* Initialization */
    2504                 :          0 :         memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
    2505                 :          0 :         memcpy(&action->data, &profile->data, sizeof(profile->data));
    2506                 :            : 
    2507                 :          0 :         return action;
    2508                 :            : }
    2509                 :            : 
    2510                 :            : static __rte_always_inline void *
    2511                 :            : action_data_get(void *data,
    2512                 :            :         struct rte_table_action *action,
    2513                 :            :         enum rte_table_action_type type)
    2514                 :            : {
    2515                 :          0 :         size_t offset = action->data.offset[type];
    2516                 :            :         uint8_t *data_bytes = data;
    2517                 :            : 
    2518                 :          0 :         return &data_bytes[offset];
    2519                 :            : }
    2520                 :            : 
    2521                 :            : int
    2522                 :          0 : rte_table_action_apply(struct rte_table_action *action,
    2523                 :            :         void *data,
    2524                 :            :         enum rte_table_action_type type,
    2525                 :            :         void *action_params)
    2526                 :            : {
    2527                 :            :         void *action_data;
    2528                 :            : 
    2529                 :            :         /* Check input arguments */
    2530                 :          0 :         if ((action == NULL) ||
    2531         [ #  # ]:          0 :                 (data == NULL) ||
    2532                 :          0 :                 (action_valid(type) == 0) ||
    2533   [ #  #  #  # ]:          0 :                 ((action->cfg.action_mask & (1LLU << type)) == 0) ||
    2534                 :            :                 (action_params == NULL))
    2535                 :            :                 return -EINVAL;
    2536                 :            : 
    2537                 :            :         /* Data update */
    2538                 :            :         action_data = action_data_get(data, action, type);
    2539                 :            : 
    2540   [ #  #  #  #  :          0 :         switch (type) {
          #  #  #  #  #  
                #  #  # ]
    2541                 :            :         case RTE_TABLE_ACTION_FWD:
    2542                 :            :                 return fwd_apply(action_data,
    2543                 :            :                         action_params);
    2544                 :            : 
    2545                 :            :         case RTE_TABLE_ACTION_LB:
    2546                 :          0 :                 return lb_apply(action_data,
    2547                 :            :                         action_params);
    2548                 :            : 
    2549                 :          0 :         case RTE_TABLE_ACTION_MTR:
    2550                 :          0 :                 return mtr_apply(action_data,
    2551                 :            :                         action_params,
    2552                 :            :                         &action->cfg.mtr,
    2553                 :          0 :                         action->mp,
    2554                 :            :                         RTE_DIM(action->mp));
    2555                 :            : 
    2556         [ #  # ]:          0 :         case RTE_TABLE_ACTION_TM:
    2557                 :            :                 return tm_apply(action_data,
    2558                 :            :                         action_params,
    2559                 :            :                         &action->cfg.tm);
    2560                 :            : 
    2561                 :          0 :         case RTE_TABLE_ACTION_ENCAP:
    2562                 :          0 :                 return encap_apply(action_data,
    2563                 :            :                         action_params,
    2564                 :            :                         &action->cfg.encap,
    2565                 :            :                         &action->cfg.common);
    2566                 :            : 
    2567                 :          0 :         case RTE_TABLE_ACTION_NAT:
    2568                 :          0 :                 return nat_apply(action_data,
    2569                 :            :                         action_params,
    2570                 :            :                         &action->cfg.common);
    2571                 :            : 
    2572                 :            :         case RTE_TABLE_ACTION_TTL:
    2573                 :          0 :                 return ttl_apply(action_data,
    2574                 :            :                         action_params);
    2575                 :            : 
    2576                 :            :         case RTE_TABLE_ACTION_STATS:
    2577                 :          0 :                 return stats_apply(action_data,
    2578                 :            :                         action_params);
    2579                 :            : 
    2580                 :            :         case RTE_TABLE_ACTION_TIME:
    2581                 :          0 :                 return time_apply(action_data,
    2582                 :            :                         action_params);
    2583                 :            : 
    2584                 :          0 :         case RTE_TABLE_ACTION_SYM_CRYPTO:
    2585                 :          0 :                 return sym_crypto_apply(action_data,
    2586                 :            :                                 &action->cfg.sym_crypto,
    2587                 :            :                                 action_params);
    2588                 :            : 
    2589                 :            :         case RTE_TABLE_ACTION_TAG:
    2590                 :          0 :                 return tag_apply(action_data,
    2591                 :            :                         action_params);
    2592                 :            : 
    2593                 :            :         case RTE_TABLE_ACTION_DECAP:
    2594                 :          0 :                 return decap_apply(action_data,
    2595                 :            :                         action_params);
    2596                 :            : 
    2597                 :            :         default:
    2598                 :            :                 return -EINVAL;
    2599                 :            :         }
    2600                 :            : }
    2601                 :            : 
    2602                 :            : int
    2603                 :          0 : rte_table_action_dscp_table_update(struct rte_table_action *action,
    2604                 :            :         uint64_t dscp_mask,
    2605                 :            :         struct rte_table_action_dscp_table *table)
    2606                 :            : {
    2607                 :            :         uint32_t i;
    2608                 :            : 
    2609                 :            :         /* Check input arguments */
    2610         [ #  # ]:          0 :         if ((action == NULL) ||
    2611         [ #  # ]:          0 :                 ((action->cfg.action_mask & ((1LLU << RTE_TABLE_ACTION_MTR) |
    2612                 :            :                 (1LLU << RTE_TABLE_ACTION_TM))) == 0) ||
    2613                 :          0 :                 (dscp_mask == 0) ||
    2614         [ #  # ]:          0 :                 (table == NULL))
    2615                 :            :                 return -EINVAL;
    2616                 :            : 
    2617         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(table->entry); i++) {
    2618                 :            :                 struct dscp_table_entry_data *data =
    2619                 :            :                         &action->dscp_table.entry[i];
    2620                 :            :                 struct rte_table_action_dscp_table_entry *entry =
    2621                 :            :                         &table->entry[i];
    2622                 :            : 
    2623         [ #  # ]:          0 :                 if ((dscp_mask & (1LLU << i)) == 0)
    2624                 :          0 :                         continue;
    2625                 :            : 
    2626                 :          0 :                 data->color = entry->color;
    2627                 :          0 :                 data->tc = entry->tc_id;
    2628                 :          0 :                 data->tc_queue = entry->tc_queue_id;
    2629                 :            :         }
    2630                 :            : 
    2631                 :            :         return 0;
    2632                 :            : }
    2633                 :            : 
    2634                 :            : int
    2635                 :          0 : rte_table_action_meter_profile_add(struct rte_table_action *action,
    2636                 :            :         uint32_t meter_profile_id,
    2637                 :            :         struct rte_table_action_meter_profile *profile)
    2638                 :            : {
    2639                 :            :         struct meter_profile_data *mp_data;
    2640                 :            :         uint32_t status;
    2641                 :            : 
    2642                 :            :         /* Check input arguments */
    2643         [ #  # ]:          0 :         if ((action == NULL) ||
    2644   [ #  #  #  # ]:          0 :                 ((action->cfg.action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0) ||
    2645                 :            :                 (profile == NULL))
    2646                 :            :                 return -EINVAL;
    2647                 :            : 
    2648         [ #  # ]:          0 :         if (profile->alg != RTE_TABLE_ACTION_METER_TRTCM)
    2649                 :            :                 return -ENOTSUP;
    2650                 :            : 
    2651                 :          0 :         mp_data = meter_profile_data_find(action->mp,
    2652                 :            :                 RTE_DIM(action->mp),
    2653                 :            :                 meter_profile_id);
    2654         [ #  # ]:          0 :         if (mp_data)
    2655                 :            :                 return -EEXIST;
    2656                 :            : 
    2657                 :            :         mp_data = meter_profile_data_find_unused(action->mp,
    2658                 :            :                 RTE_DIM(action->mp));
    2659         [ #  # ]:          0 :         if (!mp_data)
    2660                 :            :                 return -ENOSPC;
    2661                 :            : 
    2662                 :            :         /* Install new profile */
    2663                 :          0 :         status = rte_meter_trtcm_profile_config(&mp_data->profile,
    2664                 :            :                 &profile->trtcm);
    2665         [ #  # ]:          0 :         if (status)
    2666                 :            :                 return status;
    2667                 :            : 
    2668                 :          0 :         mp_data->profile_id = meter_profile_id;
    2669                 :          0 :         mp_data->valid = 1;
    2670                 :            : 
    2671                 :          0 :         return 0;
    2672                 :            : }
    2673                 :            : 
    2674                 :            : int
    2675                 :          0 : rte_table_action_meter_profile_delete(struct rte_table_action *action,
    2676                 :            :         uint32_t meter_profile_id)
    2677                 :            : {
    2678                 :            :         struct meter_profile_data *mp_data;
    2679                 :            : 
    2680                 :            :         /* Check input arguments */
    2681         [ #  # ]:          0 :         if ((action == NULL) ||
    2682         [ #  # ]:          0 :                 ((action->cfg.action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0))
    2683                 :            :                 return -EINVAL;
    2684                 :            : 
    2685                 :          0 :         mp_data = meter_profile_data_find(action->mp,
    2686                 :            :                 RTE_DIM(action->mp),
    2687                 :            :                 meter_profile_id);
    2688         [ #  # ]:          0 :         if (!mp_data)
    2689                 :            :                 return 0;
    2690                 :            : 
    2691                 :            :         /* Uninstall profile */
    2692                 :          0 :         mp_data->valid = 0;
    2693                 :            : 
    2694                 :          0 :         return 0;
    2695                 :            : }
    2696                 :            : 
    2697                 :            : int
    2698                 :          0 : rte_table_action_meter_read(struct rte_table_action *action,
    2699                 :            :         void *data,
    2700                 :            :         uint32_t tc_mask,
    2701                 :            :         struct rte_table_action_mtr_counters *stats,
    2702                 :            :         int clear)
    2703                 :            : {
    2704                 :            :         struct mtr_trtcm_data *mtr_data;
    2705                 :            :         uint32_t i;
    2706                 :            : 
    2707                 :            :         /* Check input arguments */
    2708         [ #  # ]:          0 :         if ((action == NULL) ||
    2709   [ #  #  #  # ]:          0 :                 ((action->cfg.action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0) ||
    2710                 :          0 :                 (data == NULL) ||
    2711         [ #  # ]:          0 :                 (tc_mask > RTE_LEN2MASK(action->cfg.mtr.n_tc, uint32_t)))
    2712                 :            :                 return -EINVAL;
    2713                 :            : 
    2714                 :            :         mtr_data = action_data_get(data, action, RTE_TABLE_ACTION_MTR);
    2715                 :            : 
    2716                 :            :         /* Read */
    2717         [ #  # ]:          0 :         if (stats) {
    2718         [ #  # ]:          0 :                 for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) {
    2719                 :            :                         struct rte_table_action_mtr_counters_tc *dst =
    2720                 :            :                                 &stats->stats[i];
    2721                 :          0 :                         struct mtr_trtcm_data *src = &mtr_data[i];
    2722                 :            : 
    2723         [ #  # ]:          0 :                         if ((tc_mask & (1 << i)) == 0)
    2724                 :          0 :                                 continue;
    2725                 :            : 
    2726                 :          0 :                         dst->n_packets[RTE_COLOR_GREEN] =
    2727                 :            :                                 mtr_trtcm_data_stats_get(src, RTE_COLOR_GREEN);
    2728                 :            : 
    2729                 :          0 :                         dst->n_packets[RTE_COLOR_YELLOW] =
    2730                 :            :                                 mtr_trtcm_data_stats_get(src, RTE_COLOR_YELLOW);
    2731                 :            : 
    2732                 :          0 :                         dst->n_packets[RTE_COLOR_RED] =
    2733                 :            :                                 mtr_trtcm_data_stats_get(src, RTE_COLOR_RED);
    2734                 :            : 
    2735                 :          0 :                         dst->n_packets_valid = 1;
    2736                 :          0 :                         dst->n_bytes_valid = 0;
    2737                 :            :                 }
    2738                 :            : 
    2739                 :          0 :                 stats->tc_mask = tc_mask;
    2740                 :            :         }
    2741                 :            : 
    2742                 :            :         /* Clear */
    2743         [ #  # ]:          0 :         if (clear)
    2744         [ #  # ]:          0 :                 for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++) {
    2745                 :          0 :                         struct mtr_trtcm_data *src = &mtr_data[i];
    2746                 :            : 
    2747         [ #  # ]:          0 :                         if ((tc_mask & (1 << i)) == 0)
    2748                 :          0 :                                 continue;
    2749                 :            : 
    2750                 :            :                         mtr_trtcm_data_stats_reset(src, RTE_COLOR_GREEN);
    2751                 :            :                         mtr_trtcm_data_stats_reset(src, RTE_COLOR_YELLOW);
    2752                 :            :                         mtr_trtcm_data_stats_reset(src, RTE_COLOR_RED);
    2753                 :            :                 }
    2754                 :            : 
    2755                 :            : 
    2756                 :            :         return 0;
    2757                 :            : }
    2758                 :            : 
    2759                 :            : int
    2760                 :          0 : rte_table_action_ttl_read(struct rte_table_action *action,
    2761                 :            :         void *data,
    2762                 :            :         struct rte_table_action_ttl_counters *stats,
    2763                 :            :         int clear)
    2764                 :            : {
    2765                 :            :         struct ttl_data *ttl_data;
    2766                 :            : 
    2767                 :            :         /* Check input arguments */
    2768         [ #  # ]:          0 :         if ((action == NULL) ||
    2769         [ #  # ]:          0 :                 ((action->cfg.action_mask &
    2770         [ #  # ]:          0 :                 (1LLU << RTE_TABLE_ACTION_TTL)) == 0) ||
    2771                 :            :                 (data == NULL))
    2772                 :            :                 return -EINVAL;
    2773                 :            : 
    2774                 :            :         ttl_data = action_data_get(data, action, RTE_TABLE_ACTION_TTL);
    2775                 :            : 
    2776                 :            :         /* Read */
    2777         [ #  # ]:          0 :         if (stats)
    2778                 :          0 :                 stats->n_packets = TTL_STATS_READ(ttl_data);
    2779                 :            : 
    2780                 :            :         /* Clear */
    2781         [ #  # ]:          0 :         if (clear)
    2782                 :          0 :                 TTL_STATS_RESET(ttl_data);
    2783                 :            : 
    2784                 :            :         return 0;
    2785                 :            : }
    2786                 :            : 
    2787                 :            : int
    2788                 :          0 : rte_table_action_stats_read(struct rte_table_action *action,
    2789                 :            :         void *data,
    2790                 :            :         struct rte_table_action_stats_counters *stats,
    2791                 :            :         int clear)
    2792                 :            : {
    2793                 :            :         struct stats_data *stats_data;
    2794                 :            : 
    2795                 :            :         /* Check input arguments */
    2796         [ #  # ]:          0 :         if ((action == NULL) ||
    2797         [ #  # ]:          0 :                 ((action->cfg.action_mask &
    2798         [ #  # ]:          0 :                 (1LLU << RTE_TABLE_ACTION_STATS)) == 0) ||
    2799                 :            :                 (data == NULL))
    2800                 :            :                 return -EINVAL;
    2801                 :            : 
    2802                 :            :         stats_data = action_data_get(data, action,
    2803                 :            :                 RTE_TABLE_ACTION_STATS);
    2804                 :            : 
    2805                 :            :         /* Read */
    2806         [ #  # ]:          0 :         if (stats) {
    2807                 :          0 :                 stats->n_packets = stats_data->n_packets;
    2808                 :          0 :                 stats->n_bytes = stats_data->n_bytes;
    2809                 :          0 :                 stats->n_packets_valid = 1;
    2810                 :          0 :                 stats->n_bytes_valid = 1;
    2811                 :            :         }
    2812                 :            : 
    2813                 :            :         /* Clear */
    2814         [ #  # ]:          0 :         if (clear) {
    2815                 :          0 :                 stats_data->n_packets = 0;
    2816                 :          0 :                 stats_data->n_bytes = 0;
    2817                 :            :         }
    2818                 :            : 
    2819                 :            :         return 0;
    2820                 :            : }
    2821                 :            : 
    2822                 :            : int
    2823                 :          0 : rte_table_action_time_read(struct rte_table_action *action,
    2824                 :            :         void *data,
    2825                 :            :         uint64_t *timestamp)
    2826                 :            : {
    2827                 :            :         struct time_data *time_data;
    2828                 :            : 
    2829                 :            :         /* Check input arguments */
    2830         [ #  # ]:          0 :         if ((action == NULL) ||
    2831         [ #  # ]:          0 :                 ((action->cfg.action_mask &
    2832                 :            :                 (1LLU << RTE_TABLE_ACTION_TIME)) == 0) ||
    2833                 :          0 :                 (data == NULL) ||
    2834         [ #  # ]:          0 :                 (timestamp == NULL))
    2835                 :            :                 return -EINVAL;
    2836                 :            : 
    2837                 :            :         time_data = action_data_get(data, action, RTE_TABLE_ACTION_TIME);
    2838                 :            : 
    2839                 :            :         /* Read */
    2840                 :          0 :         *timestamp = time_data->time;
    2841                 :            : 
    2842                 :          0 :         return 0;
    2843                 :            : }
    2844                 :            : 
    2845                 :            : struct rte_cryptodev_sym_session *
    2846                 :          0 : rte_table_action_crypto_sym_session_get(struct rte_table_action *action,
    2847                 :            :         void *data)
    2848                 :            : {
    2849                 :            :         struct sym_crypto_data *sym_crypto_data;
    2850                 :            : 
    2851                 :            :         /* Check input arguments */
    2852         [ #  # ]:          0 :         if ((action == NULL) ||
    2853         [ #  # ]:          0 :                 ((action->cfg.action_mask &
    2854         [ #  # ]:          0 :                 (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) == 0) ||
    2855                 :            :                 (data == NULL))
    2856                 :            :                 return NULL;
    2857                 :            : 
    2858                 :            :         sym_crypto_data = action_data_get(data, action,
    2859                 :            :                         RTE_TABLE_ACTION_SYM_CRYPTO);
    2860                 :            : 
    2861                 :          0 :         return sym_crypto_data->session;
    2862                 :            : }
    2863                 :            : 
    2864                 :            : static __rte_always_inline uint64_t
    2865                 :            : pkt_work(struct rte_mbuf *mbuf,
    2866                 :            :         struct rte_pipeline_table_entry *table_entry,
    2867                 :            :         uint64_t time,
    2868                 :            :         struct rte_table_action *action,
    2869                 :            :         struct ap_config *cfg)
    2870                 :            : {
    2871                 :            :         uint64_t drop_mask = 0;
    2872                 :            : 
    2873                 :          0 :         uint32_t ip_offset = action->cfg.common.ip_offset;
    2874                 :          0 :         void *ip = RTE_MBUF_METADATA_UINT32_PTR(mbuf, ip_offset);
    2875                 :            : 
    2876                 :            :         uint32_t dscp;
    2877                 :            :         uint16_t total_length;
    2878                 :            : 
    2879                 :          0 :         if (cfg->common.ip_version) {
    2880                 :            :                 struct rte_ipv4_hdr *hdr = ip;
    2881                 :            : 
    2882                 :          0 :                 dscp = hdr->type_of_service >> 2;
    2883   [ #  #  #  # ]:          0 :                 total_length = rte_ntohs(hdr->total_length);
    2884                 :            :         } else {
    2885                 :            :                 struct rte_ipv6_hdr *hdr = ip;
    2886                 :            : 
    2887   [ #  #  #  # ]:          0 :                 dscp = (rte_ntohl(hdr->vtc_flow) & 0x0F600000) >> 18;
    2888   [ #  #  #  # ]:          0 :                 total_length = rte_ntohs(hdr->payload_len) +
    2889                 :            :                         sizeof(struct rte_ipv6_hdr);
    2890                 :            :         }
    2891                 :            : 
    2892   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
    2893                 :            :                 void *data =
    2894                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_LB);
    2895                 :            : 
    2896                 :            :                 pkt_work_lb(mbuf,
    2897                 :            :                         data,
    2898                 :            :                         &cfg->lb);
    2899                 :            :         }
    2900   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
    2901                 :            :                 void *data =
    2902                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_MTR);
    2903                 :            : 
    2904                 :            :                 drop_mask |= pkt_work_mtr(mbuf,
    2905                 :            :                         data,
    2906                 :            :                         &action->dscp_table,
    2907                 :          0 :                         action->mp,
    2908                 :            :                         time,
    2909                 :            :                         dscp,
    2910                 :            :                         total_length);
    2911                 :            :         }
    2912                 :            : 
    2913   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
    2914                 :            :                 void *data =
    2915                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_TM);
    2916                 :            : 
    2917                 :            :                 pkt_work_tm(mbuf,
    2918                 :            :                         data,
    2919                 :            :                         &action->dscp_table,
    2920                 :            :                         dscp);
    2921                 :            :         }
    2922                 :            : 
    2923   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
    2924                 :            :                 void *data = action_data_get(table_entry,
    2925                 :            :                         action,
    2926                 :            :                         RTE_TABLE_ACTION_DECAP);
    2927                 :            : 
    2928                 :            :                 pkt_work_decap(mbuf, data);
    2929                 :            :         }
    2930                 :            : 
    2931   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
    2932                 :            :                 void *data =
    2933                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_ENCAP);
    2934                 :            : 
    2935   [ #  #  #  #  :          0 :                 pkt_work_encap(mbuf,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    2936                 :            :                         data,
    2937                 :            :                         &cfg->encap,
    2938                 :            :                         ip,
    2939                 :            :                         total_length,
    2940                 :            :                         ip_offset);
    2941                 :            :         }
    2942                 :            : 
    2943   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
    2944                 :            :                 void *data =
    2945                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_NAT);
    2946                 :            : 
    2947   [ #  #  #  # ]:          0 :                 if (cfg->common.ip_version)
    2948                 :            :                         pkt_ipv4_work_nat(ip, data, &cfg->nat);
    2949                 :            :                 else
    2950                 :            :                         pkt_ipv6_work_nat(ip, data, &cfg->nat);
    2951                 :            :         }
    2952                 :            : 
    2953   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
    2954                 :            :                 void *data =
    2955                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_TTL);
    2956                 :            : 
    2957   [ #  #  #  # ]:          0 :                 if (cfg->common.ip_version)
    2958                 :          0 :                         drop_mask |= pkt_ipv4_work_ttl(ip, data);
    2959                 :            :                 else
    2960                 :          0 :                         drop_mask |= pkt_ipv6_work_ttl(ip, data);
    2961                 :            :         }
    2962                 :            : 
    2963   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
    2964                 :            :                 void *data =
    2965                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_STATS);
    2966                 :            : 
    2967                 :            :                 pkt_work_stats(data, total_length);
    2968                 :            :         }
    2969                 :            : 
    2970   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
    2971                 :            :                 void *data =
    2972                 :            :                         action_data_get(table_entry, action, RTE_TABLE_ACTION_TIME);
    2973                 :            : 
    2974                 :            :                 pkt_work_time(data, time);
    2975                 :            :         }
    2976                 :            : 
    2977   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
    2978                 :            :                 void *data = action_data_get(table_entry, action,
    2979                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO);
    2980                 :            : 
    2981   [ #  #  #  # ]:          0 :                 drop_mask |= pkt_work_sym_crypto(mbuf, data, &cfg->sym_crypto,
    2982                 :            :                                 ip_offset);
    2983                 :            :         }
    2984                 :            : 
    2985   [ #  #  #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
    2986                 :            :                 void *data = action_data_get(table_entry,
    2987                 :            :                         action,
    2988                 :            :                         RTE_TABLE_ACTION_TAG);
    2989                 :            : 
    2990                 :            :                 pkt_work_tag(mbuf, data);
    2991                 :            :         }
    2992                 :            : 
    2993                 :            :         return drop_mask;
    2994                 :            : }
    2995                 :            : 
    2996                 :            : static __rte_always_inline uint64_t
    2997                 :            : pkt4_work(struct rte_mbuf **mbufs,
    2998                 :            :         struct rte_pipeline_table_entry **table_entries,
    2999                 :            :         uint64_t time,
    3000                 :            :         struct rte_table_action *action,
    3001                 :            :         struct ap_config *cfg)
    3002                 :            : {
    3003                 :            :         uint64_t drop_mask0 = 0;
    3004                 :            :         uint64_t drop_mask1 = 0;
    3005                 :            :         uint64_t drop_mask2 = 0;
    3006                 :            :         uint64_t drop_mask3 = 0;
    3007                 :            : 
    3008                 :          0 :         struct rte_mbuf *mbuf0 = mbufs[0];
    3009                 :          0 :         struct rte_mbuf *mbuf1 = mbufs[1];
    3010                 :          0 :         struct rte_mbuf *mbuf2 = mbufs[2];
    3011                 :          0 :         struct rte_mbuf *mbuf3 = mbufs[3];
    3012                 :            : 
    3013                 :          0 :         struct rte_pipeline_table_entry *table_entry0 = table_entries[0];
    3014                 :          0 :         struct rte_pipeline_table_entry *table_entry1 = table_entries[1];
    3015                 :          0 :         struct rte_pipeline_table_entry *table_entry2 = table_entries[2];
    3016                 :          0 :         struct rte_pipeline_table_entry *table_entry3 = table_entries[3];
    3017                 :            : 
    3018                 :          0 :         uint32_t ip_offset = action->cfg.common.ip_offset;
    3019                 :          0 :         void *ip0 = RTE_MBUF_METADATA_UINT32_PTR(mbuf0, ip_offset);
    3020                 :          0 :         void *ip1 = RTE_MBUF_METADATA_UINT32_PTR(mbuf1, ip_offset);
    3021                 :          0 :         void *ip2 = RTE_MBUF_METADATA_UINT32_PTR(mbuf2, ip_offset);
    3022                 :          0 :         void *ip3 = RTE_MBUF_METADATA_UINT32_PTR(mbuf3, ip_offset);
    3023                 :            : 
    3024                 :            :         uint32_t dscp0, dscp1, dscp2, dscp3;
    3025                 :            :         uint16_t total_length0, total_length1, total_length2, total_length3;
    3026                 :            : 
    3027                 :          0 :         if (cfg->common.ip_version) {
    3028                 :            :                 struct rte_ipv4_hdr *hdr0 = ip0;
    3029                 :            :                 struct rte_ipv4_hdr *hdr1 = ip1;
    3030                 :            :                 struct rte_ipv4_hdr *hdr2 = ip2;
    3031                 :            :                 struct rte_ipv4_hdr *hdr3 = ip3;
    3032                 :            : 
    3033                 :          0 :                 dscp0 = hdr0->type_of_service >> 2;
    3034                 :          0 :                 dscp1 = hdr1->type_of_service >> 2;
    3035                 :          0 :                 dscp2 = hdr2->type_of_service >> 2;
    3036                 :          0 :                 dscp3 = hdr3->type_of_service >> 2;
    3037                 :            : 
    3038         [ #  # ]:          0 :                 total_length0 = rte_ntohs(hdr0->total_length);
    3039         [ #  # ]:          0 :                 total_length1 = rte_ntohs(hdr1->total_length);
    3040         [ #  # ]:          0 :                 total_length2 = rte_ntohs(hdr2->total_length);
    3041         [ #  # ]:          0 :                 total_length3 = rte_ntohs(hdr3->total_length);
    3042                 :            :         } else {
    3043                 :            :                 struct rte_ipv6_hdr *hdr0 = ip0;
    3044                 :            :                 struct rte_ipv6_hdr *hdr1 = ip1;
    3045                 :            :                 struct rte_ipv6_hdr *hdr2 = ip2;
    3046                 :            :                 struct rte_ipv6_hdr *hdr3 = ip3;
    3047                 :            : 
    3048         [ #  # ]:          0 :                 dscp0 = (rte_ntohl(hdr0->vtc_flow) & 0x0F600000) >> 18;
    3049         [ #  # ]:          0 :                 dscp1 = (rte_ntohl(hdr1->vtc_flow) & 0x0F600000) >> 18;
    3050         [ #  # ]:          0 :                 dscp2 = (rte_ntohl(hdr2->vtc_flow) & 0x0F600000) >> 18;
    3051         [ #  # ]:          0 :                 dscp3 = (rte_ntohl(hdr3->vtc_flow) & 0x0F600000) >> 18;
    3052                 :            : 
    3053         [ #  # ]:          0 :                 total_length0 = rte_ntohs(hdr0->payload_len) +
    3054                 :            :                         sizeof(struct rte_ipv6_hdr);
    3055         [ #  # ]:          0 :                 total_length1 = rte_ntohs(hdr1->payload_len) +
    3056                 :            :                         sizeof(struct rte_ipv6_hdr);
    3057         [ #  # ]:          0 :                 total_length2 = rte_ntohs(hdr2->payload_len) +
    3058                 :            :                         sizeof(struct rte_ipv6_hdr);
    3059         [ #  # ]:          0 :                 total_length3 = rte_ntohs(hdr3->payload_len) +
    3060                 :            :                         sizeof(struct rte_ipv6_hdr);
    3061                 :            :         }
    3062                 :            : 
    3063         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
    3064                 :            :                 void *data0 =
    3065                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_LB);
    3066                 :            :                 void *data1 =
    3067                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_LB);
    3068                 :            :                 void *data2 =
    3069                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_LB);
    3070                 :            :                 void *data3 =
    3071                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_LB);
    3072                 :            : 
    3073                 :            :                 pkt_work_lb(mbuf0,
    3074                 :            :                         data0,
    3075                 :            :                         &cfg->lb);
    3076                 :            : 
    3077                 :            :                 pkt_work_lb(mbuf1,
    3078                 :            :                         data1,
    3079                 :            :                         &cfg->lb);
    3080                 :            : 
    3081                 :            :                 pkt_work_lb(mbuf2,
    3082                 :            :                         data2,
    3083                 :            :                         &cfg->lb);
    3084                 :            : 
    3085                 :            :                 pkt_work_lb(mbuf3,
    3086                 :            :                         data3,
    3087                 :            :                         &cfg->lb);
    3088                 :            :         }
    3089                 :            : 
    3090         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
    3091                 :            :                 void *data0 =
    3092                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_MTR);
    3093                 :            :                 void *data1 =
    3094                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_MTR);
    3095                 :            :                 void *data2 =
    3096                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_MTR);
    3097                 :            :                 void *data3 =
    3098                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_MTR);
    3099                 :            : 
    3100                 :            :                 drop_mask0 |= pkt_work_mtr(mbuf0,
    3101                 :            :                         data0,
    3102                 :            :                         &action->dscp_table,
    3103                 :          0 :                         action->mp,
    3104                 :            :                         time,
    3105                 :            :                         dscp0,
    3106                 :            :                         total_length0);
    3107                 :            : 
    3108                 :            :                 drop_mask1 |= pkt_work_mtr(mbuf1,
    3109                 :            :                         data1,
    3110                 :            :                         &action->dscp_table,
    3111                 :            :                         action->mp,
    3112                 :            :                         time,
    3113                 :            :                         dscp1,
    3114                 :            :                         total_length1);
    3115                 :            : 
    3116                 :            :                 drop_mask2 |= pkt_work_mtr(mbuf2,
    3117                 :            :                         data2,
    3118                 :            :                         &action->dscp_table,
    3119                 :            :                         action->mp,
    3120                 :            :                         time,
    3121                 :            :                         dscp2,
    3122                 :            :                         total_length2);
    3123                 :            : 
    3124                 :            :                 drop_mask3 |= pkt_work_mtr(mbuf3,
    3125                 :            :                         data3,
    3126                 :            :                         &action->dscp_table,
    3127                 :            :                         action->mp,
    3128                 :            :                         time,
    3129                 :            :                         dscp3,
    3130                 :            :                         total_length3);
    3131                 :            :         }
    3132                 :            : 
    3133         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
    3134                 :            :                 void *data0 =
    3135                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_TM);
    3136                 :            :                 void *data1 =
    3137                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_TM);
    3138                 :            :                 void *data2 =
    3139                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_TM);
    3140                 :            :                 void *data3 =
    3141                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_TM);
    3142                 :            : 
    3143                 :            :                 pkt_work_tm(mbuf0,
    3144                 :            :                         data0,
    3145                 :            :                         &action->dscp_table,
    3146                 :            :                         dscp0);
    3147                 :            : 
    3148                 :            :                 pkt_work_tm(mbuf1,
    3149                 :            :                         data1,
    3150                 :            :                         &action->dscp_table,
    3151                 :            :                         dscp1);
    3152                 :            : 
    3153                 :            :                 pkt_work_tm(mbuf2,
    3154                 :            :                         data2,
    3155                 :            :                         &action->dscp_table,
    3156                 :            :                         dscp2);
    3157                 :            : 
    3158                 :            :                 pkt_work_tm(mbuf3,
    3159                 :            :                         data3,
    3160                 :            :                         &action->dscp_table,
    3161                 :            :                         dscp3);
    3162                 :            :         }
    3163                 :            : 
    3164         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
    3165                 :            :                 void *data0 = action_data_get(table_entry0,
    3166                 :            :                         action,
    3167                 :            :                         RTE_TABLE_ACTION_DECAP);
    3168                 :            :                 void *data1 = action_data_get(table_entry1,
    3169                 :            :                         action,
    3170                 :            :                         RTE_TABLE_ACTION_DECAP);
    3171                 :            :                 void *data2 = action_data_get(table_entry2,
    3172                 :            :                         action,
    3173                 :            :                         RTE_TABLE_ACTION_DECAP);
    3174                 :            :                 void *data3 = action_data_get(table_entry3,
    3175                 :            :                         action,
    3176                 :            :                         RTE_TABLE_ACTION_DECAP);
    3177                 :            : 
    3178                 :            :                 pkt4_work_decap(mbuf0, mbuf1, mbuf2, mbuf3,
    3179                 :            :                         data0, data1, data2, data3);
    3180                 :            :         }
    3181                 :            : 
    3182         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
    3183                 :            :                 void *data0 =
    3184                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_ENCAP);
    3185                 :            :                 void *data1 =
    3186                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_ENCAP);
    3187                 :            :                 void *data2 =
    3188                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_ENCAP);
    3189                 :            :                 void *data3 =
    3190                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_ENCAP);
    3191                 :            : 
    3192   [ #  #  #  #  :          0 :                 pkt_work_encap(mbuf0,
             #  #  #  # ]
    3193                 :            :                         data0,
    3194                 :            :                         &cfg->encap,
    3195                 :            :                         ip0,
    3196                 :            :                         total_length0,
    3197                 :            :                         ip_offset);
    3198                 :            : 
    3199   [ #  #  #  #  :          0 :                 pkt_work_encap(mbuf1,
             #  #  #  # ]
    3200                 :            :                         data1,
    3201                 :            :                         &cfg->encap,
    3202                 :            :                         ip1,
    3203                 :            :                         total_length1,
    3204                 :            :                         ip_offset);
    3205                 :            : 
    3206   [ #  #  #  #  :          0 :                 pkt_work_encap(mbuf2,
             #  #  #  # ]
    3207                 :            :                         data2,
    3208                 :            :                         &cfg->encap,
    3209                 :            :                         ip2,
    3210                 :            :                         total_length2,
    3211                 :            :                         ip_offset);
    3212                 :            : 
    3213   [ #  #  #  #  :          0 :                 pkt_work_encap(mbuf3,
             #  #  #  # ]
    3214                 :            :                         data3,
    3215                 :            :                         &cfg->encap,
    3216                 :            :                         ip3,
    3217                 :            :                         total_length3,
    3218                 :            :                         ip_offset);
    3219                 :            :         }
    3220                 :            : 
    3221         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
    3222                 :            :                 void *data0 =
    3223                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_NAT);
    3224                 :            :                 void *data1 =
    3225                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_NAT);
    3226                 :            :                 void *data2 =
    3227                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_NAT);
    3228                 :            :                 void *data3 =
    3229                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_NAT);
    3230                 :            : 
    3231         [ #  # ]:          0 :                 if (cfg->common.ip_version) {
    3232                 :            :                         pkt_ipv4_work_nat(ip0, data0, &cfg->nat);
    3233                 :            :                         pkt_ipv4_work_nat(ip1, data1, &cfg->nat);
    3234                 :            :                         pkt_ipv4_work_nat(ip2, data2, &cfg->nat);
    3235                 :            :                         pkt_ipv4_work_nat(ip3, data3, &cfg->nat);
    3236                 :            :                 } else {
    3237                 :            :                         pkt_ipv6_work_nat(ip0, data0, &cfg->nat);
    3238                 :            :                         pkt_ipv6_work_nat(ip1, data1, &cfg->nat);
    3239                 :            :                         pkt_ipv6_work_nat(ip2, data2, &cfg->nat);
    3240                 :            :                         pkt_ipv6_work_nat(ip3, data3, &cfg->nat);
    3241                 :            :                 }
    3242                 :            :         }
    3243                 :            : 
    3244         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
    3245                 :            :                 void *data0 =
    3246                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_TTL);
    3247                 :            :                 void *data1 =
    3248                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_TTL);
    3249                 :            :                 void *data2 =
    3250                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_TTL);
    3251                 :            :                 void *data3 =
    3252                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_TTL);
    3253                 :            : 
    3254         [ #  # ]:          0 :                 if (cfg->common.ip_version) {
    3255                 :          0 :                         drop_mask0 |= pkt_ipv4_work_ttl(ip0, data0);
    3256                 :          0 :                         drop_mask1 |= pkt_ipv4_work_ttl(ip1, data1);
    3257                 :          0 :                         drop_mask2 |= pkt_ipv4_work_ttl(ip2, data2);
    3258                 :          0 :                         drop_mask3 |= pkt_ipv4_work_ttl(ip3, data3);
    3259                 :            :                 } else {
    3260                 :          0 :                         drop_mask0 |= pkt_ipv6_work_ttl(ip0, data0);
    3261                 :          0 :                         drop_mask1 |= pkt_ipv6_work_ttl(ip1, data1);
    3262                 :          0 :                         drop_mask2 |= pkt_ipv6_work_ttl(ip2, data2);
    3263                 :          0 :                         drop_mask3 |= pkt_ipv6_work_ttl(ip3, data3);
    3264                 :            :                 }
    3265                 :            :         }
    3266                 :            : 
    3267         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
    3268                 :            :                 void *data0 =
    3269                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_STATS);
    3270                 :            :                 void *data1 =
    3271                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_STATS);
    3272                 :            :                 void *data2 =
    3273                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_STATS);
    3274                 :            :                 void *data3 =
    3275                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_STATS);
    3276                 :            : 
    3277                 :            :                 pkt_work_stats(data0, total_length0);
    3278                 :            :                 pkt_work_stats(data1, total_length1);
    3279                 :            :                 pkt_work_stats(data2, total_length2);
    3280                 :            :                 pkt_work_stats(data3, total_length3);
    3281                 :            :         }
    3282                 :            : 
    3283         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
    3284                 :            :                 void *data0 =
    3285                 :            :                         action_data_get(table_entry0, action, RTE_TABLE_ACTION_TIME);
    3286                 :            :                 void *data1 =
    3287                 :            :                         action_data_get(table_entry1, action, RTE_TABLE_ACTION_TIME);
    3288                 :            :                 void *data2 =
    3289                 :            :                         action_data_get(table_entry2, action, RTE_TABLE_ACTION_TIME);
    3290                 :            :                 void *data3 =
    3291                 :            :                         action_data_get(table_entry3, action, RTE_TABLE_ACTION_TIME);
    3292                 :            : 
    3293                 :            :                 pkt_work_time(data0, time);
    3294                 :            :                 pkt_work_time(data1, time);
    3295                 :            :                 pkt_work_time(data2, time);
    3296                 :            :                 pkt_work_time(data3, time);
    3297                 :            :         }
    3298                 :            : 
    3299         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
    3300                 :            :                 void *data0 = action_data_get(table_entry0, action,
    3301                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO);
    3302                 :            :                 void *data1 = action_data_get(table_entry1, action,
    3303                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO);
    3304                 :            :                 void *data2 = action_data_get(table_entry2, action,
    3305                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO);
    3306                 :            :                 void *data3 = action_data_get(table_entry3, action,
    3307                 :            :                                 RTE_TABLE_ACTION_SYM_CRYPTO);
    3308                 :            : 
    3309   [ #  #  #  # ]:          0 :                 drop_mask0 |= pkt_work_sym_crypto(mbuf0, data0, &cfg->sym_crypto,
    3310                 :            :                                 ip_offset);
    3311         [ #  # ]:          0 :                 drop_mask1 |= pkt_work_sym_crypto(mbuf1, data1, &cfg->sym_crypto,
    3312                 :            :                                 ip_offset);
    3313         [ #  # ]:          0 :                 drop_mask2 |= pkt_work_sym_crypto(mbuf2, data2, &cfg->sym_crypto,
    3314                 :            :                                 ip_offset);
    3315                 :          0 :                 drop_mask3 |= pkt_work_sym_crypto(mbuf3, data3, &cfg->sym_crypto,
    3316                 :            :                                 ip_offset);
    3317                 :            :         }
    3318                 :            : 
    3319         [ #  # ]:          0 :         if (cfg->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
    3320                 :            :                 void *data0 = action_data_get(table_entry0,
    3321                 :            :                         action,
    3322                 :            :                         RTE_TABLE_ACTION_TAG);
    3323                 :            :                 void *data1 = action_data_get(table_entry1,
    3324                 :            :                         action,
    3325                 :            :                         RTE_TABLE_ACTION_TAG);
    3326                 :            :                 void *data2 = action_data_get(table_entry2,
    3327                 :            :                         action,
    3328                 :            :                         RTE_TABLE_ACTION_TAG);
    3329                 :            :                 void *data3 = action_data_get(table_entry3,
    3330                 :            :                         action,
    3331                 :            :                         RTE_TABLE_ACTION_TAG);
    3332                 :            : 
    3333                 :            :                 pkt4_work_tag(mbuf0, mbuf1, mbuf2, mbuf3,
    3334                 :            :                         data0, data1, data2, data3);
    3335                 :            :         }
    3336                 :            : 
    3337                 :          0 :         return drop_mask0 |
    3338                 :          0 :                 (drop_mask1 << 1) |
    3339                 :          0 :                 (drop_mask2 << 2) |
    3340                 :          0 :                 (drop_mask3 << 3);
    3341                 :            : }
    3342                 :            : 
    3343                 :            : static __rte_always_inline int
    3344                 :            : ah(struct rte_pipeline *p,
    3345                 :            :         struct rte_mbuf **pkts,
    3346                 :            :         uint64_t pkts_mask,
    3347                 :            :         struct rte_pipeline_table_entry **entries,
    3348                 :            :         struct rte_table_action *action,
    3349                 :            :         struct ap_config *cfg)
    3350                 :            : {
    3351                 :            :         uint64_t pkts_drop_mask = 0;
    3352                 :            :         uint64_t time = 0;
    3353                 :            : 
    3354                 :          0 :         if (cfg->action_mask & ((1LLU << RTE_TABLE_ACTION_MTR) |
    3355                 :            :                 (1LLU << RTE_TABLE_ACTION_TIME)))
    3356                 :          0 :                 time = rte_rdtsc();
    3357                 :            : 
    3358         [ #  # ]:          0 :         if ((pkts_mask & (pkts_mask + 1)) == 0) {
    3359                 :          0 :                 uint64_t n_pkts = rte_popcount64(pkts_mask);
    3360                 :            :                 uint32_t i;
    3361                 :            : 
    3362         [ #  # ]:          0 :                 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) {
    3363                 :            :                         uint64_t drop_mask;
    3364                 :            : 
    3365                 :          0 :                         drop_mask = pkt4_work(&pkts[i],
    3366         [ #  # ]:          0 :                                 &entries[i],
    3367                 :            :                                 time,
    3368                 :            :                                 action,
    3369                 :            :                                 cfg);
    3370                 :            : 
    3371                 :          0 :                         pkts_drop_mask |= drop_mask << i;
    3372                 :            :                 }
    3373                 :            : 
    3374         [ #  # ]:          0 :                 for ( ; i < n_pkts; i++) {
    3375                 :            :                         uint64_t drop_mask;
    3376                 :            : 
    3377                 :          0 :                         drop_mask = pkt_work(pkts[i],
    3378         [ #  # ]:          0 :                                 entries[i],
    3379                 :            :                                 time,
    3380                 :            :                                 action,
    3381                 :            :                                 cfg);
    3382                 :            : 
    3383                 :          0 :                         pkts_drop_mask |= drop_mask << i;
    3384                 :            :                 }
    3385                 :            :         } else
    3386         [ #  # ]:          0 :                 for ( ; pkts_mask; ) {
    3387                 :          0 :                         uint32_t pos = rte_ctz64(pkts_mask);
    3388                 :          0 :                         uint64_t pkt_mask = 1LLU << pos;
    3389                 :            :                         uint64_t drop_mask;
    3390                 :            : 
    3391                 :          0 :                         drop_mask = pkt_work(pkts[pos],
    3392         [ #  # ]:          0 :                                 entries[pos],
    3393                 :            :                                 time,
    3394                 :            :                                 action,
    3395                 :            :                                 cfg);
    3396                 :            : 
    3397                 :          0 :                         pkts_mask &= ~pkt_mask;
    3398                 :          0 :                         pkts_drop_mask |= drop_mask << pos;
    3399                 :            :                 }
    3400                 :            : 
    3401                 :          0 :         rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
    3402                 :            : 
    3403                 :            :         return 0;
    3404                 :            : }
    3405                 :            : 
    3406                 :            : static int
    3407         [ #  # ]:          0 : ah_default(struct rte_pipeline *p,
    3408                 :            :         struct rte_mbuf **pkts,
    3409                 :            :         uint64_t pkts_mask,
    3410                 :            :         struct rte_pipeline_table_entry **entries,
    3411                 :            :         void *arg)
    3412                 :            : {
    3413                 :            :         struct rte_table_action *action = arg;
    3414                 :            : 
    3415                 :          0 :         return ah(p,
    3416                 :            :                 pkts,
    3417                 :            :                 pkts_mask,
    3418                 :            :                 entries,
    3419                 :            :                 action,
    3420                 :            :                 &action->cfg);
    3421                 :            : }
    3422                 :            : 
    3423                 :            : static rte_pipeline_table_action_handler_hit
    3424                 :            : ah_selector(struct rte_table_action *action)
    3425                 :            : {
    3426         [ #  # ]:          0 :         if (action->cfg.action_mask == (1LLU << RTE_TABLE_ACTION_FWD))
    3427                 :          0 :                 return NULL;
    3428                 :            : 
    3429                 :            :         return ah_default;
    3430                 :            : }
    3431                 :            : 
    3432                 :            : int
    3433                 :          0 : rte_table_action_table_params_get(struct rte_table_action *action,
    3434                 :            :         struct rte_pipeline_table_params *params)
    3435                 :            : {
    3436                 :            :         rte_pipeline_table_action_handler_hit f_action_hit;
    3437                 :            :         uint32_t total_size;
    3438                 :            : 
    3439                 :            :         /* Check input arguments */
    3440                 :          0 :         if ((action == NULL) ||
    3441         [ #  # ]:          0 :                 (params == NULL))
    3442                 :            :                 return -EINVAL;
    3443                 :            : 
    3444                 :            :         f_action_hit = ah_selector(action);
    3445         [ #  # ]:          0 :         total_size = rte_align32pow2(action->data.total_size);
    3446                 :            : 
    3447                 :            :         /* Fill in params */
    3448                 :          0 :         params->f_action_hit = f_action_hit;
    3449                 :          0 :         params->f_action_miss = NULL;
    3450         [ #  # ]:          0 :         params->arg_ah = (f_action_hit) ? action : NULL;
    3451                 :          0 :         params->action_data_size = total_size -
    3452                 :            :                 sizeof(struct rte_pipeline_table_entry);
    3453                 :            : 
    3454                 :          0 :         return 0;
    3455                 :            : }
    3456                 :            : 
    3457                 :            : int
    3458                 :          0 : rte_table_action_free(struct rte_table_action *action)
    3459                 :            : {
    3460         [ #  # ]:          0 :         if (action == NULL)
    3461                 :            :                 return 0;
    3462                 :            : 
    3463                 :          0 :         rte_free(action);
    3464                 :            : 
    3465                 :          0 :         return 0;
    3466                 :            : }

Generated by: LCOV version 1.14