LCOV - code coverage report
Current view: top level - vnet/fib - ip4_fib_hash.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 52 55 94.5 %
Date: 2023-10-26 01:39:38 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <vnet/fib/fib_table.h>
      17             : #include <vnet/fib/fib_entry.h>
      18             : #include <vnet/fib/ip4_fib.h>
      19             : 
      20             : /*
      21             :  * ip4_fib_hash_table_lookup_exact_match
      22             :  *
      23             :  * Exact match prefix lookup
      24             :  */
      25             : fib_node_index_t
      26      191902 : ip4_fib_hash_table_lookup_exact_match (const ip4_fib_hash_t *fib,
      27             :                                        const ip4_address_t *addr,
      28             :                                        u32 len)
      29             : {
      30             :     uword * hash, * result;
      31             :     u32 key;
      32             : 
      33      191902 :     hash = fib->fib_entry_by_dst_address[len];
      34      191902 :     key  = (addr->data_u32 & ip4_main.fib_masks[len]);
      35             : 
      36      191902 :     result = hash_get(hash, key);
      37             : 
      38      191902 :     if (NULL != result) {
      39      166690 :         return (result[0]);
      40             :     }
      41       25212 :     return (FIB_NODE_INDEX_INVALID);
      42             : }
      43             : 
      44             : /*
      45             :  * ip4_fib_hash_table_lookup_adj
      46             :  *
      47             :  * Longest prefix match
      48             :  */
      49             : index_t
      50         100 : ip4_fib_hash_table_lookup_lb (const ip4_fib_hash_t *fib,
      51             :                               const ip4_address_t *addr)
      52             : {
      53             :     fib_node_index_t fei;
      54             : 
      55         100 :     fei = ip4_fib_hash_table_lookup(fib, addr, 32);
      56             : 
      57         100 :     if (FIB_NODE_INDEX_INVALID != fei)
      58             :     {
      59             :         const dpo_id_t *dpo;
      60             : 
      61         100 :         dpo = fib_entry_contribute_ip_forwarding(fei);
      62             : 
      63         100 :         return (dpo->dpoi_index);
      64             :     }
      65           0 :     return (INDEX_INVALID);
      66             : }
      67             : 
      68             : /*
      69             :  * ip4_fib_hash_table_lookup
      70             :  *
      71             :  * Longest prefix match
      72             :  */
      73             : fib_node_index_t
      74      119410 : ip4_fib_hash_table_lookup (const ip4_fib_hash_t *fib,
      75             :                            const ip4_address_t *addr,
      76             :                            u32 len)
      77             : {
      78             :     uword * hash, * result;
      79             :     i32 mask_len;
      80             :     u32 key;
      81             : 
      82      771287 :     for (mask_len = len; mask_len >= 0; mask_len--)
      83             :     {
      84      771287 :         hash = fib->fib_entry_by_dst_address[mask_len];
      85      771287 :         key = (addr->data_u32 & ip4_main.fib_masks[mask_len]);
      86             : 
      87      771287 :         result = hash_get (hash, key);
      88             : 
      89      771284 :         if (NULL != result) {
      90      119407 :             return (result[0]);
      91             :         }
      92             :     }
      93           0 :     return (FIB_NODE_INDEX_INVALID);
      94             : }
      95             : 
      96             : void
      97       22420 : ip4_fib_hash_table_entry_insert (ip4_fib_hash_t *fib,
      98             :                                  const ip4_address_t *addr,
      99             :                                  u32 len,
     100             :                                  fib_node_index_t fib_entry_index)
     101             : {
     102             :     uword * hash, * result;
     103             :     u32 key;
     104             : 
     105       22420 :     key = (addr->data_u32 & ip4_main.fib_masks[len]);
     106       22420 :     hash = fib->fib_entry_by_dst_address[len];
     107       22420 :     result = hash_get (hash, key);
     108             : 
     109       22420 :     if (NULL == result) {
     110             :         /*
     111             :          * adding a new entry
     112             :          */
     113             : 
     114       22420 :         if (NULL == hash) {
     115        2581 :             hash = hash_create (32 /* elts */, sizeof (uword));
     116        2581 :             hash_set_flags (hash, HASH_FLAG_NO_AUTO_SHRINK);
     117             : 
     118             :         }
     119       22420 :         hash = hash_set(hash, key, fib_entry_index);
     120       22420 :         fib->fib_entry_by_dst_address[len] = hash;
     121             :     }
     122             :     else
     123             :     {
     124           0 :         ASSERT(0);
     125             :     }
     126       22420 : }
     127             : 
     128             : void
     129       16239 : ip4_fib_hash_table_entry_remove (ip4_fib_hash_t *fib,
     130             :                                  const ip4_address_t *addr,
     131             :                                  u32 len)
     132             : {
     133             :     uword * hash, * result;
     134             :     u32 key;
     135             : 
     136       16239 :     key = (addr->data_u32 & ip4_main.fib_masks[len]);
     137       16239 :     hash = fib->fib_entry_by_dst_address[len];
     138       16239 :     result = hash_get (hash, key);
     139             : 
     140       16239 :     if (NULL == result)
     141             :     {
     142             :         /*
     143             :          * removing a non-existent entry. i'll allow it.
     144             :          */
     145             :     }
     146             :     else
     147             :     {
     148       16239 :         hash_unset(hash, key);
     149             :     }
     150             : 
     151       16239 :     fib->fib_entry_by_dst_address[len] = hash;
     152       16239 : }
     153             : 
     154             : void
     155        3184 : ip4_fib_hash_table_walk (ip4_fib_hash_t *fib,
     156             :                          fib_table_walk_fn_t fn,
     157             :                          void *ctx)
     158             : {
     159        3184 :     fib_prefix_t root = {
     160             :         .fp_proto = FIB_PROTOCOL_IP4,
     161             :         // address and length default to all 0
     162             :     };
     163             : 
     164             :     /*
     165             :      * A full tree walk is the dengenerate case of a sub-tree from
     166             :      * the very root
     167             :      */
     168        3184 :     return (ip4_fib_hash_table_sub_tree_walk(fib, &root, fn, ctx));
     169             : }
     170             : 
     171             : void
     172        3240 : ip4_fib_hash_table_sub_tree_walk (ip4_fib_hash_t *fib,
     173             :                                   const fib_prefix_t *root,
     174             :                                   fib_table_walk_fn_t fn,
     175             :                                   void *ctx)
     176             : {
     177        3240 :     fib_prefix_t *sub_trees = NULL;
     178             :     int i;
     179             : 
     180             :     /*
     181             :      * There is no efficient way to walk this array of hash tables.
     182             :      * so we walk each table with a mask length greater than and equal to
     183             :      * the required root and check it is covered by the root.
     184             :      */
     185        3240 :     for (i = root->fp_len;
     186      108554 :          i < ARRAY_LEN (fib->fib_entry_by_dst_address);
     187      105314 :          i++)
     188             :     {
     189      105314 :         uword * hash = fib->fib_entry_by_dst_address[i];
     190             : 
     191      105314 :         if (NULL != hash)
     192             :         {
     193             :             ip4_address_t key;
     194             :             hash_pair_t * p;
     195             : 
     196     1395330 :             hash_foreach_pair (p, hash,
     197             :             ({
     198             :                 key.as_u32 = p->key;
     199             :                 if (ip4_destination_matches_route(&ip4_main,
     200             :                                                   &key,
     201             :                                                   &root->fp_addr.ip4,
     202             :                                                   root->fp_len))
     203             :                 {
     204             :                     const fib_prefix_t *sub_tree;
     205             :                     int skip = 0;
     206             : 
     207             :                     /*
     208             :                      * exclude sub-trees the walk does not want to explore
     209             :                      */
     210             :                     vec_foreach(sub_tree, sub_trees)
     211             :                     {
     212             :                         if (ip4_destination_matches_route(&ip4_main,
     213             :                                                           &key,
     214             :                                                           &sub_tree->fp_addr.ip4,
     215             :                                                           sub_tree->fp_len))
     216             :                         {
     217             :                             skip = 1;
     218             :                             break;
     219             :                         }
     220             :                     }
     221             : 
     222             :                     if (!skip)
     223             :                     {
     224             :                         switch (fn(p->value[0], ctx))
     225             :                         {
     226             :                         case FIB_TABLE_WALK_CONTINUE:
     227             :                             break;
     228             :                         case FIB_TABLE_WALK_SUB_TREE_STOP: {
     229             :                             fib_prefix_t pfx = {
     230             :                                 .fp_proto = FIB_PROTOCOL_IP4,
     231             :                                 .fp_len = i,
     232             :                                 .fp_addr.ip4 = key,
     233             :                             };
     234             :                             vec_add1(sub_trees, pfx);
     235             :                             break;
     236             :                         }
     237             :                         case FIB_TABLE_WALK_STOP:
     238             :                             goto done;
     239             :                         }
     240             :                     }
     241             :                 }
     242             :             }));
     243             :         }
     244             :     }
     245        3240 : done:
     246        3240 :     vec_free(sub_trees);
     247        3240 :     return;
     248             : }
     249             : 

Generated by: LCOV version 1.14