LCOV - code coverage report
Current view: top level - lib/lpm - rte_lpm.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 10 21 47.6 %
Date: 2025-03-01 20:23:48 Functions: 0 1 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 117 228 51.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  * Copyright(c) 2020 Arm Limited
       4                 :            :  */
       5                 :            : 
       6                 :            : #ifndef _RTE_LPM_H_
       7                 :            : #define _RTE_LPM_H_
       8                 :            : 
       9                 :            : /**
      10                 :            :  * @file
      11                 :            :  * RTE Longest Prefix Match (LPM)
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <errno.h>
      15                 :            : #include <stdalign.h>
      16                 :            : #include <stdint.h>
      17                 :            : 
      18                 :            : #include <rte_branch_prediction.h>
      19                 :            : #include <rte_byteorder.h>
      20                 :            : #include <rte_common.h>
      21                 :            : #include <rte_vect.h>
      22                 :            : #include <rte_rcu_qsbr.h>
      23                 :            : 
      24                 :            : #ifdef __cplusplus
      25                 :            : extern "C" {
      26                 :            : #endif
      27                 :            : 
      28                 :            : /** Max number of characters in LPM name. */
      29                 :            : #define RTE_LPM_NAMESIZE                32
      30                 :            : 
      31                 :            : /** Maximum depth value possible for IPv4 LPM. */
      32                 :            : #define RTE_LPM_MAX_DEPTH               32
      33                 :            : 
      34                 :            : /** @internal Total number of tbl24 entries. */
      35                 :            : #define RTE_LPM_TBL24_NUM_ENTRIES       (1 << 24)
      36                 :            : 
      37                 :            : /** @internal Number of entries in a tbl8 group. */
      38                 :            : #define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256
      39                 :            : 
      40                 :            : /** @internal Max number of tbl8 groups in the tbl8. */
      41                 :            : #define RTE_LPM_MAX_TBL8_NUM_GROUPS         (1 << 24)
      42                 :            : 
      43                 :            : /** @internal Total number of tbl8 groups in the tbl8. */
      44                 :            : #define RTE_LPM_TBL8_NUM_GROUPS         256
      45                 :            : 
      46                 :            : /** @internal Total number of tbl8 entries. */
      47                 :            : #define RTE_LPM_TBL8_NUM_ENTRIES        (RTE_LPM_TBL8_NUM_GROUPS * \
      48                 :            :                                         RTE_LPM_TBL8_GROUP_NUM_ENTRIES)
      49                 :            : 
      50                 :            : /** @internal Macro to enable/disable run-time checks. */
      51                 :            : #if defined(RTE_LIBRTE_LPM_DEBUG)
      52                 :            : #define RTE_LPM_RETURN_IF_TRUE(cond, retval) do { \
      53                 :            :         if (cond) return (retval);                \
      54                 :            : } while (0)
      55                 :            : #else
      56                 :            : #define RTE_LPM_RETURN_IF_TRUE(cond, retval)
      57                 :            : #endif
      58                 :            : 
      59                 :            : /** @internal bitmask with valid and valid_group fields set */
      60                 :            : #define RTE_LPM_VALID_EXT_ENTRY_BITMASK 0x03000000
      61                 :            : 
      62                 :            : /** Bitmask used to indicate successful lookup */
      63                 :            : #define RTE_LPM_LOOKUP_SUCCESS          0x01000000
      64                 :            : 
      65                 :            : /** @internal Default RCU defer queue entries to reclaim in one go. */
      66                 :            : #define RTE_LPM_RCU_DQ_RECLAIM_MAX      16
      67                 :            : 
      68                 :            : /** RCU reclamation modes */
      69                 :            : enum rte_lpm_qsbr_mode {
      70                 :            :         /** Create defer queue for reclaim. */
      71                 :            :         RTE_LPM_QSBR_MODE_DQ = 0,
      72                 :            :         /** Use blocking mode reclaim. No defer queue created. */
      73                 :            :         RTE_LPM_QSBR_MODE_SYNC
      74                 :            : };
      75                 :            : 
      76                 :            : #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
      77                 :            : /** @internal Tbl24 entry structure. */
      78                 :            : __extension__
      79                 :            : struct rte_lpm_tbl_entry {
      80                 :            :         /**
      81                 :            :          * Stores Next hop (tbl8 or tbl24 when valid_group is not set) or
      82                 :            :          * a group index pointing to a tbl8 structure (tbl24 only, when
      83                 :            :          * valid_group is set)
      84                 :            :          */
      85                 :            :         uint32_t next_hop    :24;
      86                 :            :         /* Using single uint8_t to store 3 values. */
      87                 :            :         uint32_t valid       :1;   /**< Validation flag. */
      88                 :            :         /**
      89                 :            :          * For tbl24:
      90                 :            :          *  - valid_group == 0: entry stores a next hop
      91                 :            :          *  - valid_group == 1: entry stores a group_index pointing to a tbl8
      92                 :            :          * For tbl8:
      93                 :            :          *  - valid_group indicates whether the current tbl8 is in use or not
      94                 :            :          */
      95                 :            :         uint32_t valid_group :1;
      96                 :            :         uint32_t depth       :6; /**< Rule depth. */
      97                 :            : };
      98                 :            : 
      99                 :            : #else
     100                 :            : 
     101                 :            : __extension__
     102                 :            : struct rte_lpm_tbl_entry {
     103                 :            :         uint32_t depth       :6;
     104                 :            :         uint32_t valid_group :1;
     105                 :            :         uint32_t valid       :1;
     106                 :            :         uint32_t next_hop    :24;
     107                 :            : 
     108                 :            : };
     109                 :            : 
     110                 :            : #endif
     111                 :            : 
     112                 :            : /** LPM configuration structure. */
     113                 :            : struct rte_lpm_config {
     114                 :            :         uint32_t max_rules;      /**< Max number of rules. */
     115                 :            :         uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
     116                 :            :         int flags;               /**< This field is currently unused. */
     117                 :            : };
     118                 :            : 
     119                 :            : /** @internal LPM structure. */
     120                 :            : struct rte_lpm {
     121                 :            :         /* LPM Tables. */
     122                 :            :         alignas(RTE_CACHE_LINE_SIZE) struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES];
     123                 :            :                         /**< LPM tbl24 table. */
     124                 :            :         struct rte_lpm_tbl_entry *tbl8; /**< LPM tbl8 table. */
     125                 :            : };
     126                 :            : 
     127                 :            : /** LPM RCU QSBR configuration structure. */
     128                 :            : struct rte_lpm_rcu_config {
     129                 :            :         struct rte_rcu_qsbr *v; /* RCU QSBR variable. */
     130                 :            :         /* Mode of RCU QSBR. RTE_LPM_QSBR_MODE_xxx
     131                 :            :          * '0' for default: create defer queue for reclaim.
     132                 :            :          */
     133                 :            :         enum rte_lpm_qsbr_mode mode;
     134                 :            :         uint32_t dq_size;       /* RCU defer queue size.
     135                 :            :                                  * default: lpm->number_tbl8s.
     136                 :            :                                  */
     137                 :            :         uint32_t reclaim_thd;   /* Threshold to trigger auto reclaim. */
     138                 :            :         uint32_t reclaim_max;   /* Max entries to reclaim in one go.
     139                 :            :                                  * default: RTE_LPM_RCU_DQ_RECLAIM_MAX.
     140                 :            :                                  */
     141                 :            : };
     142                 :            : 
     143                 :            : /**
     144                 :            :  * Free an LPM object.
     145                 :            :  *
     146                 :            :  * @param lpm
     147                 :            :  *   LPM object handle
     148                 :            :  *   If lpm is NULL, no operation is performed.
     149                 :            :  */
     150                 :            : void
     151                 :            : rte_lpm_free(struct rte_lpm *lpm);
     152                 :            : 
     153                 :            : /**
     154                 :            :  * Create an LPM object.
     155                 :            :  *
     156                 :            :  * @param name
     157                 :            :  *   LPM object name
     158                 :            :  * @param socket_id
     159                 :            :  *   NUMA socket ID for LPM table memory allocation
     160                 :            :  * @param config
     161                 :            :  *   Structure containing the configuration
     162                 :            :  * @return
     163                 :            :  *   Handle to LPM object on success, NULL otherwise with rte_errno set
     164                 :            :  *   to an appropriate values. Possible rte_errno values include:
     165                 :            :  *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
     166                 :            :  *    - E_RTE_SECONDARY - function was called from a secondary process instance
     167                 :            :  *    - EINVAL - invalid parameter passed to function
     168                 :            :  *    - ENOSPC - the maximum number of memzones has already been allocated
     169                 :            :  *    - EEXIST - a memzone with the same name already exists
     170                 :            :  *    - ENOMEM - no appropriate memory area found in which to create memzone
     171                 :            :  */
     172                 :            : struct rte_lpm *
     173                 :            : rte_lpm_create(const char *name, int socket_id,
     174                 :            :                const struct rte_lpm_config *config)
     175                 :            :         __rte_malloc __rte_dealloc(rte_lpm_free, 1);
     176                 :            : 
     177                 :            : /**
     178                 :            :  * Find an existing LPM object and return a pointer to it.
     179                 :            :  *
     180                 :            :  * @param name
     181                 :            :  *   Name of the lpm object as passed to rte_lpm_create()
     182                 :            :  * @return
     183                 :            :  *   Pointer to lpm object or NULL if object not found with rte_errno
     184                 :            :  *   set appropriately. Possible rte_errno values include:
     185                 :            :  *    - ENOENT - required entry not available to return.
     186                 :            :  */
     187                 :            : struct rte_lpm *
     188                 :            : rte_lpm_find_existing(const char *name);
     189                 :            : 
     190                 :            : /**
     191                 :            :  * Associate RCU QSBR variable with an LPM object.
     192                 :            :  *
     193                 :            :  * @param lpm
     194                 :            :  *   the lpm object to add RCU QSBR
     195                 :            :  * @param cfg
     196                 :            :  *   RCU QSBR configuration
     197                 :            :  * @return
     198                 :            :  *   On success - 0
     199                 :            :  *   On error - 1 with error code set in rte_errno.
     200                 :            :  *   Possible rte_errno codes are:
     201                 :            :  *   - EINVAL - invalid pointer
     202                 :            :  *   - EEXIST - already added QSBR
     203                 :            :  *   - ENOMEM - memory allocation failure
     204                 :            :  */
     205                 :            : int rte_lpm_rcu_qsbr_add(struct rte_lpm *lpm, struct rte_lpm_rcu_config *cfg);
     206                 :            : 
     207                 :            : /**
     208                 :            :  * Add a rule to the LPM table.
     209                 :            :  *
     210                 :            :  * @param lpm
     211                 :            :  *   LPM object handle
     212                 :            :  * @param ip
     213                 :            :  *   IP of the rule to be added to the LPM table
     214                 :            :  * @param depth
     215                 :            :  *   Depth of the rule to be added to the LPM table
     216                 :            :  * @param next_hop
     217                 :            :  *   Next hop of the rule to be added to the LPM table
     218                 :            :  * @return
     219                 :            :  *   0 on success, negative value otherwise
     220                 :            :  */
     221                 :            : int
     222                 :            : rte_lpm_add(struct rte_lpm *lpm, uint32_t ip, uint8_t depth, uint32_t next_hop);
     223                 :            : 
     224                 :            : /**
     225                 :            :  * Check if a rule is present in the LPM table,
     226                 :            :  * and provide its next hop if it is.
     227                 :            :  *
     228                 :            :  * @param lpm
     229                 :            :  *   LPM object handle
     230                 :            :  * @param ip
     231                 :            :  *   IP of the rule to be searched
     232                 :            :  * @param depth
     233                 :            :  *   Depth of the rule to searched
     234                 :            :  * @param next_hop
     235                 :            :  *   Next hop of the rule (valid only if it is found)
     236                 :            :  * @return
     237                 :            :  *   1 if the rule exists, 0 if it does not, a negative value on failure
     238                 :            :  */
     239                 :            : int
     240                 :            : rte_lpm_is_rule_present(struct rte_lpm *lpm, uint32_t ip, uint8_t depth,
     241                 :            : uint32_t *next_hop);
     242                 :            : 
     243                 :            : /**
     244                 :            :  * Delete a rule from the LPM table.
     245                 :            :  *
     246                 :            :  * @param lpm
     247                 :            :  *   LPM object handle
     248                 :            :  * @param ip
     249                 :            :  *   IP of the rule to be deleted from the LPM table
     250                 :            :  * @param depth
     251                 :            :  *   Depth of the rule to be deleted from the LPM table
     252                 :            :  * @return
     253                 :            :  *   0 on success, negative value otherwise
     254                 :            :  */
     255                 :            : int
     256                 :            : rte_lpm_delete(struct rte_lpm *lpm, uint32_t ip, uint8_t depth);
     257                 :            : 
     258                 :            : /**
     259                 :            :  * Delete all rules from the LPM table.
     260                 :            :  *
     261                 :            :  * @param lpm
     262                 :            :  *   LPM object handle
     263                 :            :  */
     264                 :            : void
     265                 :            : rte_lpm_delete_all(struct rte_lpm *lpm);
     266                 :            : 
     267                 :            : /**
     268                 :            :  * Lookup an IP into the LPM table.
     269                 :            :  *
     270                 :            :  * @param lpm
     271                 :            :  *   LPM object handle
     272                 :            :  * @param ip
     273                 :            :  *   IP to be looked up in the LPM table
     274                 :            :  * @param next_hop
     275                 :            :  *   Next hop of the most specific rule found for IP (valid on lookup hit only)
     276                 :            :  * @return
     277                 :            :  *   -EINVAL for incorrect arguments, -ENOENT on lookup miss, 0 on lookup hit
     278                 :            :  */
     279                 :            : static inline int
     280                 :            : rte_lpm_lookup(const struct rte_lpm *lpm, uint32_t ip, uint32_t *next_hop)
     281                 :            : {
     282                 :        778 :         unsigned tbl24_index = (ip >> 8);
     283                 :            :         uint32_t tbl_entry;
     284                 :            :         const uint32_t *ptbl;
     285                 :            : 
     286                 :            :         /* DEBUG: Check user input arguments. */
     287                 :            :         RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
     288                 :            : 
     289                 :            :         /* Copy tbl24 entry */
     290                 :        778 :         ptbl = (const uint32_t *)(&lpm->tbl24[tbl24_index]);
     291                 :       4949 :         tbl_entry = *ptbl;
     292                 :            : 
     293                 :            :         /* Memory ordering is not required in lookup. Because dataflow
     294                 :            :          * dependency exists, compiler or HW won't be able to re-order
     295                 :            :          * the operations.
     296                 :            :          */
     297                 :            :         /* Copy tbl8 entry (only if needed) */
     298   [ +  +  -  +  :       4953 :         if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  -  
          +  +  -  -  +  
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
          +  -  +  +  -  
          +  -  +  -  +  
          -  -  +  -  +  
          -  +  -  +  +  
          -  +  -  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          -  +  -  +  +  
          +  +  +  -  +  
          +  -  -  +  -  
                +  -  + ]
     299                 :            :                         RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
     300                 :            : 
     301                 :         11 :                 unsigned tbl8_index = (uint8_t)ip +
     302                 :       2551 :                                 (((uint32_t)tbl_entry & 0x00FFFFFF) *
     303                 :            :                                                 RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
     304                 :            : 
     305                 :       2551 :                 ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
     306                 :       2551 :                 tbl_entry = *ptbl;
     307                 :            :         }
     308                 :            : 
     309                 :       3871 :         *next_hop = ((uint32_t)tbl_entry & 0x00FFFFFF);
     310   [ +  +  +  -  :       4953 :         return (tbl_entry & RTE_LPM_LOOKUP_SUCCESS) ? 0 : -ENOENT;
          -  +  +  -  -  
          +  -  +  -  +  
          -  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  +  +  -  
          +  -  +  -  +  
                -  +  - ]
     311                 :            : }
     312                 :            : 
     313                 :            : /**
     314                 :            :  * Lookup multiple IP addresses in an LPM table. This may be implemented as a
     315                 :            :  * macro, so the address of the function should not be used.
     316                 :            :  *
     317                 :            :  * @param lpm
     318                 :            :  *   LPM object handle
     319                 :            :  * @param ips
     320                 :            :  *   Array of IPs to be looked up in the LPM table
     321                 :            :  * @param next_hops
     322                 :            :  *   Next hop of the most specific rule found for IP (valid on lookup hit only).
     323                 :            :  *   This is an array of two byte values. The most significant byte in each
     324                 :            :  *   value says whether the lookup was successful (bitmask
     325                 :            :  *   RTE_LPM_LOOKUP_SUCCESS is set). The least significant byte is the
     326                 :            :  *   actual next hop.
     327                 :            :  * @param n
     328                 :            :  *   Number of elements in ips (and next_hops) array to lookup. This should be a
     329                 :            :  *   compile time constant, and divisible by 8 for best performance.
     330                 :            :  *  @return
     331                 :            :  *   -EINVAL for incorrect arguments, otherwise 0
     332                 :            :  */
     333                 :            : #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
     334                 :            :                 rte_lpm_lookup_bulk_func(lpm, ips, next_hops, n)
     335                 :            : 
     336                 :            : static inline int
     337                 :          0 : rte_lpm_lookup_bulk_func(const struct rte_lpm *lpm, const uint32_t *ips,
     338                 :            :                 uint32_t *next_hops, const unsigned n)
     339                 :            : {
     340                 :            :         unsigned i;
     341                 :            :         const uint32_t *ptbl;
     342                 :            : 
     343                 :            :         /* DEBUG: Check user input arguments. */
     344                 :            :         RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (ips == NULL) ||
     345                 :            :                         (next_hops == NULL)), -EINVAL);
     346                 :            : 
     347         [ #  # ]:          0 :         for (i = 0; i < n; i++) {
     348                 :          0 :                 unsigned int tbl24_index = ips[i] >> 8;
     349                 :            : 
     350                 :            :                 /* Simply copy tbl24 entry to output */
     351                 :          0 :                 ptbl = (const uint32_t *)&lpm->tbl24[tbl24_index];
     352                 :          0 :                 next_hops[i] = *ptbl;
     353                 :            : 
     354                 :            :                 /* Overwrite output with tbl8 entry if needed */
     355         [ #  # ]:          0 :                 if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
     356                 :            :                                 RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
     357                 :            : 
     358                 :          0 :                         unsigned tbl8_index = (uint8_t)ips[i] +
     359                 :          0 :                                         (((uint32_t)next_hops[i] & 0x00FFFFFF) *
     360                 :            :                                          RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
     361                 :            : 
     362                 :          0 :                         ptbl = (const uint32_t *)&lpm->tbl8[tbl8_index];
     363                 :          0 :                         next_hops[i] = *ptbl;
     364                 :            :                 }
     365                 :            :         }
     366                 :          0 :         return 0;
     367                 :            : }
     368                 :            : 
     369                 :            : /* Mask four results. */
     370                 :            : #define  RTE_LPM_MASKX4_RES     UINT64_C(0x00ffffff00ffffff)
     371                 :            : 
     372                 :            : /**
     373                 :            :  * Lookup four IP addresses in an LPM table.
     374                 :            :  *
     375                 :            :  * @param lpm
     376                 :            :  *   LPM object handle
     377                 :            :  * @param ip
     378                 :            :  *   Four IPs to be looked up in the LPM table
     379                 :            :  * @param hop
     380                 :            :  *   Next hop of the most specific rule found for IP (valid on lookup hit only).
     381                 :            :  *   This is an 4 elements array of two byte values.
     382                 :            :  *   If the lookup was successful for the given IP, then least significant byte
     383                 :            :  *   of the corresponding element is the  actual next hop and the most
     384                 :            :  *   significant byte is zero.
     385                 :            :  *   If the lookup for the given IP failed, then corresponding element would
     386                 :            :  *   contain default value, see description of then next parameter.
     387                 :            :  * @param defv
     388                 :            :  *   Default value to populate into corresponding element of hop[] array,
     389                 :            :  *   if lookup would fail.
     390                 :            :  */
     391                 :            : static inline void
     392                 :            : rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
     393                 :            :         uint32_t defv);
     394                 :            : 
     395                 :            : #ifdef __cplusplus
     396                 :            : }
     397                 :            : #endif
     398                 :            : 
     399                 :            : #if defined(RTE_ARCH_ARM)
     400                 :            : #ifdef RTE_HAS_SVE_ACLE
     401                 :            : #include "rte_lpm_sve.h"
     402                 :            : #undef rte_lpm_lookup_bulk
     403                 :            : #define rte_lpm_lookup_bulk(lpm, ips, next_hops, n) \
     404                 :            :                 __rte_lpm_lookup_vec(lpm, ips, next_hops, n)
     405                 :            : #endif
     406                 :            : #include "rte_lpm_neon.h"
     407                 :            : #elif defined(RTE_ARCH_PPC_64)
     408                 :            : #include "rte_lpm_altivec.h"
     409                 :            : #elif defined(RTE_ARCH_X86)
     410                 :            : #include "rte_lpm_sse.h"
     411                 :            : #else
     412                 :            : #include "rte_lpm_scalar.h"
     413                 :            : #endif
     414                 :            : 
     415                 :            : #endif /* _RTE_LPM_H_ */

Generated by: LCOV version 1.14