openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

alpm_trie.c (152630B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * File:    trie.c
      7  * Purpose: Custom Trie Data structure
      8  * Requires:
      9  */
     10 
     11 /* Implementation notes:
     12  * Trie is a prefix based data strucutre. It is based on modification to digital search trie.
     13  * This implementation is not a Path compressed Binary Trie (or) a Patricia Trie.
     14  * It is a custom version which represents prefix on a digital search trie as following.
     15  * A given node on the trie could be a Payload node or a Internal node. Each node is represented
     16  * by <skip address, skip length> pair. Each node represents the given prefix it represents when
     17  * the prefix is viewed from Right to Left. ie., Most significant bits to Least significant bits.
     18  * Each node has a Right & Left child which branches based on bit on that position. 
     19  * There can be empty split node i.e, <0,0> just to host two of its children. 
     20  */
     21 #include <soc/types.h>
     22 #include <soc/drv.h>
     23 #include <shared/bsl.h>
     24 #ifdef ALPM_ENABLE
     25 #ifdef BCM_TRIDENT2_SUPPORT
     26 
     27 #include <shared/util.h>
     28 #include <sal/appl/sal.h>
     29 #include <sal/core/libc.h>
     30 #include <sal/core/time.h>
     31 #include <soc/esw/trie.h>
     32 #include <soc/esw/trie_util.h>
     33 #include <soc/esw/alpm_trie_v6.h>
     34 
     35 #define _MAX_SKIP_LEN_  (31)
     36 #define _MAX_KEY_LEN_   (48)
     37 
     38 #define _MAX_KEY_WORDS_ (BITS2WORDS(_MAX_KEY_LEN_))
     39 
     40 #define SHL(data, shift, max) \
     41     (((shift)>=(max))?0:((data)<<(shift)))
     42 
     43 #define SHR(data, shift, max) \
     44     (((shift)>=(max))?0:((data)>>(shift)))
     45 
     46 #define MASK(len) \
     47     (((len)>=32 || (len)==0)?0xFFFFFFFF:((1<<(len))-1))
     48 
     49 #define BITMASK(len) \
     50     (((len)>=32)?0xFFFFFFFF:((1<<(len))-1))
     51 
     52 #define ABS(n) ((((int)(n)) < 0) ? -(n) : (n))
     53 
     54 #define _NUM_WORD_BITS_ (32)
     55 
     56 #define BITS2SKIPOFF(x) (((x) + _MAX_SKIP_LEN_-1) / _MAX_SKIP_LEN_)
     57 
     58 /* key packing expetations:
     59  * eg., 48 bit key
     60  * - 10/8 -> key[0]=0, key[1]=8
     61  * - 0x123456789a -> key[0] = 0x12 key[1] = 0x3456789a
     62  * length - represents number of valid bits from farther to lower index ie., 1->0 
     63  */
     64 
     65 #define KEY_BIT2IDX(x) (((BITS2WORDS(_MAX_KEY_LEN_)*32) - (x))/32)
     66 
     67 
     68 /* (internal) Generic operation macro on bit array _a, with bit _b */
     69 #define	_BITOP(_a, _b, _op)	\
     70         ((_a) _op (1U << ((_b) % _NUM_WORD_BITS_)))
     71 
     72 /* Specific operations */
     73 #define	_BITGET(_a, _b)	_BITOP(_a, _b, &)
     74 #define	_BITSET(_a, _b)	_BITOP(_a, _b, |=)
     75 #define	_BITCLR(_a, _b)	_BITOP(_a, _b, &= ~)
     76 
     77 /* get the bit position of the LSB set in bit 0 to bit "msb" of "data"
     78  * (max 32 bits), "lsb" is set to -1 if no bit is set in "data".
     79  */
     80 #define BITGETLSBSET(data, msb, lsb)    \
     81     {                                    \
     82 	lsb = 0;                         \
     83 	while ((lsb)<=(msb)) {		 \
     84 	    if ((data)&(1<<(lsb)))     { \
     85 		break;                   \
     86 	    } else { (lsb)++;}           \
     87 	}                                \
     88 	lsb = ((lsb)>(msb))?-1:(lsb);    \
     89     }
     90 #define KEY_BIT2IDX(x) (((BITS2WORDS(_MAX_KEY_LEN_)*32) - (x))/32)
     91 
     92 /********************************************************/
     93 /* Get a chunk of bits from a key (MSB bit - on word0, lsb on word 1).. 
     94  */
     95 unsigned int _key_get_bits(unsigned int *key, 
     96                            unsigned int pos /* 1based, msb bit position */, 
     97                            unsigned int len,
     98                            unsigned int skip_len_check)
     99 {
    100     unsigned int val=0, delta=0, diff, bitpos;
    101 
    102     /* coverity[var_deref_op : FALSE] */
    103     if (!key || (pos < 1) || (pos > _MAX_KEY_LEN_) || 
    104         ((skip_len_check == 0) && (len > _MAX_SKIP_LEN_))) assert(0);
    105 
    106     bitpos = (pos-1) % _NUM_WORD_BITS_;
    107     bitpos++; /* 1 based */
    108 
    109     if (bitpos >= len) {
    110         diff = bitpos - len;
    111         /* coverity[var_deref_op : FALSE] */
    112         val = SHR(key[KEY_BIT2IDX(pos)], diff, _NUM_WORD_BITS_);
    113         val &= MASK(len);
    114         return val;
    115     } else {
    116         diff = len - bitpos;
    117         if (skip_len_check==0) assert(diff <= _MAX_SKIP_LEN_);
    118         /* coverity[var_deref_op : FALSE] */
    119         val = key[KEY_BIT2IDX(pos)] & MASK(bitpos);
    120         val = SHL(val, diff, _NUM_WORD_BITS_);
    121         /* get bits from next word */
    122         delta = _key_get_bits(key, pos-bitpos, diff, skip_len_check);
    123         return (delta | val);
    124     }
    125 }		
    126 
    127 
    128 /* 
    129  * Assumes the layout for 
    130  * 0 - most significant word
    131  * _MAX_KEY_WORDS_ - least significant word
    132  * eg., for key size of 48, word0-[bits 48-32] word1-[bits31-0]
    133  */
    134 int _key_shift_left(unsigned int *key, unsigned int shift)
    135 {
    136     unsigned int index=0;
    137 
    138     if (!key || shift > _MAX_SKIP_LEN_) return SOC_E_PARAM;
    139 
    140     for(index=KEY_BIT2IDX(_MAX_KEY_LEN_); index < KEY_BIT2IDX(1); index++) {
    141         key[index] = SHL(key[index], shift,_NUM_WORD_BITS_) | \
    142                      SHR(key[index+1],_NUM_WORD_BITS_-shift,_NUM_WORD_BITS_);
    143     }
    144 
    145     key[index] = SHL(key[index], shift, _NUM_WORD_BITS_);
    146 
    147     /* mask off snippets bit on MSW */
    148     key[0] &= MASK(_MAX_KEY_LEN_ % _NUM_WORD_BITS_);
    149     return SOC_E_NONE;
    150 }
    151 
    152 /* 
    153  * Assumes the layout for 
    154  * 0 - most significant word
    155  * _MAX_KEY_WORDS_ - least significant word
    156  * eg., for key size of 48, word0-[bits 48-32] word1-[bits31-0]
    157  */
    158 int _key_shift_right(unsigned int *key, unsigned int shift)
    159 {
    160     unsigned int index=0;
    161 
    162     if (!key || shift > _MAX_SKIP_LEN_) return SOC_E_PARAM;
    163 
    164     for(index=KEY_BIT2IDX(1); index > KEY_BIT2IDX(_MAX_KEY_LEN_); index--) {
    165         key[index] = SHR(key[index], shift,_NUM_WORD_BITS_) | \
    166                      SHL(key[index-1],_NUM_WORD_BITS_-shift,_NUM_WORD_BITS_);
    167     }
    168 
    169     key[index] = SHR(key[index], shift, _NUM_WORD_BITS_);
    170 
    171     /* mask off snippets bit on MSW */
    172     key[0] &= MASK(_MAX_KEY_LEN_ % _NUM_WORD_BITS_);
    173     return SOC_E_NONE;
    174 }
    175 
    176 
    177 /* 
    178  * Assumes the layout for 
    179  * 0 - most significant word
    180  * _MAX_KEY_WORDS_ - least significant word
    181  * eg., for key size of 48, word0-[bits 48-32] word1-[bits31-0]
    182  */
    183 int _key_append(unsigned int *key, 
    184                 unsigned int *length,
    185                 unsigned int skip_addr,
    186                 unsigned int skip_len)
    187 {
    188     int rv=SOC_E_NONE;
    189 
    190     if (!key || !length || (skip_len + *length > _MAX_KEY_LEN_) || skip_len > _MAX_SKIP_LEN_ ) return SOC_E_PARAM;
    191 
    192     rv = _key_shift_left(key, skip_len);
    193     if (SOC_SUCCESS(rv)) {
    194         key[KEY_BIT2IDX(1)] |= skip_addr;
    195         *length += skip_len;
    196     }
    197 
    198     return rv;
    199 }
    200 
    201 int _bpm_append(unsigned int *key, 
    202                 unsigned int *length,
    203                 unsigned int skip_addr,
    204                 unsigned int skip_len)
    205 {
    206     int rv=SOC_E_NONE;
    207 
    208     if (!key || !length || (skip_len + *length > _MAX_KEY_LEN_) || skip_len > (_MAX_SKIP_LEN_+1) ) return SOC_E_PARAM;
    209 
    210     if (skip_len == 32) {
    211 	key[0] = key[1];
    212 	key[1] = skip_addr;
    213 	*length += skip_len;
    214     } else {
    215 	rv = _key_shift_left(key, skip_len);
    216 	if (SOC_SUCCESS(rv)) {
    217 	    key[KEY_BIT2IDX(1)] |= skip_addr;
    218 	    *length += skip_len;
    219 	}
    220     }
    221 
    222     return rv;
    223 }
    224 
    225 /*
    226  * Function:
    227  *     lcplen
    228  * Purpose:
    229  *     returns longest common prefix length provided a key & skip address
    230  */
    231 unsigned int
    232 lcplen(unsigned int *key, unsigned int len1,
    233        unsigned int skip_addr, unsigned int len2)
    234 {
    235     unsigned int diff;
    236     unsigned int lcp = len1 < len2 ? len1 : len2;
    237 
    238     if ((len1 > _MAX_KEY_LEN_) || (len2 > _MAX_KEY_LEN_)) {
    239 	LOG_CLI((BSL_META("len1 %d or len2 %d is larger than %d\n"),
    240                  len1, len2, _MAX_KEY_LEN_));
    241 	assert(0);
    242     } 
    243 
    244     if (len1 == 0 || len2 == 0) return 0;
    245 
    246     diff = _key_get_bits(key, len1, lcp, 0);
    247     diff ^= (SHR(skip_addr, len2 - lcp, _MAX_SKIP_LEN_) & MASK(lcp));
    248 
    249     while (diff) {
    250         diff >>= 1;
    251         --lcp;
    252     }
    253 
    254     return lcp;
    255 }
    256 
    257 int _print_trie_node(trie_node_t *trie, void *datum)
    258 {
    259     if (trie != NULL) {
    260 
    261 	LOG_CLI((BSL_META("trie: %p, type %s, skip_addr 0x%x skip_len %d "
    262                           "count:%d bpm:0x%x Child[0]:%p Child[1]:%p\n"),
    263                  trie, (trie->type == PAYLOAD)?"P":"I",
    264                  trie->skip_addr, trie->skip_len, 
    265                  trie->count, trie->bpm, trie->child[0].child_node,
    266                  trie->child[1].child_node));
    267     }
    268     return SOC_E_NONE;
    269 }
    270 
    271 STATIC int _trie_preorder_traverse(trie_node_t *trie, trie_callback_f cb, void *user_data)
    272 {
    273     int rv = SOC_E_NONE;
    274     trie_node_t *tmp1, *tmp2;
    275 
    276     if (trie == NULL || !cb) {
    277 	return SOC_E_NONE;
    278     } else {
    279         /* make the node delete safe */
    280         tmp1 = trie->child[0].child_node;
    281         tmp2 = trie->child[1].child_node;
    282         rv = cb(trie, user_data);
    283     }
    284 
    285     if (SOC_SUCCESS(rv)) {
    286         rv = _trie_preorder_traverse(tmp1, cb, user_data);
    287     }
    288     if (SOC_SUCCESS(rv)) {
    289         rv = _trie_preorder_traverse(tmp2, cb, user_data);
    290     }
    291     return rv;
    292 }
    293 
    294 STATIC int _trie_postorder_traverse(trie_node_t *trie, trie_callback_f cb, void *user_data)
    295 {
    296     int rv = SOC_E_NONE;
    297 
    298     if (trie == NULL) {
    299 	return SOC_E_NONE;
    300     }
    301 
    302     if (SOC_SUCCESS(rv)) {
    303         rv = _trie_postorder_traverse(trie->child[0].child_node, cb, user_data);
    304     }
    305     if (SOC_SUCCESS(rv)) {
    306         rv = _trie_postorder_traverse(trie->child[1].child_node, cb, user_data);
    307     }
    308     if (SOC_SUCCESS(rv)) {
    309         rv = cb(trie, user_data);
    310     }
    311     return rv;
    312 }
    313 
    314 STATIC int _trie_inorder_traverse(trie_node_t *trie, trie_callback_f cb, void *user_data)
    315 {
    316     int rv = SOC_E_NONE;
    317     trie_node_t *tmp = NULL;
    318 
    319     if (trie == NULL) {
    320 	return SOC_E_NONE;
    321     }
    322 
    323     if (SOC_SUCCESS(rv)) {
    324         rv = _trie_inorder_traverse(trie->child[0].child_node, cb, user_data);
    325     }
    326 
    327     /* make the trie pointers delete safe */
    328     tmp = trie->child[1].child_node;
    329 
    330     if (SOC_SUCCESS(rv)) {
    331         rv = cb(trie, user_data);
    332     }
    333 
    334     if (SOC_SUCCESS(rv)) {
    335         rv = _trie_inorder_traverse(tmp, cb, user_data);
    336     }
    337     return rv;
    338 }
    339 
    340 STATIC int _trie_traverse(trie_node_t *trie, trie_callback_f cb, 
    341 			  void *user_data,  trie_traverse_order_e_t order)
    342 {
    343     int rv = SOC_E_NONE;
    344 
    345     switch(order) {
    346     case _TRIE_PREORDER_TRAVERSE:
    347         rv = _trie_preorder_traverse(trie, cb, user_data);
    348         break;
    349     case _TRIE_POSTORDER_TRAVERSE:
    350         rv = _trie_postorder_traverse(trie, cb, user_data);
    351         break;
    352     case _TRIE_INORDER_TRAVERSE:
    353         rv = _trie_inorder_traverse(trie, cb, user_data);
    354         break;
    355     default:
    356         assert(0);
    357     }
    358 
    359     return rv;
    360 }
    361 
    362 /*
    363  * Function:
    364  *     trie_traverse
    365  * Purpose:
    366  *     Traverse the trie & call the application callback with user data 
    367  */
    368 int trie_traverse(trie_t *trie, trie_callback_f cb, 
    369                   void *user_data, trie_traverse_order_e_t order)
    370 {
    371     if (order < _TRIE_PREORDER_TRAVERSE ||
    372         order >= _TRIE_TRAVERSE_MAX || !cb) return SOC_E_PARAM;
    373 
    374     if (trie == NULL) {
    375 	return SOC_E_NONE;
    376     } else {
    377         return _trie_traverse(trie->trie, cb, user_data, order);
    378     }
    379 }
    380 
    381 #define TRIE_TRAVERSE_STOP(state, rv) \
    382     {if (state == TRIE_TRAVERSE_STATE_DONE || rv < 0) {return rv;} }
    383 
    384 STATIC int _trie_preorder_traverse2(trie_node_t *ptrie,
    385                                     trie_node_t *trie,
    386                                     trie_traverse_states_e_t *state,
    387                                     trie_callback_ext_f cb,
    388                                     void *user_data)
    389 {
    390     int rv = SOC_E_NONE;
    391     trie_node_t *lc, *rc;
    392 
    393     if (trie == NULL || !cb) {
    394         return SOC_E_NONE;
    395     } else {
    396         assert(!ptrie || ptrie->type == PAYLOAD);
    397 
    398         /* make the trie delete safe */
    399         lc = trie->child[0].child_node;
    400         rc = trie->child[1].child_node;
    401         if (trie->type == PAYLOAD) { /* no need to callback on internal nodes */
    402             rv = cb(ptrie, trie, state, user_data);
    403             TRIE_TRAVERSE_STOP(*state, rv);
    404 
    405             /* Change the ptrie as trie if applicable */
    406             /* make the ptrie delete safe */
    407             if (*state != TRIE_TRAVERSE_STATE_DELETED) {
    408                 ptrie = trie;
    409             }
    410         }
    411     }
    412 
    413     if (SOC_SUCCESS(rv)) {
    414         rv = _trie_preorder_traverse2(ptrie, lc, state, cb, user_data);
    415         TRIE_TRAVERSE_STOP(*state, rv);
    416     }
    417     if (SOC_SUCCESS(rv)) {
    418         rv = _trie_preorder_traverse2(ptrie, rc, state, cb, user_data);
    419     }
    420     return rv;
    421 }
    422 
    423 STATIC int _trie_postorder_traverse2(trie_node_t *ptrie,
    424                                     trie_node_t *trie,
    425                                     trie_traverse_states_e_t *state,
    426                                     trie_callback_ext_f cb,
    427                                     void *user_data)
    428 {
    429     int rv = SOC_E_NONE;
    430     trie_node_t *ori_ptrie = ptrie;
    431     trie_node_t *lc, *rc;
    432     node_type_e_t trie_type;
    433     if (trie == NULL) {
    434         return SOC_E_NONE;
    435     }
    436 
    437     assert(!ptrie || ptrie->type == PAYLOAD);
    438 
    439     /* Change the ptrie as trie if applicable */
    440     if (trie->type == PAYLOAD) {
    441         ptrie = trie;
    442     }
    443 
    444     /* During the callback, a trie node can be deleted or inserted.
    445      * For a deleted node, its internal parent could also be deleted, thus to
    446      * make it safe we should record rc.
    447      */
    448     trie_type = trie->type;
    449     lc = trie->child[0].child_node;
    450     rc = trie->child[1].child_node;
    451 
    452     if (SOC_SUCCESS(rv)) {
    453         rv = _trie_postorder_traverse2(ptrie, lc, state, cb, user_data);
    454         TRIE_TRAVERSE_STOP(*state, rv);
    455     }
    456     if (SOC_SUCCESS(rv)) {
    457         rv = _trie_postorder_traverse2(ptrie, rc, state, cb, user_data);
    458         TRIE_TRAVERSE_STOP(*state, rv);
    459     }
    460     if (SOC_SUCCESS(rv)) {
    461         if (trie_type == PAYLOAD) {
    462             rv = cb(ori_ptrie, trie, state, user_data);
    463         }
    464     }
    465     return rv;
    466 }
    467 
    468 STATIC int _trie_inorder_traverse2(trie_node_t *ptrie,
    469                                    trie_node_t *trie,
    470                                    trie_traverse_states_e_t *state,
    471                                    trie_callback_ext_f cb,
    472                                    void *user_data)
    473 {
    474     int rv = SOC_E_NONE;
    475     trie_node_t *rc = NULL;
    476     trie_node_t *ori_ptrie = ptrie;
    477 
    478     if (trie == NULL) {
    479         return SOC_E_NONE;
    480     }
    481 
    482     assert(!ptrie || ptrie->type == PAYLOAD);
    483 
    484     /* Change the ptrie as trie if applicable */
    485     if (trie->type == PAYLOAD) {
    486         ptrie = trie;
    487     }
    488 
    489     rv = _trie_inorder_traverse2(ptrie, trie->child[0].child_node, state, cb, user_data);
    490     TRIE_TRAVERSE_STOP(*state, rv);
    491 
    492     /* make the trie delete safe */
    493     rc = trie->child[1].child_node;
    494 
    495     if (SOC_SUCCESS(rv)) {
    496         if (trie->type == PAYLOAD) {
    497             rv = cb(ptrie, trie, state, user_data);
    498             TRIE_TRAVERSE_STOP(*state, rv);
    499             /* make the ptrie delete safe */
    500             if (*state == TRIE_TRAVERSE_STATE_DELETED) {
    501                 ptrie = ori_ptrie;
    502             }
    503         }
    504     }
    505 
    506     if (SOC_SUCCESS(rv)) {
    507         rv = _trie_inorder_traverse2(ptrie, rc, state, cb, user_data);
    508     }
    509     return rv;
    510 }
    511 
    512 
    513 STATIC int _trie_traverse2(trie_node_t *trie, trie_callback_ext_f cb,
    514                            void *user_data,  trie_traverse_order_e_t order,
    515                            trie_traverse_states_e_t *state)
    516 {
    517     int rv = SOC_E_NONE;
    518 
    519     switch(order) {
    520         case _TRIE_PREORDER_TRAVERSE:
    521             rv = _trie_preorder_traverse2(NULL, trie, state, cb, user_data);
    522             break;
    523         case _TRIE_POSTORDER_TRAVERSE:
    524             rv = _trie_postorder_traverse2(NULL, trie, state, cb, user_data);
    525             break;
    526         case _TRIE_INORDER_TRAVERSE:
    527             rv = _trie_inorder_traverse2(NULL, trie, state, cb, user_data);
    528             break;
    529         default:
    530             assert(0);
    531     }
    532 
    533     return rv;
    534 }
    535 
    536 /*
    537  * Function:
    538  *     trie_traverse2
    539  * Purpose:
    540  *     Traverse the trie (PAYLOAD) & call the extended application callback
    541  *     which has current node's PAYLOAD parent node with user data.
    542  */
    543 int trie_traverse2(trie_t *trie, trie_callback_ext_f cb,
    544                    void *user_data, trie_traverse_order_e_t order)
    545 {
    546     trie_traverse_states_e_t state = TRIE_TRAVERSE_STATE_NONE;
    547 
    548     if (order < _TRIE_PREORDER_TRAVERSE ||
    549         order >= _TRIE_TRAVERSE_MAX || !cb) return SOC_E_PARAM;
    550 
    551     if (trie == NULL) {
    552         return SOC_E_NONE;
    553     } else {
    554         return _trie_traverse2(trie->trie, cb, user_data, order, &state);
    555     }
    556 }
    557 
    558 
    559 
    560 typedef struct trie_list_s {
    561     trie_node_t *node;
    562     struct trie_list_s *next;
    563 } trie_list_t;
    564 
    565 #ifdef REPART_DEBUG
    566 int repart_debug = 0;
    567 trie_t *repart_trie = (trie_t *) 0xFFFFFFFF;
    568 #endif
    569 
    570 STATIC int _trie_repartition(trie_node_t *ptrie,
    571                              trie_node_t *trie,
    572                              trie_traverse_states_e_t *state,
    573                              trie_repartition_callback_f cb,
    574                              void *user_data,
    575                              trie_list_t **ptrie_list_in_out,
    576                              int level,
    577                              int *repart_count,
    578                              int *merge_count)
    579 {
    580     int rv = SOC_E_NONE;
    581     node_type_e_t   curr_trie_type;
    582     trie_node_t *rc = NULL;
    583     trie_node_t *new_ptrie = NULL;       /* new ptrie from callback, to be added to list. */
    584     trie_node_t *further_ptrie = NULL;   /* ptrie for recursion */
    585     trie_node_t *latest_ptrie = NULL;    /* ptrie for callback */
    586     trie_list_t *ptrie_list = NULL;      /* always the update-to-date ptrie list */
    587     trie_list_t *ptrie_list_next = NULL; /* for delete safe */
    588     trie_list_t *new_ptrie_list = NULL;  
    589     trie_list_t *l_ptrie_list = NULL;    /* ptrie list from left child */
    590     trie_list_t *r_ptrie_list = NULL;    /* ptrie list from right child */
    591     trie_list_t *ptrie_tail = NULL;      /* ptrie list tail */
    592     trie_list_t *r_ptrie_tail = NULL;    /* right ptrie list tail */
    593     trie_list_t *l_ptrie_tail = NULL;    /* left ptrie list tail */
    594     trie_list_t *ptrie_list_iter = NULL;
    595     int curr_trie_count;
    596     int trc = 0, lrc = 0, rrc = 0;      /* repartition counts */
    597     int tmc = 0, lmc = 0, rmc = 0;      /* merge counts */
    598     int tmp = 0;
    599 #ifdef REPART_DEBUG
    600     int lvl;
    601 #endif
    602     int l_prune_count = 0, r_prune_count = 0;   /* pruning counts */
    603     int l_stay_count = 0, r_stay_count = 0;     /* staying counts */
    604     if (trie == NULL) {
    605         return SOC_E_NONE;
    606     }
    607 
    608     /* assert(!ptrie || ptrie->type == PAYLOAD); */
    609 
    610     /* During the callback, a trie node can be deleted or inserted.
    611      * For a deleted node, its internal parent could also be deleted, thus to
    612      * make it safe we should record rc. 
    613      */
    614     curr_trie_type  = trie->type;
    615     curr_trie_count = trie->count;
    616     rc = trie->child[1].child_node;
    617 
    618     if (ptrie_list_in_out) {
    619         ptrie_list = *ptrie_list_in_out;
    620 
    621         /* Set tail */
    622         ptrie_tail = ptrie_list;
    623         if (ptrie_tail) {
    624             while(ptrie_tail->next) {
    625                 ptrie_tail = ptrie_tail->next;
    626             }
    627         }
    628     }
    629 #ifdef REPART_DEBUG
    630     if (repart_debug) {
    631         lvl = level;
    632         while(lvl) {
    633             LOG_CLI((BSL_META("%x  "),level - lvl));
    634             lvl--;
    635         }
    636         LOG_CLI(("#Ptrie %p, trie %p\n", ptrie, trie));
    637     }
    638 #endif
    639 
    640 #define KEEP_OP >=
    641 #define PRUNE_OP <
    642 
    643     if (curr_trie_type == PAYLOAD) {
    644         further_ptrie = trie;
    645     } else if (ptrie_list) {
    646         further_ptrie = ptrie_tail->node;
    647         /* assert(ptrie_tail->node->count <= ptrie->count); */
    648     } else {
    649         further_ptrie = ptrie;
    650     }
    651 
    652     rv = _trie_repartition(further_ptrie, trie->child[0].child_node,
    653                            state, cb, user_data,
    654                            (curr_trie_type == PAYLOAD) ? NULL : &l_ptrie_list, level+1, &lrc, &lmc);
    655 
    656 
    657     /* Note, the ptrie_list could be updated */
    658     TRIE_TRAVERSE_STOP(*state, rv);
    659 
    660     /* Somehow, the _trie_repartition may get us some new payload nodes,
    661      * these new payload nodes can be many, and they can be lower than the trie, 
    662      * or higher than it, but all must be lower than ptrie. The child cannot
    663      * decide status of each, only the current node can.
    664      */
    665 
    666     /* Prune unnecessary heads in the list (assuming the lower/longer comes first)*/
    667     tmc += lmc;
    668 
    669     l_prune_count = 0;
    670     l_stay_count = 0;
    671     l_ptrie_tail = NULL;
    672     ptrie_list_iter = l_ptrie_list;
    673 #ifdef REPART_DEBUG
    674     if (repart_debug) {
    675         if (l_ptrie_list) {
    676             lvl = level;
    677             while(lvl) {
    678                 LOG_CLI((BSL_META("%x  "),level - lvl));
    679                 lvl--;
    680             }
    681 
    682             LOG_CLI(("After LC Pruning:"));
    683             while (ptrie_list_iter) {
    684                 ptrie_list_next = ptrie_list_iter->next;
    685                 if (ptrie_list_iter->node->count KEEP_OP (curr_trie_count - tmc - l_stay_count)) {
    686                     l_ptrie_tail = ptrie_list_iter;
    687                     l_stay_count++;
    688                     assert(l_prune_count == 0);
    689                 } else {
    690                     l_prune_count++;
    691                     LOG_CLI(("%p  ", ptrie_list_iter->node));
    692                     sal_free(ptrie_list_iter);
    693 
    694                 }
    695                 ptrie_list_iter = ptrie_list_next;
    696             }
    697             if (l_ptrie_tail) {
    698                 l_ptrie_tail->next = NULL;
    699             } else {
    700                 l_ptrie_list = NULL;
    701             }
    702 
    703             LOG_CLI(("\n"));
    704 
    705             ptrie_list_iter = l_ptrie_list;
    706             lvl = level;
    707             while(lvl) {
    708                 LOG_CLI((BSL_META("%x  "),level - lvl));
    709                 lvl--;
    710             }
    711             LOG_CLI(("After LC Pruned: "));
    712             while(ptrie_list_iter) {
    713                 LOG_CLI(("%p -> ", ptrie_list_iter->node));
    714                 ptrie_list_iter = ptrie_list_iter->next;
    715             }
    716             LOG_CLI(("NULL \n"));
    717         }
    718     } else
    719 #endif
    720     {
    721         while (ptrie_list_iter) {
    722             ptrie_list_next = ptrie_list_iter->next;
    723             if (ptrie_list_iter->node->count KEEP_OP (curr_trie_count - tmc - l_stay_count)) {
    724                 l_ptrie_tail = ptrie_list_iter;
    725                 l_stay_count++;
    726                 /* assert(l_prune_count == 0); */
    727             } else {
    728                 l_prune_count++;
    729                 sal_free(ptrie_list_iter);
    730             }
    731             ptrie_list_iter = ptrie_list_next;
    732         }
    733         if (l_ptrie_tail) {
    734             l_ptrie_tail->next = NULL;
    735         } else {
    736             l_ptrie_list = NULL;
    737         }
    738     }
    739 
    740     lrc = lrc - l_prune_count;
    741     /* assert(lrc == l_stay_count); */
    742 
    743     trc += lrc;
    744 
    745     if (l_ptrie_list) {
    746         if (ptrie_list) {
    747             ptrie_tail->next = l_ptrie_list;
    748         } else {
    749             ptrie_list = l_ptrie_list;
    750         }
    751 
    752         /* Reset tail */
    753         ptrie_tail = l_ptrie_tail;
    754     }
    755 
    756     if (curr_trie_type == PAYLOAD) {
    757         further_ptrie = trie;
    758     } else if (ptrie_list) {
    759         further_ptrie = ptrie_tail->node;
    760         /* assert(ptrie_tail->node->count <= ptrie->count); */
    761     } else {
    762         further_ptrie = ptrie;
    763     }
    764 
    765     /* One important thing to notice is that after done with left child trie,
    766      * the current node (trie) could be deleted, but, the right child trie won't
    767      * be deleted. It's because that the internal node are allcoated because of
    768      * its children, not because of its parent. Despite of that, the skip length
    769      * and skip addr of the right child could be modified.
    770      */
    771 
    772     if (SOC_SUCCESS(rv)) {
    773         rv = _trie_repartition(further_ptrie, rc, state, cb, user_data,
    774                                (curr_trie_type == PAYLOAD) ? NULL : &r_ptrie_list,
    775                                level+1, &rrc, &rmc);
    776 
    777         TRIE_TRAVERSE_STOP(*state, rv);
    778         tmc += rmc;
    779 
    780         /* Prune unnecessary heads in the list (assuming the lower/longer comes first)*/
    781         r_prune_count = 0;
    782         r_stay_count = 0;
    783         r_ptrie_tail = NULL;
    784         ptrie_list_iter = r_ptrie_list;
    785 #ifdef REPART_DEBUG
    786         if (repart_debug) {
    787             if (r_ptrie_list) {
    788                 lvl = level;
    789                 while(lvl) {
    790                     LOG_CLI((BSL_META("%x  "),level - lvl));
    791                     lvl--;
    792                 }
    793 
    794                 LOG_CLI(("After RC Pruning:"));
    795                 while (ptrie_list_iter) {
    796                     ptrie_list_next = ptrie_list_iter->next;
    797                     if (ptrie_list_iter->node->count KEEP_OP
    798                         (curr_trie_count - tmc - lrc - r_stay_count)) {
    799                         r_ptrie_tail = ptrie_list_iter;
    800                         r_stay_count++;
    801                         assert(r_prune_count == 0);
    802                     } else {
    803                         r_prune_count++;
    804                         LOG_CLI(("%p  ", ptrie_list_iter->node));
    805                         sal_free(ptrie_list_iter);
    806                     }
    807                     ptrie_list_iter = ptrie_list_next;
    808                 }
    809                 if (r_ptrie_tail) {
    810                     r_ptrie_tail->next = NULL;
    811                 } else {
    812                     /* whole list cleared */
    813                     r_ptrie_list = NULL;
    814                 }
    815 
    816                 LOG_CLI(("\n"));
    817 
    818                 ptrie_list_iter = r_ptrie_list;
    819                 lvl = level;
    820                 while(lvl) {
    821                     LOG_CLI((BSL_META("%x  "),level - lvl));
    822                     lvl--;
    823                 }
    824                 LOG_CLI(("After RC Pruned: "));
    825                 while(ptrie_list_iter) {
    826                     LOG_CLI(("%p -> ", ptrie_list_iter->node));
    827                     ptrie_list_iter = ptrie_list_iter->next;
    828                 }
    829                 LOG_CLI(("NULL \n"));
    830             }
    831         } else
    832 #endif
    833         {
    834             while (ptrie_list_iter) {
    835                 ptrie_list_next = ptrie_list_iter->next;
    836                 if (ptrie_list_iter->node->count KEEP_OP
    837                     (curr_trie_count - tmc - lrc - r_stay_count)) {
    838                     r_ptrie_tail = ptrie_list_iter;
    839                     r_stay_count++;
    840                     /* assert(r_prune_count == 0); */
    841                 } else {
    842                     r_prune_count++;
    843                     sal_free(ptrie_list_iter);
    844 
    845                 }
    846                 ptrie_list_iter = ptrie_list_next;
    847             }
    848             if (r_ptrie_tail) {
    849                 r_ptrie_tail->next = NULL;
    850             } else {
    851                 /* whole list cleared */
    852                 r_ptrie_list = NULL;
    853             }
    854         }
    855 
    856         rrc = rrc - r_prune_count;
    857         /* assert(rrc == r_stay_count); */
    858 
    859         trc += rrc;
    860 
    861         if (r_ptrie_list) {
    862             if (ptrie_list) {
    863                 ptrie_tail->next = r_ptrie_list;
    864             } else {
    865                 ptrie_list = r_ptrie_list;
    866             }
    867             /* Reset tail */
    868             ptrie_tail = r_ptrie_tail;
    869         }
    870 
    871     }
    872 
    873     if (SOC_SUCCESS(rv) && curr_trie_type == PAYLOAD) {
    874         /* Get the latest ptrie, could be from the list or the orig ptre */
    875         if (ptrie_list) {
    876             latest_ptrie = ptrie_tail->node;
    877             /* assert(ptrie_tail->node->count <= ptrie->count); */
    878         } else {
    879             latest_ptrie = ptrie;
    880         }
    881 
    882         /* If curr_trie_type is payload, then trie must not be deleted */
    883         rv = cb(latest_ptrie, trie, state, user_data, &new_ptrie);
    884 
    885         /* a new ptrie generated, add to the list as tail */
    886         if (new_ptrie) {
    887             new_ptrie_list = sal_alloc(sizeof(trie_list_t), "trie list");
    888             sal_memset(new_ptrie_list, 0, sizeof(trie_list_t));
    889             new_ptrie_list->node = new_ptrie;
    890 
    891             if (ptrie_list) {
    892                 ptrie_tail->next = new_ptrie_list;
    893                 ptrie_tail = new_ptrie_list;
    894             } else {
    895                 ptrie_list = new_ptrie_list;
    896             }
    897 
    898 #ifdef REPART_DEBUG
    899             if (repart_debug) {
    900                 lvl = level;
    901                 while(lvl) {
    902                     LOG_CLI((BSL_META("%x  "),level - lvl));
    903                     lvl--;
    904                 }
    905 
    906                 LOG_CLI(("New Head %p. Now: ", new_ptrie));
    907                 ptrie_list_iter = ptrie_list;
    908                 while(ptrie_list_iter) {
    909                     LOG_CLI(("%p -> ", ptrie_list_iter->node));
    910                     ptrie_list_iter = ptrie_list_iter->next;
    911                 }
    912                 LOG_CLI(("NULL. Updated trie:\n"));
    913                 trie_dump(repart_trie, 0, 0);
    914             }
    915 #endif
    916             trc++;
    917         } else if (*state == TRIE_TRAVERSE_STATE_DELETED) {
    918 #ifdef REPART_DEBUG
    919             if (repart_debug) {
    920                 lvl = level;
    921                 while(lvl) {
    922                     LOG_CLI((BSL_META("%x  "),level - lvl));
    923                     lvl--;
    924                 }
    925 
    926                 LOG_CLI(("Node %p merged (deleted).  Updated trie:\n", trie));
    927                 trie_dump(repart_trie, 0, 0);
    928             }
    929 #endif
    930             tmc++;
    931         }
    932     }
    933 
    934     if (ptrie_list_in_out) {
    935         *ptrie_list_in_out = ptrie_list;
    936     } else {
    937         /* Done with repartition, clear list if any */
    938         tmp = 0;
    939         ptrie_list_iter = ptrie_list;
    940         while (ptrie_list_iter) {
    941             ptrie_list_next = ptrie_list_iter->next;
    942 #ifdef REPART_DEBUG
    943             if (repart_debug) {
    944                 lvl = level;
    945                 while(lvl) {
    946                     LOG_CLI((BSL_META("%x  "),level - lvl));
    947                     lvl--;
    948                 }
    949                 LOG_CLI((" Clear Prune %p . trc %d. \n",
    950                     ptrie_list_iter->node, trc));
    951 
    952                 if (ptrie_list_iter->node->count != (curr_trie_count - tmc - tmp)) {
    953                     LOG_CLI((" Count %d . Curr %d tmc %d tmp %d. \n",
    954                         ptrie_list_iter->node->count, curr_trie_count, tmc, tmp));
    955                     assert(0);
    956                 }
    957             }
    958 #endif
    959             sal_free(ptrie_list_iter);
    960             ptrie_list_iter = ptrie_list_next;
    961             tmp++;
    962         }
    963         /* assert(trc == tmp); */
    964         trc = 0;
    965     }
    966 
    967     /* assert(trc >= 0 && tmc >= 0); */
    968     if (repart_count) {
    969         *repart_count += trc;
    970     }
    971     if (merge_count) {
    972         *merge_count += tmc;
    973     }
    974     return rv;
    975 }
    976 /*
    977  * Function:
    978  *     trie_repartition
    979  * Purpose:
    980  *     Traverse the trie (PAYLOAD) & call the extended application callback
    981  *     which has current node's PAYLOAD parent node with user data.
    982  */
    983 int trie_repartition(trie_t *trie, trie_repartition_callback_f cb,
    984                      void *user_data, trie_traverse_order_e_t order)
    985 {
    986     trie_traverse_states_e_t state = TRIE_TRAVERSE_STATE_NONE;
    987 
    988     if (order < _TRIE_PREORDER_TRAVERSE ||
    989         order >= _TRIE_TRAVERSE_MAX || !cb) return SOC_E_PARAM;
    990 
    991 #ifdef REPART_DEBUG
    992     if (repart_debug) {
    993         repart_trie = trie;
    994         LOG_CLI(("=====================\n"));
    995         trie_dump(repart_trie, 0, 0);
    996     }
    997 #endif
    998     if (trie == NULL) {
    999         return SOC_E_NONE;
   1000     } else {
   1001         return _trie_repartition(NULL, trie->trie, &state, cb, user_data, NULL, 0, NULL, NULL);
   1002     }
   1003 }
   1004 
   1005 
   1006 
   1007 STATIC int _trie_preorder_iter_get_first(trie_node_t *node, trie_node_t **payload)
   1008 {
   1009     int rv = SOC_E_NONE;
   1010 
   1011     if (!payload) return SOC_E_PARAM;
   1012 
   1013     if (*payload != NULL) return SOC_E_NONE;
   1014 
   1015     if (node == NULL) {
   1016 	return SOC_E_NONE;
   1017     } else {
   1018         if (node->type == PAYLOAD) {
   1019             *payload = node;
   1020             return rv;
   1021         }
   1022     }
   1023 
   1024     if (SOC_SUCCESS(rv)) {
   1025         rv = _trie_preorder_iter_get_first(node->child[0].child_node, payload);
   1026     }
   1027     if (SOC_SUCCESS(rv)) {
   1028         rv = _trie_preorder_iter_get_first(node->child[1].child_node, payload);
   1029     }
   1030     return rv;
   1031 }
   1032 
   1033 /*
   1034  * Function:
   1035  *     trie_iter_get_first
   1036  * Purpose:
   1037  *     Traverse the trie & return pointer to first payload node
   1038  */
   1039 int trie_iter_get_first(trie_t *trie, trie_node_t **payload)
   1040 {
   1041     int rv = SOC_E_EMPTY;
   1042 
   1043     if (!trie || !payload) return SOC_E_PARAM;
   1044 
   1045     if (trie && trie->trie) {
   1046         *payload = NULL;
   1047         return _trie_preorder_iter_get_first(trie->trie, payload);
   1048     }
   1049 
   1050     return rv;
   1051 }
   1052 
   1053 STATIC int _trie_dump(trie_node_t *trie, trie_callback_f cb, 
   1054 		      void *user_data, unsigned int level)
   1055 {
   1056     if (trie == NULL) {
   1057 	return SOC_E_NONE;
   1058     } else {
   1059         unsigned int lvl = level;
   1060 	while(lvl) {
   1061 	    if (lvl == 1) {
   1062             LOG_CLI((BSL_META("|-")));
   1063 	    } else {
   1064             LOG_CLI((BSL_META("| ")));
   1065 	    }
   1066 	    lvl--; 
   1067 	}
   1068 
   1069         if (cb) {
   1070             cb(trie, user_data);
   1071         } else {
   1072             _print_trie_node(trie, NULL);
   1073         }
   1074     }
   1075 
   1076     _trie_dump(trie->child[0].child_node, cb, user_data, level+1);
   1077     _trie_dump(trie->child[1].child_node, cb, user_data, level+1);
   1078     return SOC_E_NONE;
   1079 }
   1080 
   1081 /*
   1082  * Function:
   1083  *     trie_dump
   1084  * Purpose:
   1085  *     Dumps the trie pre-order [root|left|child]
   1086  */
   1087 int trie_dump(trie_t *trie, trie_callback_f cb, void *user_data)
   1088 {
   1089     if (trie->trie) {
   1090 	return _trie_dump(trie->trie, cb, user_data, 0);
   1091     } else {
   1092         return SOC_E_PARAM;
   1093     }
   1094 }
   1095 
   1096 STATIC int _trie_search(trie_node_t *trie,
   1097 			unsigned int *key,
   1098 			unsigned int length,
   1099 			trie_node_t **payload,
   1100 			unsigned int *result_key,
   1101 			unsigned int *result_len,
   1102 			unsigned int dump,
   1103 			unsigned int find_pivot)
   1104 {
   1105     unsigned int lcp=0;
   1106     int bit=0, rv=SOC_E_NONE;
   1107 
   1108     if (!trie || (length && trie->skip_len && !key)) return SOC_E_PARAM;
   1109     if ((result_key && !result_len) || (!result_key && result_len)) return SOC_E_PARAM;
   1110 
   1111     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1112 
   1113     if (dump) {
   1114         _print_trie_node(trie, (unsigned int *)1);
   1115     }
   1116 
   1117     if (length > trie->skip_len) {
   1118         if (lcp == trie->skip_len) {
   1119             bit = (key[KEY_BIT2IDX(length - lcp)] & \
   1120                    (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1121             if (dump) {
   1122                 LOG_CLI((BSL_META(" Length: %d Next-Bit[%d] \n"), length, bit));
   1123             }
   1124 
   1125             if (result_key) {
   1126                 rv = _key_append(result_key, result_len, trie->skip_addr, trie->skip_len);
   1127                 if (SOC_FAILURE(rv)) return rv;
   1128             }
   1129 
   1130             /* based on next bit branch left or right */
   1131             if (trie->child[bit].child_node) {
   1132 
   1133                 if (result_key) {
   1134                     rv = _key_append(result_key, result_len, bit, 1);
   1135                     if (SOC_FAILURE(rv)) return rv;
   1136                 }
   1137 
   1138                 return _trie_search(trie->child[bit].child_node, key, 
   1139                                     length - lcp - 1, payload, 
   1140                                     result_key, result_len, dump, find_pivot);
   1141             } else {
   1142                 return SOC_E_NOT_FOUND; /* not found */
   1143             }
   1144         } else { 
   1145             return SOC_E_NOT_FOUND; /* not found */
   1146         }
   1147     } else if (length == trie->skip_len) {
   1148         if (lcp == length) {
   1149             if (dump) {
   1150                 LOG_CLI((BSL_META(": MATCH \n")));
   1151             }
   1152             *payload = trie;
   1153 	    if (trie->type != PAYLOAD && !find_pivot) {
   1154 		/* no assert here, possible during dbucket search
   1155 		 * due to 1* and 0* bucket search
   1156 		 */
   1157 		return SOC_E_NOT_FOUND;
   1158 	    }
   1159             if (result_key) {
   1160                 rv = _key_append(result_key, result_len, trie->skip_addr, trie->skip_len);
   1161                 if (SOC_FAILURE(rv)) return rv;
   1162             }
   1163             return SOC_E_NONE;
   1164         }
   1165         else return SOC_E_NOT_FOUND;
   1166     } else {
   1167         if (lcp == length && find_pivot) {
   1168             *payload = trie;
   1169             if (result_key) {
   1170                 rv = _key_append(result_key, result_len, trie->skip_addr, trie->skip_len);
   1171                 if (SOC_FAILURE(rv)) return rv;
   1172             }
   1173             return SOC_E_NONE;
   1174         }
   1175         return SOC_E_NOT_FOUND; /* not found */
   1176     }
   1177 }
   1178 
   1179 /*
   1180  * Function:
   1181  *     trie_search
   1182  * Purpose:
   1183  *     Search the given trie for exact match of provided prefix/length
   1184  *     If dump is set to 1 it traces the path as it traverses the trie 
   1185  */
   1186 int trie_search(trie_t *trie, 
   1187                 unsigned int *key, 
   1188                 unsigned int length,
   1189                 trie_node_t **payload)
   1190 {
   1191     if (trie->trie) {
   1192 	if (trie->v6_key) {
   1193 	    return _trie_v6_search(trie->trie, key, length, payload, NULL, NULL, 0, 0);	    
   1194 	} else {
   1195 	    return _trie_search(trie->trie, key, length, payload, NULL, NULL, 0, 0);
   1196 	}
   1197     } else {
   1198         return SOC_E_NOT_FOUND;
   1199     }
   1200 }
   1201 
   1202 /*
   1203  * Function:
   1204  *     trie_search_verbose
   1205  * Purpose:
   1206  *     Search the given trie for provided prefix/length
   1207  *     If dump is set to 1 it traces the path as it traverses the trie 
   1208  */
   1209 int trie_search_verbose(trie_t *trie, 
   1210                         unsigned int *key, 
   1211                         unsigned int length,
   1212                         trie_node_t **payload,
   1213                         unsigned int *result_key, 
   1214                         unsigned int *result_len)
   1215 {
   1216     if (trie->trie) {
   1217 	if (trie->v6_key) {
   1218 	    return _trie_v6_search(trie->trie, key, length, payload, result_key, result_len, 0, 0);
   1219 	} else {
   1220 	    return _trie_search(trie->trie, key, length, payload, result_key, result_len, 0, 0);
   1221 	}
   1222     } else {
   1223         return SOC_E_NOT_FOUND;
   1224     }
   1225 }
   1226 
   1227 /*
   1228  * Internal function for LPM match searching.
   1229  * callback on all payload nodes if cb != NULL.
   1230  */
   1231 STATIC int _trie_find_lpm(trie_node_t *trie,
   1232 			  unsigned int *key,
   1233 			  unsigned int length,
   1234 			  trie_node_t **payload,
   1235 			  trie_callback_f cb,
   1236 			  void *user_data,
   1237 			  unsigned int exclude_self)
   1238 {
   1239     unsigned int lcp=0;
   1240     int bit=0, rv=SOC_E_NONE;
   1241 
   1242     if (!trie || (length && trie->skip_len && !key)) return SOC_E_PARAM;
   1243 
   1244     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1245 
   1246     if ((length > trie->skip_len) && (lcp == trie->skip_len)) {
   1247         if (trie->type == PAYLOAD) {
   1248 	    /* lpm cases */
   1249 	    if (payload != NULL) {
   1250 		/* update lpm result */
   1251 		*payload = trie;
   1252 	    }
   1253 
   1254 	    if (cb != NULL) {
   1255 		/* callback with any nodes which is shorter and matches the prefix */
   1256 		rv = cb(trie, user_data);
   1257 		if (SOC_FAILURE(rv)) {
   1258 		    /* early bailout if there is error in callback handling */
   1259 		    return rv;
   1260 		}
   1261 	    }
   1262 	}
   1263 
   1264         bit = (key[KEY_BIT2IDX(length - lcp)] & \
   1265                (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1266 
   1267         /* based on next bit branch left or right */
   1268         if (trie->child[bit].child_node) {
   1269             return _trie_find_lpm(trie->child[bit].child_node, key, length - lcp - 1,
   1270 				  payload, cb, user_data, exclude_self);
   1271         } 
   1272     } else if ((length == trie->skip_len) && (lcp == length)) {
   1273         if (trie->type == PAYLOAD) {
   1274 	    /* exact match case */
   1275 	    if (payload != NULL && !exclude_self) {
   1276 		/* lpm is exact match */
   1277 		*payload = trie;
   1278 	    }
   1279 
   1280 	    if (cb != NULL) {
   1281 		/* callback with the exact match node */
   1282 		rv = cb(trie, user_data);
   1283 		if (SOC_FAILURE(rv)) {
   1284 		    /* early bailout if there is error in callback handling */
   1285 		    return rv;
   1286 		}		
   1287 	    }
   1288         }
   1289     }
   1290     return rv;
   1291 }
   1292 
   1293 /*
   1294  * Function:
   1295  *     trie_find_lpm
   1296  * Purpose:
   1297  *     Find the longest prefix matched with given prefix 
   1298  */
   1299 int trie_find_lpm(trie_t *trie, 
   1300                   unsigned int *key, 
   1301                   unsigned int length,
   1302                   trie_node_t **payload)
   1303 {
   1304     int rv = SOC_E_NONE;
   1305 
   1306     *payload = NULL;
   1307 
   1308     if (trie->trie) {
   1309         if (trie->v6_key) {
   1310             rv = _trie_v6_find_lpm(trie->trie, key, length, payload,
   1311                                    NULL, NULL, 0);
   1312         } else {
   1313             rv = _trie_find_lpm(trie->trie, key, length, payload,
   1314                                 NULL, NULL, 0);
   1315         }
   1316         if (*payload || (rv != SOC_E_NONE)) {
   1317             return rv;
   1318         }
   1319     }
   1320 
   1321     return SOC_E_NOT_FOUND;
   1322 }
   1323 
   1324 
   1325 
   1326 /*
   1327  * Function:
   1328  *     trie_find_lpm2
   1329  * Purpose:
   1330  *     Find the longest prefix matched with given prefix
   1331  */
   1332 int trie_find_lpm2(trie_t *trie,
   1333                    unsigned int *key,
   1334                    unsigned int length,
   1335                    trie_node_t **payload)
   1336 {
   1337     int rv = SOC_E_NONE;
   1338 
   1339     *payload = NULL;
   1340 
   1341     if (trie->trie) {
   1342         if (trie->v6_key) {
   1343             rv = _trie_v6_find_lpm(trie->trie, key, length, payload,
   1344                                    NULL, NULL, 1);
   1345         } else {
   1346             rv = _trie_find_lpm(trie->trie, key, length, payload,
   1347                                 NULL, NULL, 1);
   1348         }
   1349         if (*payload || (rv != SOC_E_NONE)) {
   1350             return rv;
   1351         }
   1352     }
   1353 
   1354     return SOC_E_NOT_FOUND;
   1355 }
   1356 
   1357 
   1358 /*
   1359  * Function:
   1360  *     trie_find_pm
   1361  * Purpose:
   1362  *     Find the prefix matched nodes with given prefix and callback
   1363  *     with specified callback funtion and user data
   1364  */
   1365 int trie_find_pm(trie_t *trie, 
   1366 		 unsigned int *key, 
   1367 		 unsigned int length,
   1368 		 trie_callback_f cb,
   1369 		 void *user_data)
   1370 {
   1371 
   1372     if (trie->trie) {
   1373 	if (trie->v6_key) {
   1374 	    return _trie_v6_find_lpm(trie->trie, key, length, NULL, cb, user_data, 0);	
   1375 	} else {
   1376 	    return _trie_find_lpm(trie->trie, key, length, NULL, cb, user_data, 0);
   1377 	}
   1378     }
   1379 
   1380     return SOC_E_NONE;
   1381 }
   1382 
   1383 /* trie->bpm format:
   1384  * bit 0 is for the pivot itself (longest)
   1385  * bit skip_len is for the trie branch leading to the pivot node (shortest)
   1386  * bits (0-skip_len) is for the routes in the parent node's bucket
   1387  */
   1388 int _trie_find_bpm(trie_node_t *trie,
   1389                    unsigned int *key,
   1390                    unsigned int length,
   1391 		   int *bpm_length)
   1392 {
   1393     unsigned int lcp=0, local_bpm_mask=0;
   1394     int bit=0, rv=SOC_E_NONE, local_bpm=0;
   1395 
   1396     if (!trie || (length && trie->skip_len && !key) ||
   1397         (length > _MAX_KEY_LEN_)) return SOC_E_PARAM;
   1398 
   1399     /* calculate number of matching msb bits */
   1400     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1401 
   1402     if (length > trie->skip_len) {
   1403 	if (lcp == trie->skip_len) {
   1404 	    /* fully matched and more bits to check, go down the trie */
   1405 	    bit = (key[KEY_BIT2IDX(length - lcp)] &			\
   1406 		   (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1407 	    
   1408 	    if (trie->child[bit].child_node) {
   1409 		rv = _trie_find_bpm(trie->child[bit].child_node, key, length - lcp - 1, bpm_length);
   1410 		/* on the way back, start bpm_length accumulation when encounter first non-0 bpm */
   1411 		if (*bpm_length >= 0) {
   1412 		    /* child node has non-zero bpm, just need to accumulate skip_len and branch bit */
   1413 		    *bpm_length += (trie->skip_len+1);
   1414 		    return rv;
   1415 		} else if (trie->bpm & BITMASK(trie->skip_len+1)) {
   1416 		    /* first non-zero bmp on the way back */
   1417 		    BITGETLSBSET(trie->bpm, trie->skip_len, local_bpm);
   1418 		    if (local_bpm >= 0) {
   1419                         *bpm_length = trie->skip_len - local_bpm;
   1420 		    }
   1421 		}
   1422 		/* on the way back, and so far all bpm are 0 */
   1423 		return rv;
   1424 	    }
   1425 	}
   1426     }
   1427 
   1428     /* no need to go further, we find whatever bits matched and 
   1429      * check that part of the bpm mask
   1430      */
   1431     /* coverity[large_shift : FALSE] */
   1432     local_bpm_mask = trie->bpm & (~(BITMASK(trie->skip_len-lcp)));
   1433     if (local_bpm_mask & BITMASK(trie->skip_len+1)) {
   1434 	/* first non-zero bmp on the way back */
   1435 	BITGETLSBSET(local_bpm_mask, trie->skip_len, local_bpm);
   1436 	if (local_bpm >= 0) {
   1437 	    *bpm_length = trie->skip_len - local_bpm;
   1438 	}
   1439     }
   1440 
   1441     return rv;
   1442 }
   1443 
   1444 /*
   1445  * Function:
   1446  *     trie_find_prefix_bpm
   1447  * Purpose:
   1448  *    Given a key/length return the Best prefix match length
   1449  *    key/bpm_pfx_len will be the BPM for the key/length
   1450  *    using the bpm info in the trie database
   1451  */
   1452 int trie_find_prefix_bpm(trie_t *trie, 
   1453                          unsigned int *key, 
   1454                          unsigned int length,
   1455                          unsigned int *bpm_pfx_len)
   1456 {
   1457     /* Return: SOC_E_EMPTY is not bpm bit is found */
   1458     int rv = SOC_E_EMPTY, bpm=0;
   1459 
   1460     if (!trie || !key || !bpm_pfx_len ) {
   1461 	return SOC_E_PARAM;
   1462     }
   1463 
   1464     bpm = -1;
   1465     if (trie->trie) {
   1466 	if (trie->v6_key) {
   1467 	    rv = _trie_v6_find_bpm(trie->trie, key, length, &bpm);
   1468 	} else {
   1469 	    rv = _trie_find_bpm(trie->trie, key, length, &bpm);
   1470 	}
   1471 
   1472 	if (SOC_SUCCESS(rv)) {
   1473             /* all bpm bits are 0 */
   1474             *bpm_pfx_len = (bpm < 0)? 0:(unsigned int)bpm;
   1475         }
   1476     }
   1477 
   1478     return rv;
   1479 }
   1480 
   1481 STATIC int _trie_bpm_mask_get(trie_node_t *trie,
   1482                     unsigned int *key,
   1483                     unsigned int length,
   1484                     unsigned int *bpm_mask)
   1485 {
   1486     unsigned int lcp=0, scratch=0;
   1487     int bit=0, rv=SOC_E_NONE;
   1488 
   1489     if (!trie || (length > _MAX_KEY_LEN_)) return SOC_E_PARAM;
   1490 
   1491     /* calculate number of matching msb bits */
   1492     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1493 
   1494     if (length > trie->skip_len) {
   1495         if (lcp == trie->skip_len) {
   1496             /* fully matched and more bits to check, go down the trie */
   1497             bit = (key[KEY_BIT2IDX(length - lcp)] & \
   1498                    (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1499 
   1500             if (trie->child[bit].child_node) {
   1501                 _bpm_append(bpm_mask, &scratch, trie->bpm, trie->skip_len + 1);
   1502                 rv = _trie_bpm_mask_get(trie->child[bit].child_node, key, length - lcp - 1, bpm_mask);
   1503                 return rv;
   1504             }
   1505         }
   1506     }
   1507 
   1508     _bpm_append(bpm_mask, &scratch, trie->bpm, trie->skip_len + 1);
   1509     return rv;
   1510 }
   1511 
   1512 /*
   1513  * Function:
   1514  *     trie_bpm_mask_get
   1515  * Purpose:
   1516  *     Get the bpm mask of target key. This key is already in the trie.
   1517  */
   1518 int trie_bpm_mask_get(trie_t *trie,
   1519                   unsigned int *key,
   1520                   unsigned int length,
   1521                   unsigned int *bpm_mask)
   1522 {
   1523     int rv = SOC_E_NONE;
   1524 
   1525     if (!trie || !key || !bpm_mask ) {
   1526         return SOC_E_PARAM;
   1527     }
   1528 
   1529     if (trie->trie) {
   1530         if (trie->v6_key) {
   1531             rv = _trie_v6_bpm_mask_get(trie->trie, key, length, bpm_mask);
   1532         } else {
   1533             rv = _trie_bpm_mask_get(trie->trie, key, length, bpm_mask);
   1534         }
   1535     }
   1536     return rv;
   1537 }
   1538 
   1539 /*
   1540  * Function:
   1541  *   _trie_skip_node_free
   1542  * Purpose:
   1543  *   Destroy a chain of trie_node_t that has the target node at the end.
   1544  *   The target node is not necessarily PAYLOAD type, but all nodes
   1545  *   on the chain except for the end must have only one branch.
   1546  * Input:
   1547  *   key      --  target key
   1548  *   length   --  target key length
   1549  *   free_end --  free
   1550  */
   1551 STATIC int _trie_skip_node_free(trie_node_t *trie,
   1552                                 unsigned int *key,
   1553                                 unsigned int length)
   1554 {
   1555     unsigned int lcp=0;
   1556     int bit=0, rv=SOC_E_NONE;
   1557 
   1558     if (!trie || (length && trie->skip_len && !key)) return SOC_E_PARAM;
   1559 
   1560     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1561 
   1562 
   1563     if (length > trie->skip_len) {
   1564 
   1565         if (lcp == trie->skip_len) {
   1566             bit = (key[KEY_BIT2IDX(length - lcp)] & \
   1567                     (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1568 
   1569             /* There should be only one branch on the chain until the end node */
   1570             if (!trie->child[0].child_node == !trie->child[1].child_node) {
   1571                 return SOC_E_PARAM;
   1572             }
   1573 
   1574             /* based on next bit branch left or right */
   1575             if (trie->child[bit].child_node) {
   1576                 rv = _trie_skip_node_free(trie->child[bit].child_node, key,
   1577                         length - lcp - 1);
   1578                 if (SOC_SUCCESS(rv)) {
   1579                     assert(trie->type == INTERNAL);
   1580                     sal_free(trie);
   1581                 }
   1582                 return rv;
   1583             } else {
   1584                 return SOC_E_NOT_FOUND; /* not found */
   1585             }
   1586         } else {
   1587             return SOC_E_NOT_FOUND; /* not found */
   1588         }
   1589     } else if (length == trie->skip_len) {
   1590         if (lcp == length) {
   1591             /* the end node is not necessarily type payload. */
   1592             /* Do not free the end */
   1593 
   1594             return SOC_E_NONE;
   1595         }
   1596         else return SOC_E_NOT_FOUND;
   1597     } else {
   1598         return SOC_E_NOT_FOUND; /* not found */
   1599     }
   1600 }
   1601 
   1602 
   1603 
   1604 /*
   1605  * Function:
   1606  *   _trie_skip_node_alloc
   1607  * Purpose:
   1608  *   create a chain of trie_node_t that has the payload at the end.
   1609  *   each node in the chain can skip upto _MAX_SKIP_LEN number of bits,
   1610  *   while the child pointer in the chain represent 1 bit. So totally
   1611  *   each node can absorb (_MAX_SKIP_LEN+1) bits.
   1612  * Input:
   1613  *   key      --  
   1614  *   bpm      --  
   1615  *   msb      --  
   1616  *   skip_len --  skip_len of the whole chain
   1617  *   payload  --  payload node we want to insert
   1618  *   count    --  child count
   1619  * Output:
   1620  *   node     -- return pointer of the starting node of the chain.
   1621  */
   1622 STATIC int _trie_skip_node_alloc(trie_node_t **node, 
   1623 				 unsigned int *key, 
   1624 				 /* bpm bit map if bpm management is required, passing null skips bpm management */
   1625 				 unsigned int *bpm, 
   1626 				 unsigned int msb, /* NOTE: valid msb position 1 based, 0 means skip0/0 node */
   1627 				 unsigned int skip_len,
   1628 				 trie_node_t *payload,
   1629 				 unsigned int count) /* payload count underneath - mostly 1 except some tricky cases */
   1630 {
   1631     int lsb=0, msbpos=0, lsbpos=0, bit=0, index;
   1632     trie_node_t *child = NULL, *skip_node = NULL;
   1633 
   1634     /* calculate lsb bit position, also 1 based */
   1635     lsb = ((msb)? msb + 1 - skip_len : msb);
   1636 
   1637     assert(((int)msb >= 0) && (lsb >= 0));
   1638 
   1639     if (!node || !key || !payload || msb > _MAX_KEY_LEN_ || msb < skip_len) return SOC_E_PARAM;
   1640 
   1641     if (msb) {
   1642         for (index = BITS2SKIPOFF(lsb), lsbpos = lsb - 1; index <= BITS2SKIPOFF(msb); index++) {
   1643 	    /* each loop process _MAX_SKIP_LEN number of bits?? */
   1644             if (lsbpos == lsb-1) {
   1645 		/* (lsbpos == lsb-1) is only true for first node (loop) here */
   1646                 skip_node = payload;
   1647             } else {
   1648 		/* other nodes need to be created */
   1649                 skip_node = sal_alloc(sizeof(trie_node_t), "trie_node");
   1650             }
   1651 
   1652 	    /* init memory */
   1653             sal_memset(skip_node, 0, sizeof(trie_node_t));
   1654 
   1655 	    /* calculate msb bit position of current chunk of bits we are processing */
   1656             msbpos = index * _MAX_SKIP_LEN_ - 1;
   1657             if (msbpos > msb-1) msbpos = msb-1;
   1658 
   1659 	    /* calculate the skip_len of the created node */
   1660             if (msbpos - lsbpos < _MAX_SKIP_LEN_) {
   1661                 skip_node->skip_len = msbpos - lsbpos + 1;
   1662             } else {
   1663                 skip_node->skip_len = _MAX_SKIP_LEN_;
   1664             }
   1665 
   1666             /* calculate the skip_addr (skip_length number of bits).
   1667 	     * skip might be skipping bits on 2 different words 
   1668              * if msb & lsb spawns 2 word boundary in worst case
   1669 	     */
   1670             if (BITS2WORDS(msbpos+1) != BITS2WORDS(lsbpos+1)) {
   1671                 /* pull snippets from the different words & fuse */
   1672                 skip_node->skip_addr = key[KEY_BIT2IDX(msbpos+1)] & MASK((msbpos+1) % _NUM_WORD_BITS_); 
   1673                 skip_node->skip_addr = SHL(skip_node->skip_addr, 
   1674                                            skip_node->skip_len - ((msbpos+1) % _NUM_WORD_BITS_),
   1675                                            _NUM_WORD_BITS_);
   1676                 skip_node->skip_addr |= SHR(key[KEY_BIT2IDX(lsbpos+1)],(lsbpos % _NUM_WORD_BITS_),_NUM_WORD_BITS_);
   1677             } else {
   1678                 skip_node->skip_addr = SHR(key[KEY_BIT2IDX(msbpos+1)], (lsbpos % _NUM_WORD_BITS_),_NUM_WORD_BITS_);
   1679             }
   1680 
   1681 	    /* set up the chain of child pointer, first node has no child since "child" was inited to NULL */
   1682             if (child) {
   1683                 skip_node->child[bit].child_node = child;
   1684             }
   1685 
   1686 	    /* calculate child pointer for next loop. NOTE: skip_addr has not been masked
   1687 	     * so we still have the child bit in the skip_addr here.
   1688 	     */
   1689             bit = (skip_node->skip_addr & SHL(1, skip_node->skip_len - 1,_MAX_SKIP_LEN_)) ? 1:0;
   1690 
   1691 	    /* calculate node type */
   1692             if (lsbpos == lsb-1) {
   1693 		/* first node is payload */
   1694                 skip_node->type = PAYLOAD;
   1695             } else {
   1696 		/* other nodes are internal nodes */
   1697                 skip_node->type = INTERNAL;
   1698             }
   1699 
   1700 	    /* all internal nodes will have the same "count" as the payload node */
   1701             skip_node->count = count;
   1702 
   1703             /* advance lsb to next word */
   1704             lsbpos += skip_node->skip_len;
   1705 
   1706 	    /* calculate bpm of the skip_node */
   1707             if (bpm) {
   1708 		if (lsbpos == _MAX_KEY_LEN_) {
   1709 		    /* parent node is 0/0, so there is no branch bit here */
   1710 		    skip_node->bpm = _key_get_bits(bpm, lsbpos, skip_node->skip_len, 1);
   1711 		} else {
   1712 		    skip_node->bpm = _key_get_bits(bpm, lsbpos+1, skip_node->skip_len+1, 1);
   1713 		}
   1714             }
   1715             
   1716             /* for all child nodes 0/1 is implicitly obsorbed on parent */
   1717             if (msbpos != msb-1) {
   1718 		/* msbpos == (msb-1) is only true for the first node */
   1719 		skip_node->skip_len--;
   1720 	    }
   1721             skip_node->bpm &= MASK(skip_node->skip_len + 1);
   1722             skip_node->skip_addr &= MASK(skip_node->skip_len);
   1723             child = skip_node;
   1724         } 
   1725     } else {
   1726 	/* skip_len == 0 case, create a payload node with skip_len = 0 and bpm should be 1 bits only
   1727 	 * bit 0 and bit "skip_len" are same bit (bit 0).
   1728 	 */
   1729         skip_node = payload;
   1730         sal_memset(skip_node, 0, sizeof(trie_node_t));  
   1731         skip_node->type = PAYLOAD;   
   1732         skip_node->count = count;
   1733         if (bpm) {
   1734             skip_node->bpm =  _key_get_bits(bpm,1,1,0);
   1735         }
   1736     }
   1737 
   1738     *node = skip_node;
   1739     return SOC_E_NONE;
   1740 }
   1741 
   1742 STATIC int _trie_insert(trie_node_t *trie, 
   1743 			unsigned int *key, 
   1744 			/* bpm bit map if bpm management is required, passing null skips bpm management */
   1745 			unsigned int *bpm, 
   1746 			unsigned int length,
   1747 			trie_node_t *payload, /* payload node */
   1748             trie_node_t **child, /* child pointer if the child is modified */
   1749             int child_count)
   1750 {
   1751     unsigned int lcp;
   1752     int rv=SOC_E_NONE, bit=0;
   1753     trie_node_t *node = NULL;
   1754 
   1755     if (!trie || (length && trie->skip_len && !key) ||
   1756         !payload || !child || (length > _MAX_KEY_LEN_))
   1757         return SOC_E_PARAM;
   1758 
   1759     *child = NULL;
   1760 
   1761     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1762 
   1763     /* insert cases:
   1764      * 1 - new key could be the parent of existing node
   1765      * 2 - new key could become the child of a existing node
   1766      * 3 - internal node could be inserted and the key becomes one of child 
   1767      * 4 - internal node is converted to a payload node */
   1768 
   1769     /* if the new key qualifies as new root do the inserts here */
   1770     if (lcp == length) { /* guaranteed: length < _MAX_SKIP_LEN_ */
   1771         if (trie->skip_len == lcp) {
   1772             if (trie->type != INTERNAL) {
   1773                 /* duplicate */ 
   1774                 return SOC_E_EXISTS;
   1775             } else { 
   1776                 /* change the internal node to payload node */
   1777                 _CLONE_TRIE_NODE_(payload,trie);
   1778                 sal_free(trie);
   1779                 payload->type = PAYLOAD;
   1780                 payload->count += child_count;
   1781                 *child = payload;
   1782 
   1783                 if (bpm) {
   1784                     /* bpm at this internal mode must be same as the inserted pivot */
   1785                     payload->bpm |= _key_get_bits(bpm, lcp+1, lcp+1, 1);
   1786                     /* implicity preserve the previous bpm & set bit 0 -myself bit */
   1787                 } 
   1788                 return SOC_E_NONE;
   1789             }
   1790         } else { /* skip length can never be less than lcp implcitly here */
   1791             /* this node is new parent for the old trie node */
   1792             /* lcp is the new skip length */
   1793             _CLONE_TRIE_NODE_(payload,trie);
   1794             *child = payload;
   1795 
   1796             bit = (trie->skip_addr & SHL(1,trie->skip_len - length - 1,_MAX_SKIP_LEN_)) ? 1 : 0;
   1797             trie->skip_addr &= MASK(trie->skip_len - length - 1);
   1798             trie->skip_len  -= (length + 1);   
   1799  
   1800             if (bpm) {
   1801                 trie->bpm &= MASK(trie->skip_len+1);   
   1802             }
   1803 
   1804             payload->skip_addr = (length > 0) ? key[KEY_BIT2IDX(length)] : 0;
   1805             payload->skip_addr &= MASK(length);
   1806             payload->skip_len  = length;
   1807             payload->child[bit].child_node = trie;
   1808             payload->child[!bit].child_node = NULL;
   1809             payload->type = PAYLOAD;
   1810             payload->count += child_count;
   1811 
   1812             if (bpm) {
   1813                 payload->bpm = SHR(payload->bpm, trie->skip_len + 1,_NUM_WORD_BITS_);
   1814                 payload->bpm |= _key_get_bits(bpm, payload->skip_len+1, payload->skip_len+1, 1);
   1815             }
   1816         }
   1817     } else if (lcp == trie->skip_len) {
   1818         /* key length is implictly greater than lcp here */
   1819         /* decide based on key's next applicable bit */
   1820         bit = (key[KEY_BIT2IDX(length-lcp)] & 
   1821                (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   1822 
   1823         if (!trie->child[bit].child_node) {
   1824             /* the key is going to be one of the child of existing node */
   1825             /* should be the child */
   1826             rv = _trie_skip_node_alloc(&node, key, bpm,
   1827 				       length-lcp-1, /* 0 based msbit position */
   1828 				       length-lcp-1,
   1829                        payload, child_count);
   1830             if (SOC_SUCCESS(rv)) {
   1831                 trie->child[bit].child_node = node;
   1832                 trie->count += child_count;
   1833             } else {
   1834                 LOG_CLI((BSL_META("\n Error on trie skip node allocaiton [%d]!!!!\n"),
   1835                          rv));
   1836             }
   1837         } else { 
   1838             rv = _trie_insert(trie->child[bit].child_node, 
   1839                               key, bpm, length - lcp - 1, 
   1840                               payload, child, child_count);
   1841             if (SOC_SUCCESS(rv)) {
   1842                 trie->count += child_count;
   1843                 if (*child != NULL) { /* chande the old child pointer to new child */
   1844                     trie->child[bit].child_node = *child;
   1845                     *child = NULL;
   1846                 }
   1847             }
   1848         }
   1849     } else {
   1850         trie_node_t *newchild = NULL;
   1851 
   1852         /* need to introduce internal nodes */
   1853         node = sal_alloc(sizeof(trie_node_t), "trie-node");
   1854         _CLONE_TRIE_NODE_(node, trie);
   1855 
   1856         rv = _trie_skip_node_alloc(&newchild, key, bpm,
   1857 				   ((lcp)?length-lcp-1:length-1),
   1858 				   length - lcp - 1,
   1859                    payload, child_count);
   1860         if (SOC_SUCCESS(rv)) {
   1861             bit = (key[KEY_BIT2IDX(length-lcp)] & 
   1862                    (1 << ((length - lcp - 1) % _NUM_WORD_BITS_))) ? 1: 0;
   1863 
   1864             node->child[!bit].child_node = trie;
   1865             node->child[bit].child_node = newchild;
   1866             node->type = INTERNAL;
   1867             node->skip_addr = SHR(trie->skip_addr,trie->skip_len - lcp,_MAX_SKIP_LEN_);
   1868             node->skip_len = lcp;
   1869             node->count += child_count;
   1870             if (bpm) {
   1871                 node->bpm = SHR(node->bpm, trie->skip_len - lcp, _MAX_SKIP_LEN_);
   1872             }
   1873             *child = node;
   1874             
   1875             trie->skip_addr &= MASK(trie->skip_len - lcp - 1);
   1876             trie->skip_len  -= (lcp + 1); 
   1877             if (bpm) {
   1878                 trie->bpm &= MASK(trie->skip_len+1);      
   1879             }
   1880         } else {
   1881             LOG_CLI((BSL_META("\n Error on trie skip node allocaiton [%d]!!!!\n"), rv));
   1882 	    sal_free(node);
   1883         }
   1884     }
   1885 
   1886     return rv;
   1887 }
   1888 
   1889 /*
   1890  * Function:
   1891  *     trie_insert
   1892  * Purpose:
   1893  *     Inserts provided prefix/length in to the trie
   1894  */
   1895 int trie_insert(trie_t *trie, 
   1896                 unsigned int *key, 
   1897                 unsigned int *bpm,
   1898                 unsigned int length, 
   1899                 trie_node_t *payload)
   1900 {
   1901     int rv = SOC_E_NONE;
   1902     trie_node_t *child=NULL;
   1903 
   1904     if (!trie) return SOC_E_PARAM;
   1905 
   1906     if (trie->trie == NULL) {
   1907         if (trie->v6_key) {
   1908 	        rv = _trie_v6_skip_node_alloc(&trie->trie, key, bpm, length, length, payload, 1);
   1909 	    } else {
   1910            rv = _trie_skip_node_alloc(&trie->trie, key, bpm, length, length, payload, 1);
   1911 	    }
   1912     } else {
   1913 	   if (trie->v6_key) {
   1914            rv = _trie_v6_insert(trie->trie, key, bpm, length, payload, &child, 1);
   1915 	   } else {
   1916            rv = _trie_insert(trie->trie, key, bpm, length, payload, &child, 1);
   1917 	   }
   1918        if (child) { /* chande the old child pointer to new child */
   1919            trie->trie = child;
   1920        }
   1921     }
   1922 
   1923     return rv;
   1924 }
   1925 
   1926 int _trie_fuse_child(trie_node_t *trie, int bit)
   1927 {
   1928     trie_node_t *child = NULL;
   1929     int rv = SOC_E_NONE;
   1930 
   1931     if (trie->child[0].child_node && trie->child[1].child_node) {
   1932         return SOC_E_PARAM;
   1933     } 
   1934 
   1935     bit = (bit > 0)?1:0;
   1936     child = trie->child[bit].child_node;
   1937 
   1938     if (child == NULL) {
   1939         return SOC_E_PARAM;
   1940     } else {
   1941         if (trie->skip_len + child->skip_len + 1 <= _MAX_SKIP_LEN_) {
   1942 
   1943             if (trie->skip_len == 0) trie->skip_addr = 0; 
   1944 
   1945             if (child->skip_len < _MAX_SKIP_LEN_) {
   1946                 trie->skip_addr = SHL(trie->skip_addr,child->skip_len + 1,_MAX_SKIP_LEN_);
   1947             }
   1948 
   1949             trie->skip_addr  |= SHL(bit,child->skip_len,_MAX_SKIP_LEN_);
   1950             child->skip_addr |= trie->skip_addr;
   1951             child->bpm       |= SHL(trie->bpm,child->skip_len+1,_MAX_SKIP_LEN_); 
   1952             child->skip_len  += trie->skip_len + 1;
   1953 
   1954             /* do not free payload nodes as they are user managed */
   1955             if (trie->type == INTERNAL) {
   1956                 sal_free(trie);
   1957             }
   1958         }
   1959     }
   1960 
   1961     return rv;
   1962 }
   1963 
   1964 STATIC int _trie_delete(trie_node_t *trie, 
   1965 			unsigned int *key,
   1966 			unsigned int length,
   1967 			trie_node_t **payload,
   1968 			trie_node_t **child)
   1969 {
   1970     unsigned int lcp;
   1971     int rv=SOC_E_NONE, bit=0;
   1972     trie_node_t *node = NULL;
   1973 
   1974     /* our algorithm should return before the length < 0, so this means
   1975      * something wrong with the trie structure. Internal error?
   1976      */
   1977     if (!trie || (length && trie->skip_len && !key) ||
   1978         !payload || !child || (length > _MAX_KEY_LEN_)) {
   1979 	return SOC_E_PARAM;
   1980     }
   1981 
   1982     *child = NULL;
   1983 
   1984     /* check a section of key, return the number of matched bits and value of next bit */
   1985     lcp = lcplen(key, length, trie->skip_addr, trie->skip_len);
   1986 
   1987     if (length > trie->skip_len) {
   1988 
   1989         if (lcp == trie->skip_len) {
   1990 
   1991             bit = (key[KEY_BIT2IDX(length-lcp)] & 
   1992                    (1 << ((length - lcp -1) % _NUM_WORD_BITS_))) ? 1:0;
   1993 
   1994             /* based on next bit branch left or right */
   1995             if (trie->child[bit].child_node) {
   1996 
   1997 	        /* has child node, keep searching */
   1998                 rv = _trie_delete(trie->child[bit].child_node, key, length - lcp - 1, payload, child);
   1999 
   2000 	        if (rv == SOC_E_BUSY) {
   2001 
   2002                     trie->child[bit].child_node = NULL; /* sal_free the child */
   2003                     rv = SOC_E_NONE;
   2004                     trie->count--;
   2005 
   2006                     if (trie->type == INTERNAL) {
   2007 
   2008                         bit = (bit==0)?1:0;
   2009 
   2010                         if (trie->child[bit].child_node == NULL) {
   2011                             /* parent and child connected, sal_free the middle-node itself */
   2012                             sal_free(trie);
   2013                             rv = SOC_E_BUSY;
   2014                         } else {
   2015                             /* fuse the parent & child */
   2016                             if (trie->skip_len + trie->child[bit].child_node->skip_len + 1 <= 
   2017                                 _MAX_SKIP_LEN_) {
   2018                                 *child = trie->child[bit].child_node;
   2019                                 rv = _trie_fuse_child(trie, bit);
   2020                                 if (rv != SOC_E_NONE) {
   2021                                     *child = NULL;
   2022                                 }
   2023                             }
   2024                         }
   2025                     }
   2026 	        } else if (SOC_SUCCESS(rv)) {
   2027                     trie->count--;
   2028                     /* update child pointer if applicable */
   2029                     if (*child != NULL) {
   2030                         trie->child[bit].child_node = *child;
   2031                         *child = NULL;
   2032                     }
   2033                 }
   2034             } else {
   2035                 /* no child node case 0: not found */
   2036                 rv = SOC_E_NOT_FOUND; 
   2037             }
   2038 
   2039         } else { 
   2040 	    /* some bits are not matching, case 0: not found */
   2041             rv = SOC_E_NOT_FOUND;
   2042         }
   2043     } else if (length == trie->skip_len) {
   2044 	/* when length equal to skip_len, unless this is a payload node
   2045 	 * and it's an exact match (lcp == length), we can not found a match
   2046 	 */ 
   2047         if (!((lcp == length) && (trie->type == PAYLOAD))) {
   2048 	    rv = SOC_E_NOT_FOUND;
   2049 	} else {
   2050             /* payload node can be deleted */
   2051             /* if this node has 2 children update it to internal node */
   2052             rv = SOC_E_NONE;
   2053 
   2054             if (trie->child[0].child_node && trie->child[1].child_node ) {
   2055 		/* the node has 2 children, update it to internal node */
   2056                 _BITCLR(trie->bpm, 0);
   2057                 node = sal_alloc(sizeof(trie_node_t), "trie_node");
   2058                 _CLONE_TRIE_NODE_(node, trie);
   2059                 node->type = INTERNAL;
   2060                 node->count--;
   2061                 *child = node;
   2062             } else if (trie->child[0].child_node || trie->child[1].child_node ) {
   2063                 /* if this node has 1 children fuse the children with this node */
   2064                 bit = (trie->child[0].child_node) ? 0:1;
   2065                 trie->count--;
   2066                 if (trie->skip_len + trie->child[bit].child_node->skip_len + 1 <= _MAX_SKIP_LEN_) {
   2067                     /* we need to clear the bpm bit of itself before fusing with child */
   2068                     _BITCLR(trie->bpm, 0);
   2069 
   2070 		    /* able to fuse the node with its child node */
   2071                     *child = trie->child[bit].child_node;
   2072                     rv = _trie_fuse_child(trie, bit);
   2073                     if (rv != SOC_E_NONE) {
   2074                         *child = NULL;
   2075                     }
   2076                 } else {
   2077 		    /* convert it to internal node, we need to alloc new memory for internal nodes
   2078 		     * since the old payload node memory will be freed by caller
   2079 		     */
   2080                     /* we need to clear the bpm bit of itself before converting */
   2081                     _BITCLR(trie->bpm, 0);
   2082 
   2083                     node = sal_alloc(sizeof(trie_node_t), "trie_node");
   2084                     _CLONE_TRIE_NODE_(node, trie);
   2085                     node->type = INTERNAL;
   2086                     *child = node;
   2087                 }
   2088             } else {
   2089                 rv = SOC_E_BUSY;
   2090             }
   2091 
   2092             *payload = trie;
   2093         }
   2094     } else {
   2095 	/* key length is shorter, no match if it's internal node,
   2096 	 * will not exact match even if this is a payload node
   2097 	 */
   2098         rv = SOC_E_NOT_FOUND; /* case 0: not found */        
   2099     }
   2100 
   2101     return rv;
   2102 }
   2103 
   2104 /*
   2105  * Function:
   2106  *     trie_delete
   2107  * Purpose:
   2108  *     Deletes provided prefix/length in to the trie
   2109  */
   2110 int trie_delete(trie_t *trie,
   2111                 unsigned int *key,
   2112                 unsigned int length,
   2113                 trie_node_t **payload)
   2114 {
   2115     int rv = SOC_E_NONE;
   2116     trie_node_t *child = NULL;
   2117 
   2118     if (trie->trie) {
   2119 	if (trie->v6_key) {
   2120 	    rv = _trie_v6_delete(trie->trie, key, length, payload, &child);
   2121 	} else {
   2122 	    rv = _trie_delete(trie->trie, key, length, payload, &child);
   2123 	}
   2124         if (rv == SOC_E_BUSY) {
   2125             /* the head node of trie was deleted, reset trie pointer to null */
   2126             trie->trie = NULL;
   2127             rv = SOC_E_NONE;
   2128         } else if (rv == SOC_E_NONE && child != NULL) {
   2129             trie->trie = child;
   2130         }
   2131     } else {
   2132         rv = SOC_E_NOT_FOUND;
   2133     }
   2134     return rv;
   2135 }
   2136 
   2137 STATIC INLINE int
   2138 _trie_splitable(trie_node_t *trie, trie_node_t *child, int max_count, int max_split_count)
   2139 {
   2140 /*
   2141     * NOTE:
   2142     *  ABS(trie->count * 2 - max_count) actually means
   2143     *  ABS(trie->count - (max_count - trie->count))
   2144     * which means the count's distance to half depth of the bucket
   2145 */
   2146     int do_split = 0;
   2147     int half_count = (max_count + 1) >> 1;
   2148 
   2149     if (trie->count <= max_split_count && trie->count != max_count) {
   2150         if (child == NULL) {
   2151             do_split = 1;
   2152         } else if (trie->count >= half_count && child->count < half_count) {
   2153             do_split = 1;
   2154         } else if (trie->count == half_count && child->count == half_count) {
   2155             do_split = 1;
   2156         } else if (ABS(child->count * 2 - max_count) >
   2157                    ABS(trie->count * 2 - max_count)) {
   2158             do_split = 1;
   2159         }
   2160     }
   2161 
   2162     return do_split;
   2163 }
   2164 
   2165 /*
   2166  * Function:
   2167  *     trie_split
   2168  * Purpose:
   2169  *     Split the trie into 2 based on optimum pivot
   2170  * NOTE:
   2171  *     max_split_len -- split will make sure the split point
   2172  *                has a length shorter or equal to the max_split_len
   2173  *                unless this will cause a no-split (all prefixs
   2174  *                stays below the split point)
   2175  *     split_to_pair -- used only when the split point will be
   2176  *                used to create a pair of tries later (i.e: dbucket
   2177  *                pair. we assume the split point itself will always be
   2178  *                put into 0* trie if itself is a payload/prefix)
   2179  */
   2180 STATIC int _trie_split(trie_node_t  *trie,
   2181 		       unsigned int *pivot,
   2182 		       unsigned int *length,
   2183 		       unsigned int *split_count,
   2184 		       trie_node_t **split_node,
   2185 		       trie_node_t **child,
   2186 		       const unsigned int max_count,
   2187 		       const unsigned int max_split_len,
   2188 		       const int split_to_pair,
   2189 		       unsigned int *bpm,
   2190 		       trie_split_states_e_t *state,
   2191                const int max_split_count)
   2192 {
   2193     int bit=0, rv=SOC_E_NONE;
   2194 
   2195     if (!trie || !pivot || !length || !split_node || max_count == 0 || !state || max_split_count == 0) return SOC_E_PARAM;
   2196 
   2197     if (trie->child[0].child_node && trie->child[1].child_node) {
   2198         bit = (trie->child[0].child_node->count > 
   2199                trie->child[1].child_node->count) ? 0:1;
   2200     } else {
   2201         bit = (trie->child[0].child_node)?0:1;
   2202     }
   2203 
   2204     /* start building the pivot */
   2205     rv = _key_append(pivot, length, trie->skip_addr, trie->skip_len);
   2206     if (SOC_FAILURE(rv)) return rv;
   2207 
   2208     if (bpm) {
   2209         unsigned int scratch=0;
   2210         rv = _bpm_append(bpm, &scratch, trie->bpm, trie->skip_len+1);
   2211         if (SOC_FAILURE(rv)) return rv;        
   2212     }
   2213 
   2214     {
   2215 	/*
   2216 	 * split logic to make sure the split length is shorter than the
   2217 	 * requested max_split_len, unless we don't actully split the
   2218 	 * tree if we stop here.
   2219 	 * if (*length > max_split_len) && (trie->count != max_count) {
   2220 	 *    need to split at or above this node. might need to split the node in middle
   2221 	 * } else if ((ABS(child count*2 - max_count) > ABS(count*2 - max_count)) ||
   2222 	 *            ((*length == max_split_len) && (trie->count != max_count))) {
   2223 	 *    (the check above imply trie->count != max_count, so also imply *length < max_split_len)
   2224 	 *    need to split at this node.
   2225 	 * } else {
   2226 	 *    keep searching, will be better split at longer pivot.
   2227 	 * }
   2228 	 */
   2229 	if ((*length > max_split_len) && (trie->count != max_count)) {
   2230 	    /* the pivot is getting too long, we better split at this node for
   2231 	     * better bucket capacity efficiency if we can. We can split if 
   2232 	     * the trie node has a count != max_count, which means the 
   2233 	     * resulted new trie will not have all pivots (FULL)
   2234 	     */ 
   2235 	    if ((TRIE_SPLIT_STATE_PAYLOAD_SPLIT == *state) && 
   2236 		(trie->type == INTERNAL)) {
   2237 		*state = TRIE_SPLIT_STATE_PAYLOAD_SPLIT_DONE;
   2238 	    } else {
   2239 		if (((*length - max_split_len) > trie->skip_len) && (trie->skip_len == 0)) {
   2240 		    /* the length is longer than max_split_len, and the trie->skip_len is 0,
   2241 		     * so the best we can do is use the node as the split point
   2242 		     */
   2243 		    *split_node = trie;
   2244 		    *split_count = trie->count;
   2245 		    
   2246 		    *state = TRIE_SPLIT_STATE_PRUNE_NODES;
   2247 		    return rv;
   2248 		}
   2249 		
   2250 		/* we need to insert a node and use it as split point */
   2251 		*split_node = sal_alloc(sizeof(trie_node_t), "trie_node");
   2252 		sal_memset((*split_node), 0, sizeof(trie_node_t));
   2253 		(*split_node)->type = INTERNAL;
   2254 		(*split_node)->count = trie->count;
   2255 		
   2256 		if ((*length - max_split_len) > trie->skip_len) {
   2257 		    /* the length is longer than the max_split_len, and the trie->skip_len is
   2258 		     * shorter than the difference (max_split_len pivot is not covered by this 
   2259 		     * node but covered by its parent, the best we can do is split at the branch
   2260 		     * lead to this node. we insert a skip_len=0 node and use it as split point
   2261 		     */
   2262 		    (*split_node)->skip_len = 0;
   2263 		    (*split_node)->skip_addr = 0;
   2264 		    (*split_node)->bpm = (trie->bpm >> trie->skip_len);
   2265 		    
   2266 		    if (_BITGET(trie->skip_addr, (trie->skip_len-1))) {
   2267 			(*split_node)->child[1].child_node = trie;
   2268 		    } else {
   2269 			(*split_node)->child[0].child_node = trie;
   2270 		    }
   2271 		    
   2272 		    /* the split point is with length max_split_len */		
   2273 		    *length -= trie->skip_len;		
   2274 
   2275 		    /* update the current node to reflect the node inserted */
   2276 		    trie->skip_len = trie->skip_len - 1;
   2277 		} else {
   2278 		    /* the length is longer than the max_split_len, and the trie->skip_len is
   2279 		     * longer than the difference (max_split_len pivot is covered by this 
   2280 		     * node, we insert a node with length = max_split_len and use it as split point
   2281 		     */
   2282 		    (*split_node)->skip_len = trie->skip_len - (*length - max_split_len);
   2283 		    (*split_node)->skip_addr = (trie->skip_addr >> (*length - max_split_len));
   2284 		    (*split_node)->bpm = (trie->bpm >> (*length - max_split_len));
   2285 		    
   2286 		    if (_BITGET(trie->skip_addr, (*length-max_split_len-1))) {
   2287 			(*split_node)->child[1].child_node = trie;
   2288 		    } else {
   2289 			(*split_node)->child[0].child_node = trie;
   2290 		    }
   2291 		    
   2292 		    /* update the current node to reflect the node inserted */
   2293 		    trie->skip_len = *length - max_split_len - 1;
   2294 		    
   2295 		    /* the split point is with length max_split_len */
   2296 		    *length = max_split_len;
   2297 		}
   2298 		
   2299 		trie->skip_addr = trie->skip_addr & BITMASK(trie->skip_len);
   2300 		trie->bpm = trie->bpm & BITMASK(trie->skip_len + 1);
   2301 		
   2302 		/* there is no need to update the parent node's child_node pointer
   2303 		 * to the "trie" node since we will split here and the parent node's
   2304 		 * child_node pointer will be set to NULL later
   2305 		 */
   2306 		*split_count = trie->count;
   2307         if (bpm) {
   2308 		    rv = _key_shift_right(bpm, trie->skip_len+1);
   2309         }
   2310 		if (SOC_SUCCESS(rv)) {
   2311 		    rv = _key_shift_right(pivot, trie->skip_len+1);
   2312 		}
   2313 		*state = TRIE_SPLIT_STATE_PRUNE_NODES;
   2314 		return rv;
   2315 	    }
   2316 	} else if ( ((*length == max_split_len) && (trie->count != max_count) && trie->count <= max_split_count) ||
   2317                  _trie_splitable(trie, trie->child[bit].child_node, max_count, max_split_count)) {
   2318 	    /* 
   2319 	     * (1) when the node is at the max_split_len and if used as spliting point
   2320 	     * the resulted trie will not have all pivots (FULL). we should split
   2321 	     * at this node.
   2322 	     * (2) when the node is at the max_split_len and if the resulted trie
   2323 	     * will have all pivots (FULL), we fall through to keep searching
   2324 	     * (3) when the node is shorter than the max_split_len and the node
   2325 	     * has a more even pivot distribution compare to it's child, we
   2326          * can split at this node. The split count must be less than or
   2327          * equal to max_split_count.
   2328          * (4) when the node's count is only 1, we must split at this point.
   2329          *
   2330          * NOTE :
   2331 	     *  when trie->count == max_count, the above check will be FALSE
   2332 	     *  so here it guarrantees *length < max_split_len. We don't
   2333 	     *  need to further split this node.
   2334 	     */
   2335 	    *split_node = trie;
   2336 	    *split_count = trie->count;
   2337 	    
   2338 	    if ((TRIE_SPLIT_STATE_PAYLOAD_SPLIT == *state) && 
   2339 		(trie->type == INTERNAL)) {
   2340 		*state = TRIE_SPLIT_STATE_PAYLOAD_SPLIT_DONE;
   2341 	    } else {
   2342 		*state = TRIE_SPLIT_STATE_PRUNE_NODES;
   2343 		return rv;
   2344 	    }
   2345 	} else {
   2346 	    /* we can not split at this node, keep searching, it's better to 
   2347 	     * split at longer pivot
   2348 	     */
   2349 	    rv = _key_append(pivot, length, bit, 1);
   2350 	    if (SOC_FAILURE(rv)) return rv;
   2351 	    
   2352 	    rv = _trie_split(trie->child[bit].child_node, 
   2353 			     pivot, length,
   2354 			     split_count, split_node,
   2355 			     child, max_count, max_split_len,
   2356                  split_to_pair, bpm, state, max_split_count);
   2357 	}
   2358     }
   2359 
   2360     /* free up internal nodes if applicable */
   2361     switch(*state) {
   2362     case TRIE_SPLIT_STATE_PAYLOAD_SPLIT_DONE:
   2363          if (trie->type == PAYLOAD) {
   2364             *state = TRIE_SPLIT_STATE_PRUNE_NODES;
   2365             *split_node = trie;
   2366             *split_count = trie->count;
   2367         } else {
   2368             /* shift the pivot to right to ignore this internal node */
   2369             rv = _key_shift_right(pivot, trie->skip_len+1);
   2370             assert(*length >= trie->skip_len + 1);
   2371             *length -= (trie->skip_len + 1);
   2372         }
   2373         break;
   2374 
   2375     case TRIE_SPLIT_STATE_PRUNE_NODES:
   2376         if (trie->count == *split_count) {
   2377             /* if the split point has associate internal nodes they have to
   2378              * be cleaned up */
   2379             assert(trie->type == INTERNAL);
   2380             assert(!(trie->child[0].child_node && trie->child[1].child_node));
   2381             sal_free(trie);
   2382         } else {
   2383             assert(*child == NULL);
   2384             /* fuse with child if possible */
   2385             trie->child[bit].child_node = NULL;
   2386             bit = (bit==0)?1:0;
   2387             trie->count -= *split_count;
   2388 
   2389             /* optimize more */
   2390             if ((trie->type == INTERNAL) &&
   2391                 (trie->skip_len +
   2392                  trie->child[bit].child_node->skip_len + 1 <= _MAX_SKIP_LEN_)) {
   2393                 *child = trie->child[bit].child_node;
   2394                 rv = _trie_fuse_child(trie, bit);
   2395                 if (rv != SOC_E_NONE) {
   2396                     *child = NULL;
   2397                 }
   2398             }
   2399             *state = TRIE_SPLIT_STATE_DONE;
   2400         }
   2401         break;
   2402 
   2403     case TRIE_SPLIT_STATE_DONE:
   2404         /* adjust parent's count */
   2405         assert(*split_count > 0);
   2406         assert(trie->count >= *split_count);
   2407 
   2408         /* update the child pointer if child was pruned */
   2409         if (*child != NULL) {
   2410             trie->child[bit].child_node = *child;
   2411             *child = NULL;
   2412         }
   2413         trie->count -= *split_count;
   2414         break;
   2415 
   2416     default:
   2417         break;
   2418     }
   2419 
   2420     return rv;
   2421 }
   2422 
   2423 /*
   2424  * Function:
   2425  *     trie_split
   2426  * Purpose:
   2427  *     Split the trie into 2 based on optimum pivot
   2428  * Note:
   2429  *     we need to make sure the length is shorter than
   2430  *     the max_split_len (for capacity optimization) if
   2431  *     possible. We should ignore the max_split_len
   2432  *     if that will result into trie not spliting
   2433  */
   2434 int trie_split(trie_t *trie,
   2435                const unsigned int max_split_len,
   2436                const int split_to_pair,
   2437                unsigned int *pivot,
   2438                unsigned int *length,
   2439                trie_node_t **split_trie_root,
   2440                unsigned int *bpm,
   2441                uint8 payload_node_split,
   2442                const int max_split_count)
   2443 {
   2444     int rv = SOC_E_NONE;
   2445     unsigned int split_count=0, max_count=0;
   2446     trie_node_t *child = NULL, *node=NULL, clone;
   2447     trie_split_states_e_t state = TRIE_SPLIT_STATE_NONE;
   2448 
   2449     if (!trie || !pivot || !length || !split_trie_root) return SOC_E_PARAM;
   2450 
   2451     *length = 0;
   2452 
   2453     if (trie->trie) {
   2454 
   2455         if (payload_node_split) state = TRIE_SPLIT_STATE_PAYLOAD_SPLIT;
   2456 
   2457 	max_count = trie->trie->count;
   2458 
   2459 	if (trie->v6_key) {	    
   2460 	    sal_memset(pivot, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_144_));
   2461 	    if (bpm) {
   2462 		sal_memset(bpm, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_144_));
   2463 	    }
   2464 	    rv = _trie_v6_split(trie->trie, pivot, length, &split_count, split_trie_root,
   2465                  &child, max_count, max_split_len, split_to_pair, bpm, &state, max_split_count);
   2466 	} else {
   2467 	    sal_memset(pivot, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_48_));
   2468 	    if (bpm) {
   2469 		sal_memset(bpm, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_48_));
   2470 	    }
   2471 
   2472 	    rv = _trie_split(trie->trie, pivot, length, &split_count, split_trie_root,
   2473                  &child, max_count, max_split_len, split_to_pair, bpm, &state, max_split_count);
   2474 	}
   2475         if (SOC_SUCCESS(rv) && (TRIE_SPLIT_STATE_DONE == state)) {
   2476             /* adjust parent's count */
   2477             assert(split_count > 0);
   2478             if (trie->trie == NULL) {
   2479                 trie_t *c1, *c2;
   2480                 trie_init(48, &c1);
   2481                 trie_init(48, &c2);
   2482                 c1->trie = child;
   2483                 c2->trie = *split_trie_root;
   2484                 LOG_ERROR(BSL_LS_SOC_ALPM,
   2485                           (BSL_META("dumping the 2 child trees\n")));
   2486                 trie_dump(c1, 0, 0);
   2487                 trie_dump(c2, 0, 0);
   2488             }
   2489             /* update the child pointer if child was pruned */
   2490             if (child != NULL) {
   2491                 trie->trie = child;
   2492             }
   2493             assert(trie->trie->count >= split_count || (*split_trie_root)->count >= split_count);
   2494 
   2495             sal_memcpy(&clone, *split_trie_root, sizeof(trie_node_t));
   2496             child = *split_trie_root;
   2497 
   2498             /* take advantage of thie function by passing in internal or payload node whatever
   2499              * is the new root. If internal the function assumed it as payload node & changes type.
   2500              * But this method is efficient to reuse the last internal or payload node possible to
   2501              * implant the new pivot */
   2502 	    if (trie->v6_key) {	    
   2503 		rv = _trie_v6_skip_node_alloc(&node, pivot, NULL,
   2504 					      *length, *length,
   2505 					      child, child->count);
   2506 	    } else {
   2507 		rv = _trie_skip_node_alloc(&node, pivot, NULL,
   2508 					   *length, *length,
   2509 					   child, child->count);
   2510 	    }
   2511 
   2512             if (SOC_SUCCESS(rv)) {
   2513                 if (clone.type == INTERNAL) {
   2514                     child->type = INTERNAL; /* since skip alloc would have reset it to payload */
   2515                 }
   2516                 child->child[0].child_node = clone.child[0].child_node;
   2517                 child->child[1].child_node = clone.child[1].child_node;
   2518                 *split_trie_root = node;
   2519             }
   2520         } else {
   2521             LOG_CLI((BSL_META("!!!! Failed to split the trie error:%d state: %d trie_count %d!!!\n"),
   2522                      rv, state, max_count));
   2523         }
   2524     } else {
   2525         rv = SOC_E_PARAM;
   2526     }
   2527 
   2528     return rv;
   2529 }
   2530 
   2531 /*
   2532  * Function:
   2533  *     _trie_merge
   2534  * Purpose:
   2535  *     merge or fuse the child trie with parent trie
   2536  */
   2537 static int
   2538 _trie_merge(trie_node_t *parent_trie,
   2539             trie_node_t *child_trie,
   2540             unsigned int *pivot,
   2541             unsigned int length,
   2542             trie_node_t **new_parent)
   2543 {
   2544     int rv, child_count;
   2545     trie_node_t *child = NULL, clone;
   2546     unsigned int bpm[TAPS_MAX_KEY_SIZE_WORDS] = {0};
   2547     unsigned int child_pivot[BITS2WORDS(_MAX_KEY_LEN_)] = {0};
   2548     unsigned int child_length = 0;
   2549 
   2550     if (!parent_trie || length == 0 || !pivot || !new_parent || (length > _MAX_KEY_LEN_))
   2551         return SOC_E_PARAM;
   2552 
   2553     /*
   2554      * to do merge, there is one and only one condition:
   2555      * parent must cover the child
   2556      */
   2557 
   2558     /*
   2559      * child pivot could be an internal node, i.e., NOT_FOUND on search
   2560      * so check the out child instead of rv.
   2561      */
   2562     _trie_search(child_trie, pivot, length, &child, child_pivot, &child_length, 0, 1);
   2563 
   2564     /* The head of a bucket usually is the pivot of the bucket,
   2565      * but for some cases, where the pivot is an INTERNAL node,
   2566      * and it is fused with its child, then the pivot can no longer
   2567      * be found, but we can still search a head. The head can be
   2568      * payload (if this is the only payload head), or internal (if
   2569      * two payload head coexist).
   2570      */
   2571     if (child == NULL) {
   2572         return SOC_E_PARAM;
   2573     }
   2574 
   2575     _CLONE_TRIE_NODE_(&clone, child);
   2576 
   2577     if (child->type == PAYLOAD && child->bpm) {
   2578         _TAPS_SET_KEY_BIT(bpm, 0, TAPS_IPV4_KEY_SIZE);
   2579     }
   2580 
   2581     if (child != child_trie) {
   2582         rv = _trie_skip_node_free(child_trie, child_pivot, child_length);
   2583         if (rv < 0) {
   2584             return SOC_E_PARAM;
   2585         }
   2586     }
   2587 
   2588     /* Record the child count before being cleared */
   2589     child_count = child->count;
   2590 
   2591     /* Clear the info before insert, mainly it is to prevent previous non-zero
   2592      * count being erroneously included to calculation.
   2593      */
   2594     sal_memset(child, 0, sizeof(*child));
   2595 
   2596     /* merge happens on bucket trie, which usually does not need bpm */
   2597     rv = _trie_insert(parent_trie, child_pivot, bpm, child_length, child,
   2598                       new_parent, child_count);
   2599     if (rv < 0) {
   2600         return SOC_E_PARAM;
   2601     }
   2602 
   2603     /*
   2604      * child node, the inserted node, will be modified during insert,
   2605      * and it must be a leaf node of the parent trie without any child.
   2606      * The child node could be either payload or internal.
   2607      */
   2608     if (child->child[0].child_node || child->child[1].child_node) {
   2609         return SOC_E_PARAM;
   2610     }
   2611     if (clone.type == INTERNAL) {
   2612         child->type = INTERNAL;
   2613     }
   2614     child->child[0].child_node = clone.child[0].child_node;
   2615     child->child[1].child_node = clone.child[1].child_node;
   2616 
   2617     return SOC_E_NONE;
   2618 }
   2619 
   2620 
   2621 /*
   2622  * Function:
   2623  *     trie_merge
   2624  * Purpose:
   2625  *     merge or fuse the child trie with parent trie.
   2626  */
   2627 int trie_merge(trie_t *parent_trie,
   2628                trie_node_t *child_trie,
   2629                unsigned int *child_pivot,
   2630                unsigned int length)
   2631 {
   2632     int rv=SOC_E_NONE;
   2633     trie_node_t *child=NULL;
   2634 
   2635     if (!parent_trie) {
   2636         return SOC_E_PARAM;
   2637     }
   2638 
   2639     if (!child_trie) {
   2640         return SOC_E_NONE;
   2641     }
   2642 
   2643     if (parent_trie->trie == NULL) {
   2644         parent_trie->trie = child_trie;
   2645     } else {
   2646         if (parent_trie->v6_key) {
   2647             rv = _trie_v6_merge(parent_trie->trie, child_trie, child_pivot, length, &child);
   2648         } else {
   2649             rv = _trie_merge(parent_trie->trie, child_trie, child_pivot, length, &child);
   2650         }
   2651         if (child) {
   2652             /* The parent head can be changed if the new payload generates a
   2653              * new internal node, which then becomes the new head.
   2654              */
   2655              parent_trie->trie = child;
   2656         }
   2657     }
   2658 
   2659     return rv;
   2660 }
   2661 
   2662 
   2663 /*
   2664  * Function:
   2665  *     trie_split
   2666  * Purpose:
   2667  *     Split the trie into 2 such that the new sub trie covers given prefix/length.
   2668  * NOTE:
   2669  *     key, key_len    -- The given prefix/length
   2670  *     max_split_count -- The sub trie's max allowed count.
   2671  */
   2672 int
   2673 _trie_split2(trie_node_t *trie,
   2674              unsigned int *key,
   2675              unsigned int key_len,
   2676              unsigned int *pivot,
   2677              unsigned int *pivot_len,
   2678              unsigned int *split_count,
   2679              trie_node_t **split_node,
   2680              trie_node_t **child,
   2681              trie_split2_states_e_t *state,
   2682              const int max_split_count,
   2683              const int exact_same)
   2684 {
   2685     unsigned int lcp=0;
   2686     int bit=0, rv=SOC_E_NONE;
   2687 
   2688     if (!trie || !pivot || !pivot_len || !split_node || !state || max_split_count == 0) return SOC_E_PARAM;
   2689     /* start building the pivot */
   2690     rv = _key_append(pivot, pivot_len, trie->skip_addr, trie->skip_len);
   2691     if (SOC_FAILURE(rv)) return rv;
   2692 
   2693 
   2694     lcp = lcplen(key, key_len, trie->skip_addr, trie->skip_len);
   2695 
   2696     if (lcp == trie->skip_len) {
   2697         if (trie->count <= max_split_count &&
   2698             (!exact_same || (key_len - lcp) == 0)) {
   2699             *split_node = trie;
   2700             *split_count = trie->count;
   2701             if (trie->count < max_split_count) {
   2702                 *state = TRIE_SPLIT2_STATE_PRUNE_NODES;
   2703             }
   2704             return SOC_E_NONE;
   2705         }
   2706         if (key_len > lcp) {
   2707             bit = (key[KEY_BIT2IDX(key_len - lcp)] & \
   2708                     (1 << ((key_len - lcp - 1) % _NUM_WORD_BITS_))) ? 1:0;
   2709 
   2710             /* based on next bit branch left or right */
   2711             if (trie->child[bit].child_node) {
   2712                 /* we can not split at this node, keep searching, it's better to
   2713                  * split at longer pivot
   2714                  */
   2715                 rv = _key_append(pivot, pivot_len, bit, 1);
   2716                 if (SOC_FAILURE(rv)) return rv;
   2717 
   2718                 rv = _trie_split2(trie->child[bit].child_node,
   2719                                   key, key_len - lcp - 1,
   2720                                   pivot, pivot_len, split_count,
   2721                                   split_node, child, state,
   2722                                   max_split_count, exact_same);
   2723                 if (SOC_FAILURE(rv)) return rv;
   2724             }
   2725         }
   2726     }
   2727 
   2728     /* free up internal nodes if applicable */
   2729     switch(*state) {
   2730         case TRIE_SPLIT2_STATE_NONE: /* fail to split */
   2731             break;
   2732 
   2733         case TRIE_SPLIT2_STATE_PRUNE_NODES:
   2734             if (trie->count == *split_count) {
   2735                 /* if the split point has associate internal nodes they have to
   2736                  * be cleaned up */
   2737                 assert(trie->type == INTERNAL);
   2738                 /* at most one child */
   2739                 assert(!(trie->child[0].child_node && trie->child[1].child_node));
   2740                 /* at least one child */
   2741                 assert(trie->child[0].child_node || trie->child[1].child_node);
   2742                 sal_free(trie);
   2743             } else {
   2744                 assert(*child == NULL);
   2745                 /* fuse with child if possible */
   2746                 trie->child[bit].child_node = NULL;
   2747                 bit = (bit==0)?1:0;
   2748                 trie->count -= *split_count;
   2749 
   2750                 /* optimize more */
   2751                 if ((trie->type == INTERNAL) &&
   2752                         (trie->skip_len +
   2753                          trie->child[bit].child_node->skip_len + 1 <= _MAX_SKIP_LEN_)) {
   2754                     *child = trie->child[bit].child_node;
   2755                     rv = _trie_fuse_child(trie, bit);
   2756                     if (rv != SOC_E_NONE) {
   2757                         *child = NULL;
   2758                     }
   2759                 }
   2760                 *state = TRIE_SPLIT2_STATE_DONE;
   2761             }
   2762             break;
   2763 
   2764         case TRIE_SPLIT2_STATE_DONE:
   2765             /* adjust parent's count */
   2766             assert(*split_count > 0);
   2767             assert(trie->count >= *split_count);
   2768 
   2769             /* update the child pointer if child was pruned */
   2770             if (*child != NULL) {
   2771                 trie->child[bit].child_node = *child;
   2772                 *child = NULL;
   2773             }
   2774             trie->count -= *split_count;
   2775             break;
   2776 
   2777         default:
   2778             break;
   2779     }
   2780 
   2781     return rv;
   2782 }
   2783 
   2784 
   2785 
   2786 /*
   2787  * Function:
   2788  *     trie_split2
   2789  * Purpose:
   2790  *     Split the trie such that the new sub trie covers given prefix/length.
   2791  *     Basically this is a reverse of trie_merge.
   2792  */
   2793 
   2794 int trie_split2(trie_t *trie,
   2795                 unsigned int *key,
   2796                 unsigned int key_len,
   2797                 unsigned int *pivot,
   2798                 unsigned int *pivot_len,
   2799                 trie_node_t **split_trie_root,
   2800                 const int max_split_count,
   2801                 const int exact_same)
   2802 {
   2803     int rv = SOC_E_NONE;
   2804     int msc = max_split_count;
   2805     unsigned int split_count=0;
   2806     trie_node_t *child = NULL, *node=NULL, clone;
   2807     trie_split2_states_e_t state = TRIE_SPLIT2_STATE_NONE;
   2808 
   2809     if (!trie || (key_len && !key) || !pivot || !pivot_len ||
   2810         !split_trie_root || max_split_count == 0) {
   2811         return SOC_E_PARAM;
   2812     }
   2813 
   2814     *split_trie_root = NULL;
   2815     *pivot_len = 0;
   2816 
   2817     if (trie->trie) {
   2818         if (max_split_count == 0xfffffff) {
   2819             trie_node_t *child2 = NULL;
   2820             trie_node_t *payload;
   2821             payload = sal_alloc(sizeof(trie_node_t), "trie_node");
   2822             if (payload == NULL) {
   2823                 return SOC_E_MEMORY;
   2824             }
   2825 
   2826             if (trie->v6_key) {
   2827                 rv = _trie_v6_insert(trie->trie, key, NULL, key_len, payload, &child2, 0);
   2828             } else {
   2829                 rv = _trie_insert(trie->trie, key, NULL, key_len, payload, &child2, 0);
   2830             }
   2831             if (child2) { /* change the old child pointer to new child */
   2832                 trie->trie = child2;
   2833             }
   2834 
   2835             if (SOC_SUCCESS(rv)) {
   2836                 payload->type = INTERNAL;
   2837             } else {
   2838                 sal_free(payload);
   2839                 if (rv != SOC_E_EXISTS) {
   2840                     return rv;
   2841                 }
   2842             }
   2843 
   2844             msc = trie->trie->count;
   2845         }
   2846         if (trie->v6_key) {
   2847             sal_memset(pivot, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_144_));
   2848             rv = _trie_v6_split2(trie->trie, key, key_len, pivot, pivot_len,
   2849                     &split_count, split_trie_root, &child, &state,
   2850                     msc, exact_same);
   2851         } else {
   2852             sal_memset(pivot, 0, sizeof(unsigned int) * BITS2WORDS(_MAX_KEY_LEN_48_));
   2853             rv = _trie_split2(trie->trie, key, key_len, pivot, pivot_len,
   2854                     &split_count, split_trie_root, &child, &state,
   2855                     msc, exact_same);
   2856         }
   2857 
   2858         if (SOC_SUCCESS(rv) && (TRIE_SPLIT2_STATE_DONE == state)) {
   2859             assert(split_count > 0);
   2860             assert(*split_trie_root);
   2861             if (max_split_count == 0xfffffff) {
   2862                 assert(*pivot_len == key_len);
   2863             } else {
   2864                 assert(*pivot_len < key_len);
   2865             }
   2866 
   2867             /* update the child pointer if child was pruned */
   2868             if (child != NULL) {
   2869                 trie->trie = child;
   2870             }
   2871 
   2872             sal_memcpy(&clone, *split_trie_root, sizeof(trie_node_t));
   2873             child = *split_trie_root;
   2874 
   2875             /* take advantage of thie function by passing in internal or payload node whatever
   2876              * is the new root. If internal the function assumed it as payload node & changes type.
   2877              * But this method is efficient to reuse the last internal or payload node possible to
   2878              * implant the new pivot */
   2879             if (trie->v6_key) {
   2880                 rv = _trie_v6_skip_node_alloc(&node, pivot, NULL,
   2881                                               *pivot_len, *pivot_len,
   2882                                               child, child->count);
   2883             } else {
   2884                 rv = _trie_skip_node_alloc(&node, pivot, NULL,
   2885                                            *pivot_len, *pivot_len,
   2886                                            child, child->count);
   2887             }
   2888 
   2889             if (SOC_SUCCESS(rv)) {
   2890                 if (clone.type == INTERNAL) {
   2891                     child->type = INTERNAL; /* since skip alloc would have reset it to payload */
   2892                 }
   2893                 child->child[0].child_node = clone.child[0].child_node;
   2894                 child->child[1].child_node = clone.child[1].child_node;
   2895                 *split_trie_root = node;
   2896             }
   2897         } else if (SOC_SUCCESS(rv) && (max_split_count == 0xfffffff) &&
   2898                    (split_count == trie->trie->count)) {
   2899             /* take all */
   2900             *split_trie_root = trie->trie;
   2901             trie->trie = NULL;
   2902         } else { /* split2 is not like split which can always succeed */
   2903             LOG_INFO(BSL_LS_SOC_ALPM,
   2904                       (BSL_META("Failed to split the trie error:%d state: %d "\
   2905                            "split_trie_root: %p !!!\n"),
   2906                         rv, state, *split_trie_root));
   2907             rv = SOC_E_NOT_FOUND;
   2908         }
   2909     } else {
   2910         rv = SOC_E_PARAM;
   2911     }
   2912 
   2913     return rv;
   2914 }
   2915 
   2916 
   2917 /*
   2918  * Function:
   2919  *     _trie_traverse_propagate_prefix
   2920  * Purpose:
   2921  *     calls back applicable payload object is affected by prefix updates 
   2922  * NOTE:
   2923  *     propagation stops once any callback funciton return something otherthan SOC_E_NONE
   2924  *     tcam propagation code should return !SOC_E_NONE so that callback only happen once.
   2925  * 
   2926  *     other propagation code should always return SOC_E_NONE so that callback will
   2927  *     happen on all pivot.
   2928  */
   2929 int _trie_traverse_propagate_prefix(trie_node_t *trie,
   2930                                     trie_propagate_cb_f cb,
   2931                                     trie_bpm_cb_info_t *cb_info,
   2932                                     unsigned int mask)
   2933 {
   2934     int rv = SOC_E_NONE, index=0;
   2935 
   2936     if (!trie || !cb || !cb_info) return SOC_E_PARAM;
   2937 
   2938     if ((trie->bpm & mask) == 0) {
   2939         /* call back the payload object if applicable */
   2940         if (PAYLOAD == trie->type) {
   2941             rv = cb(trie, cb_info);
   2942 	    if (SOC_FAILURE(rv)) {
   2943 		/* callback stops once any callback function not returning SOC_E_NONE */
   2944 		return rv;
   2945 	    }
   2946         }
   2947 
   2948         for (index=0; index < _MAX_CHILD_ && SOC_SUCCESS(rv); index++) {
   2949             if (trie->child[index].child_node && trie->child[index].child_node->bpm == 0) {
   2950                 /* coverity[large_shift : FALSE] */
   2951                 rv = _trie_traverse_propagate_prefix(trie->child[index].child_node,
   2952                                                      cb, cb_info, MASK(32));
   2953             }
   2954 
   2955 	    if (SOC_FAILURE(rv)) {
   2956 		/* callback stops once any callback function not returning SOC_E_NONE */
   2957 		return rv;
   2958 	    }
   2959         }
   2960     }
   2961 
   2962     return rv;
   2963 }
   2964 
   2965 /*
   2966  * Function:
   2967  *     _trie_propagate_prefix
   2968  * Purpose:
   2969  *  Propogate prefix BPM. If the propogation starts from intermediate pivot on
   2970  *  the trie, then the prefix length has to be appropriately adjusted or else 
   2971  *  it will end up with ill updates. 
   2972  *  Assumption: the prefix length is adjusted as per trie node on which is starts from.
   2973  *  If node == head node then adjust is none
   2974  *     node == pivot, then prefix length = org len - pivot len          
   2975  */
   2976 STATIC int _trie_propagate_prefix(trie_node_t *trie,
   2977 				  unsigned int *pfx,
   2978 				  unsigned int len,
   2979 				  unsigned int add, /* 0-del/1-add */
   2980 				  trie_propagate_cb_f cb,
   2981 				  trie_bpm_cb_info_t *cb_info)
   2982 {
   2983     int rv = SOC_E_NONE; /*, index;*/
   2984     unsigned int bit=0, lcp=0;
   2985 
   2986     if (!trie || (len && trie->skip_len && !pfx) ||
   2987         (len > _MAX_KEY_LEN_) || !cb || !cb_info) return SOC_E_PARAM;
   2988 
   2989     if (len > 0) {
   2990         /* BPM bit maps has to be updated before propagation */
   2991         lcp = lcplen(pfx, len, trie->skip_addr, trie->skip_len);            
   2992         /* if the lcp is less than prefix length the prefix is not applicable
   2993          * for any propagation */
   2994         if (lcp < ((len>trie->skip_len)?trie->skip_len:len)) {
   2995             return SOC_E_NONE; 
   2996         } else { 
   2997             if (len > trie->skip_len) {
   2998                 /* fully matched and more bits to check, go down the trie */
   2999                 bit = _key_get_bits(pfx, len-lcp, 1, 0);
   3000                 if (!trie->child[bit].child_node) return SOC_E_NONE;
   3001                 rv = _trie_propagate_prefix(trie->child[bit].child_node,
   3002                                             pfx, len-lcp-1, add, cb, cb_info);
   3003             } else {
   3004                 /* given pfx exactly matched or covers trie node, this is the
   3005                  * point to propagate.
   3006                  */
   3007                 /* pfx is <= trie skip len */
   3008                 if (!add) { /* delete */
   3009                     _BITCLR(trie->bpm, trie->skip_len - len);
   3010                 }
   3011                 
   3012                 /* update bit map and propagate if applicable:
   3013                  * there is no longer bpm than this new prefix
   3014                  */
   3015                 if ((trie->bpm & BITMASK(trie->skip_len - len)) == 0) {
   3016                     rv = _trie_traverse_propagate_prefix(trie, cb, 
   3017                                                          cb_info, 
   3018                                                          BITMASK(trie->skip_len - len));
   3019                     if (SOC_E_LIMIT == rv) rv = SOC_E_NONE;
   3020                 } else if (add && _BITGET(trie->bpm, trie->skip_len - len)) {
   3021 		    /* if adding, and bpm of this node is the specified prefix
   3022 		     * also propagate. (this is really update case)
   3023 		     */
   3024                     rv = _trie_traverse_propagate_prefix(trie, cb, 
   3025                                                          cb_info, 
   3026                                                          BITMASK(trie->skip_len - len));
   3027                     if (SOC_E_LIMIT == rv) rv = SOC_E_NONE;
   3028 		}
   3029                 
   3030                 if (add && SOC_SUCCESS(rv)) {
   3031                     /* this is the case where child bit is the new prefix */
   3032                     _BITSET(trie->bpm, trie->skip_len - len);
   3033                 }
   3034             }
   3035         }
   3036     } else {
   3037         if (!add) { /* delete */
   3038             _BITCLR(trie->bpm, trie->skip_len);
   3039         }
   3040 
   3041         if ((trie->bpm == 0) || 
   3042 	    (add && ((trie->bpm & BITMASK(trie->skip_len)) == 0))) {
   3043 	    /* if adding, and bpm of this node is the specified prefix
   3044 	     * also propagate. (this is really update case)
   3045 	     */
   3046             rv = _trie_traverse_propagate_prefix(trie, cb, cb_info, BITMASK(trie->skip_len));
   3047             if (SOC_E_LIMIT == rv) rv = SOC_E_NONE;
   3048         }
   3049         
   3050         if (add && SOC_SUCCESS(rv)) { /* add */
   3051             /* this is the case where child bit is the new prefix */
   3052             _BITSET(trie->bpm, trie->skip_len);
   3053         }
   3054     }
   3055 
   3056     return rv;
   3057 }
   3058 
   3059 /*
   3060  * Function:
   3061  *     _trie_propagate_prefix_validate
   3062  * Purpose:
   3063  *  validate that the provided prefix is valid for propagation.
   3064  *  The added prefix which was member of a shorter pivot's domain 
   3065  *  must never be more specific than another pivot encounter if any
   3066  *  in the path
   3067  */
   3068 STATIC int _trie_propagate_prefix_validate(trie_node_t *trie,
   3069 					   unsigned int *pfx,
   3070 					   unsigned int len)
   3071 {
   3072     unsigned int lcp=0, bit=0;
   3073 
   3074     if (!trie || (len && trie->skip_len && !pfx)) return SOC_E_PARAM;
   3075 
   3076     if (len == 0) return SOC_E_NONE;
   3077 
   3078     lcp = lcplen(pfx, len, trie->skip_addr, trie->skip_len);
   3079 
   3080     if (lcp == trie->skip_len) {
   3081         if (PAYLOAD == trie->type) return SOC_E_PARAM;
   3082 	if (len == lcp) return SOC_E_NONE;
   3083         bit = _key_get_bits(pfx, len-lcp, 1, 0);
   3084         if (!trie->child[bit].child_node) return SOC_E_NONE;
   3085         return _trie_propagate_prefix_validate(trie->child[bit].child_node,
   3086                                                pfx, len-1-lcp);
   3087     }
   3088 
   3089     return SOC_E_NONE;
   3090 }
   3091 
   3092 int _trie_init_propagate_info(unsigned int *pfx,
   3093 			      unsigned int len,
   3094 			      trie_propagate_cb_f cb,
   3095 			      trie_bpm_cb_info_t *cb_info)
   3096 {
   3097     cb_info->pfx = pfx;
   3098     cb_info->len = len;
   3099     return SOC_E_NONE;
   3100 }
   3101 
   3102 /*
   3103  * Function:
   3104  *     trie_pivot_propagate_prefix
   3105  * Purpose:
   3106  *  Propogate prefix BPM from a given pivot.      
   3107  */
   3108 int trie_pivot_propagate_prefix(trie_node_t *pivot,
   3109                                 unsigned int pivot_len,
   3110                                 unsigned int *pfx,
   3111                                 unsigned int len,
   3112                                 unsigned int add, /* 0-del/1-add */
   3113                                 trie_propagate_cb_f cb,
   3114                                 trie_bpm_cb_info_t *cb_info)
   3115 {
   3116     int rv = SOC_E_NONE;
   3117 
   3118     if (!pfx || !pivot || (len > _MAX_KEY_LEN_) ||
   3119         (pivot_len >  _MAX_KEY_LEN_) || (len < pivot_len) ||
   3120         (pivot->type != PAYLOAD) || !cb || !cb_info ||
   3121         !cb_info->pfx) {
   3122 	return SOC_E_PARAM;
   3123     }
   3124 
   3125     _trie_init_propagate_info(pfx,len,cb,cb_info);
   3126     len -= pivot_len;
   3127 
   3128     if (len > 0) {
   3129         unsigned int bit =  _key_get_bits(pfx, len, 1, 0);
   3130 
   3131         if (pivot->child[bit].child_node) {
   3132             /* validate if the pivot provided is correct */
   3133             rv = _trie_propagate_prefix_validate(pivot->child[bit].child_node,
   3134 						 pfx, len-1);
   3135             if (SOC_SUCCESS(rv)) {
   3136                 rv = _trie_propagate_prefix(pivot->child[bit].child_node,
   3137                                             pfx, len-1,
   3138                                             add, cb, cb_info);
   3139             }
   3140         } /* else nop, nothing to propagate on this path end */
   3141     } else {
   3142         /* pivot == prefix */
   3143         rv = _trie_propagate_prefix(pivot, pfx, pivot->skip_len,
   3144                                     add, cb, cb_info);
   3145     }
   3146 
   3147     return rv;
   3148 }
   3149 
   3150 /*
   3151  * Function:
   3152  *     _pvt_trie_traverse_propagate_prefix
   3153  * Purpose:
   3154  *     calls back applicable payload object is affected by prefix updates
   3155  * NOTE:
   3156  *     other propagation code should always return SOC_E_NONE so that
   3157  *     callback will happen on all pivot.
   3158  */
   3159 int _pvt_trie_traverse_propagate_prefix(trie_node_t *trie,
   3160                                         trie_propagate_cb_f cb,
   3161                                         trie_bpm_cb_info_t *cb_info)
   3162 {
   3163     int rv = SOC_E_NONE, index=0;
   3164     int rv1 = SOC_E_NONE;
   3165 
   3166     if (!trie || !cb || !cb_info) {
   3167         return SOC_E_PARAM;
   3168     }
   3169 
   3170     /* call back the payload object if applicable */
   3171     if (PAYLOAD == trie->type) {
   3172         rv = cb(trie, cb_info);
   3173         if (SOC_FAILURE(rv)) {
   3174             return rv;
   3175         }
   3176     }
   3177 
   3178     for (index=0; index < _MAX_CHILD_; index++) {
   3179         if (trie->child[index].child_node) {
   3180             rv = _pvt_trie_traverse_propagate_prefix(
   3181                     trie->child[index].child_node, cb, cb_info);
   3182             /* Save first error, second error can overwrite if it's more severe
   3183                than the first. SOC_E_LIMIT is considered as no severe error */
   3184             if (SOC_FAILURE(rv)) {
   3185                 if (rv1 == SOC_E_NONE || rv1 == SOC_E_LIMIT) {
   3186                     rv1 = rv;
   3187                 }
   3188             }
   3189         }
   3190     }
   3191 
   3192     return rv1;
   3193 }
   3194 
   3195 /*
   3196  * Function:
   3197  *   _pvt_trie_propagate_prefix
   3198  * Purpose:
   3199  *   If the propogation starts from intermediate pivot on
   3200  *   the trie, then the prefix length has to be appropriately adjusted or else
   3201  *   it will end up with ill updates.
   3202  *   Assumption: the prefix length is adjusted as per trie node on which
   3203  *               is starts from.
   3204  *   If node == head node then adjust is none
   3205  *      node == pivot, then prefix length = org len - pivot len
   3206  */
   3207 STATIC int _pvt_trie_propagate_prefix(trie_node_t *trie,
   3208                     unsigned int *pfx,
   3209                     unsigned int len,
   3210                     trie_propagate_cb_f cb,
   3211                     trie_bpm_cb_info_t *cb_info)
   3212 {
   3213     int rv = SOC_E_NONE; /*, index;*/
   3214     unsigned int bit = 0, lcp = 0;
   3215 
   3216     if (!trie || (len && trie->skip_len && !pfx) ||
   3217         (len > _MAX_KEY_LEN_) || !cb || !cb_info) {
   3218         return SOC_E_PARAM;
   3219     }
   3220 
   3221     if (len > 0) {
   3222         lcp = lcplen(pfx, len, trie->skip_addr, trie->skip_len);
   3223         /* if the lcp is less than prefix length the prefix is not applicable
   3224          * for any propagation */
   3225         if (lcp < ((len>trie->skip_len) ? trie->skip_len : len)) {
   3226             return SOC_E_NONE;
   3227         } else {
   3228             if (len > trie->skip_len) {
   3229                 bit = _key_get_bits(pfx, len-lcp, 1, 0);
   3230                 if (!trie->child[bit].child_node) {
   3231                     return SOC_E_NONE;
   3232                 }
   3233                 rv = _pvt_trie_propagate_prefix(
   3234                         trie->child[bit].child_node,
   3235                         pfx, len-lcp-1, cb, cb_info);
   3236             } else {
   3237                 /* pfx is <= trie skip len */
   3238                 /* propagate if applicable */
   3239                 rv = _pvt_trie_traverse_propagate_prefix(trie, cb,
   3240                                                          cb_info);
   3241                 if (SOC_E_LIMIT == rv) {
   3242                     rv = SOC_E_NONE;
   3243                 }
   3244             }
   3245         }
   3246     } else {
   3247         rv = _pvt_trie_traverse_propagate_prefix(trie, cb, cb_info);
   3248         if (SOC_E_LIMIT == rv) {
   3249             rv = SOC_E_NONE;
   3250         }
   3251     }
   3252 
   3253     return rv;
   3254 }
   3255 
   3256 /*
   3257  * Function:
   3258  *      pvt_trie_propagate_prefix
   3259  * Purpose:
   3260  *      Propogate prefix from a given pivot.
   3261  *      Callback function to decide INSERT/DELETE propagation,
   3262  *               and decide to update bpm_len or not.
   3263  */
   3264 int pvt_trie_propagate_prefix(trie_node_t *pivot,
   3265                               unsigned int pivot_len,
   3266                               unsigned int *pfx,
   3267                               unsigned int len,
   3268                               trie_propagate_cb_f cb,
   3269                               trie_bpm_cb_info_t *cb_info)
   3270 {
   3271     int rv = SOC_E_NONE;
   3272 
   3273     if (!pfx || !pivot || (len > _MAX_KEY_LEN_) ||
   3274         (pivot_len > _MAX_KEY_LEN_) || (len < pivot_len) ||
   3275         (pivot->type != PAYLOAD) || !cb || !cb_info ||
   3276         !cb_info->pfx) {
   3277         return SOC_E_PARAM;
   3278     }
   3279 
   3280     len -= pivot_len;
   3281 
   3282     if (len > 0) {
   3283         unsigned int bit = _key_get_bits(pfx, len, 1, 0);
   3284         if (pivot->child[bit].child_node) {
   3285             /* validate if the pivot provided is correct */
   3286             rv = _trie_propagate_prefix_validate(pivot->child[bit].child_node,
   3287                                                  pfx, len-1);
   3288             if (SOC_SUCCESS(rv)) {
   3289                 rv = _pvt_trie_propagate_prefix(pivot->child[bit].child_node,
   3290                                                 pfx, len-1,
   3291                                                 cb, cb_info);
   3292             }
   3293         } /* else nop, nothing to propagate on this path end */
   3294     } else {
   3295         /* pivot == prefix */
   3296         rv = _pvt_trie_propagate_prefix(pivot, pfx, pivot->skip_len,
   3297                                         cb, cb_info);
   3298     }
   3299 
   3300     return rv;
   3301 }
   3302 
   3303 int trie_ppg_prefix(trie_t *trie, unsigned int pvt_len,
   3304                     unsigned int *pfx,
   3305                     unsigned int len,
   3306                     trie_propagate_cb_f cb,
   3307                     trie_bpm_cb_info_t *cb_info)
   3308 {
   3309     int rv = SOC_E_NONE, rv2 = SOC_E_NONE;
   3310     trie_node_t *payload;
   3311 
   3312     if (!pfx || !trie || !trie->trie || !cb || !cb_info) {
   3313         return SOC_E_PARAM;
   3314     }
   3315 
   3316     payload = sal_alloc(sizeof(trie_node_t), "trie_node");
   3317     if (payload == NULL) {
   3318         return SOC_E_MEMORY;
   3319     }
   3320     rv2 = trie_insert(trie, pfx, NULL, len, payload);
   3321     if (SOC_FAILURE(rv2)) {
   3322         sal_free(payload);
   3323         if (rv2 != SOC_E_EXISTS) {
   3324             return rv2;
   3325         }
   3326         rv = trie_find_lpm(trie, pfx, len, &payload);
   3327         if (SOC_FAILURE(rv)) {
   3328             return rv;
   3329         }
   3330     } else {
   3331         payload->bpm = -1;
   3332     }
   3333 
   3334     if (trie->v6_key) {
   3335         rv = pvt_trie_v6_propagate_prefix(payload, len, pfx, len,
   3336                                           cb, cb_info);
   3337     } else {
   3338         rv = pvt_trie_propagate_prefix(payload, len, pfx, len,
   3339                                        cb, cb_info);
   3340     }
   3341 
   3342     if (SOC_SUCCESS(rv2)) {
   3343         trie_delete(trie, pfx, len, &payload);
   3344         sal_free(payload);
   3345     }
   3346 
   3347     return rv;
   3348 }
   3349 
   3350 /*
   3351  * Function:
   3352  *     trie_propagate_prefix
   3353  * Purpose:
   3354  *  Propogate prefix BPM on a given trie.      
   3355  */
   3356 int trie_propagate_prefix(trie_t *trie,
   3357                           unsigned int *pfx,
   3358                           unsigned int len,
   3359                           unsigned int add, /* 0-del/1-add */
   3360                           trie_propagate_cb_f cb,
   3361                           trie_bpm_cb_info_t *cb_info)
   3362 {
   3363     int rv=SOC_E_NONE;
   3364 
   3365     if (!pfx || !trie || !trie->trie || !cb || !cb_info || !cb_info->pfx) {
   3366 	return SOC_E_PARAM;
   3367     }
   3368 
   3369     _trie_init_propagate_info(pfx,len,cb,cb_info);
   3370 
   3371     if (SOC_SUCCESS(rv)) {
   3372 	if (trie->v6_key) {	    
   3373 	    rv = _trie_v6_propagate_prefix(trie->trie, pfx, len, add, 
   3374 					   cb, cb_info);
   3375 	} else {
   3376 	    rv = _trie_propagate_prefix(trie->trie, pfx, len, add, 
   3377 					cb, cb_info);
   3378 	}
   3379     }
   3380 
   3381     return rv;
   3382 }
   3383 
   3384 
   3385 /*
   3386  * Function:
   3387  *     trie_init
   3388  * Purpose:
   3389  *     allocates a trie & initializes it
   3390  */
   3391 int trie_init(unsigned int max_key_len, trie_t **ptrie)
   3392 {
   3393     trie_t *trie = sal_alloc(sizeof(trie_t), "trie-node");
   3394     sal_memset(trie, 0, sizeof(trie_t));
   3395 
   3396     if (max_key_len == _MAX_KEY_LEN_48_) {
   3397         trie->v6_key = FALSE;
   3398     } else if (max_key_len == _MAX_KEY_LEN_144_) {
   3399         trie->v6_key = TRUE;
   3400     } else {
   3401         sal_free(trie);
   3402         return SOC_E_PARAM;
   3403     }
   3404 
   3405     trie->trie = NULL; /* means nothing is on teie */
   3406     *ptrie = trie;
   3407     return SOC_E_NONE;
   3408 }
   3409 
   3410 
   3411 /*
   3412  * Function:
   3413  *     trie_delete_node_cb
   3414  * Purpose:
   3415  *     Call back to delete a node
   3416  */
   3417 int
   3418 trie_delete_node_cb(trie_node_t *node, void *info)
   3419 {
   3420     if (node != NULL) {
   3421         sal_free(node);
   3422     }
   3423     return SOC_E_NONE;
   3424 }
   3425 
   3426 /*
   3427  * Function:
   3428  *     trie_destroy2
   3429  * Purpose:
   3430  *     destroys a trie and its body
   3431  */
   3432 int trie_destroy2(trie_t *trie)
   3433 {
   3434     int rv;
   3435     rv = trie_traverse(trie, trie_delete_node_cb, NULL,
   3436                        _TRIE_POSTORDER_TRAVERSE);
   3437     if (SOC_FAILURE(rv)) {
   3438         return rv;
   3439     }
   3440     sal_free(trie);
   3441     return SOC_E_NONE;
   3442 }
   3443 
   3444 
   3445 /*
   3446  * Function:
   3447  *     trie_destroy
   3448  * Purpose:
   3449  *     destroys a trie
   3450  */
   3451 int trie_destroy(trie_t *trie)
   3452 {
   3453     if (trie != NULL) {
   3454         sal_free(trie);
   3455     }
   3456     return SOC_E_NONE;
   3457 }
   3458 
   3459 
   3460 STATIC int _trie_clone(trie_node_t *ptrie,
   3461                        trie_node_t *trie,
   3462                        int bit,
   3463                        trie_traverse_states_e_t *state,
   3464                        trie_node_t *pnode,
   3465                        trie_t      *clone_trie)
   3466 {
   3467     int rv = SOC_E_NONE;
   3468     trie_node_t *lc, *rc;
   3469 
   3470     if (trie == NULL) {
   3471         return SOC_E_NONE;
   3472     } else {
   3473         /* make the trie delete safe */
   3474         lc = trie->child[0].child_node;
   3475         rc = trie->child[1].child_node;
   3476         {
   3477             trie_node_t *clone_node = NULL;
   3478 
   3479             /* assert(trie); */
   3480             clone_node = sal_alloc(sizeof(trie_node_t), "clone trie");
   3481             if (clone_node == NULL) {
   3482                 return SOC_E_MEMORY;
   3483             }
   3484             sal_memcpy(clone_node, trie, sizeof(trie_node_t));
   3485 
   3486             if (ptrie == NULL) { /* clone head */
   3487                 /* assert(clone_trie); */
   3488                 clone_trie->trie = clone_node;
   3489             } else { /* clone body */
   3490                 /* assert(pnode); */
   3491                 pnode->child[bit].child_node = clone_node;
   3492             }
   3493 
   3494             pnode = clone_node;
   3495         }
   3496         TRIE_TRAVERSE_STOP(*state, rv);
   3497         /* make the ptrie delete safe */
   3498         if (*state != TRIE_TRAVERSE_STATE_DELETED) {
   3499             ptrie = trie;
   3500         }
   3501     }
   3502 
   3503     if (SOC_SUCCESS(rv)) {
   3504         rv = _trie_clone(ptrie, lc, 0, state, pnode, NULL);
   3505         TRIE_TRAVERSE_STOP(*state, rv);
   3506     }
   3507     if (SOC_SUCCESS(rv)) {
   3508         rv = _trie_clone(ptrie, rc, 1, state, pnode, NULL);
   3509     }
   3510     return rv;
   3511 }
   3512 
   3513 
   3514 int trie_clone(trie_t *trie_src, trie_t **trie_dst)
   3515 {
   3516     int rv;
   3517     trie_traverse_states_e_t state = TRIE_TRAVERSE_STATE_NONE;
   3518 
   3519     assert(trie_src && trie_dst);
   3520 
   3521     rv = trie_init(trie_src->v6_key ? _MAX_KEY_LEN_144_ : _MAX_KEY_LEN_48_,
   3522                    trie_dst);
   3523     if (SOC_FAILURE(rv)) {
   3524         return rv;
   3525     }
   3526 
   3527     rv = _trie_clone(NULL, trie_src->trie, 0, &state, NULL, *trie_dst);
   3528     if (SOC_FAILURE(rv)) {
   3529         trie_destroy2(*trie_dst);
   3530         *trie_dst = NULL;
   3531     }
   3532     return rv;
   3533 }
   3534 
   3535 
   3536 
   3537 STATIC int _trie_compare(trie_node_t *ptrie,
   3538                          trie_node_t *trie,
   3539                          int bit,
   3540                          trie_traverse_states_e_t *state,
   3541                          trie_node_t *ptrie_cmp,
   3542                          trie_node_t *trie_cmp,
   3543                          int *cmp_result)
   3544 {
   3545     int rv = SOC_E_NONE;
   3546     trie_node_t *lc, *rc;
   3547 
   3548     if (trie == NULL) {
   3549         return SOC_E_NONE;
   3550     } else {
   3551         /* make the trie delete safe */
   3552         lc = trie->child[0].child_node;
   3553         rc = trie->child[1].child_node;
   3554         {
   3555 
   3556             assert(trie && state);
   3557 
   3558             if (ptrie == NULL) { /* compare head */
   3559                 trie_cmp = trie_cmp;
   3560             } else { /* compare body */
   3561                 trie_cmp = ptrie_cmp->child[bit].child_node;
   3562             }
   3563 
   3564             /* When traverse against one trie, there is a possibility the other is
   3565              * a super set of this one. To rule out that possibility, compare the child
   3566              * pointer as well.
   3567              */
   3568             if (/* trie_cmp->skip_len != trie->skip_len ||
   3569                 (BITMASK(trie->skip_len) & trie_cmp->skip_addr) !=
   3570                 (BITMASK(trie->skip_len) & trie->skip_addr) || */
   3571                 trie_cmp->type != trie->type ||
   3572                 trie_cmp->count != trie->count ||
   3573                 trie_cmp->bpm != trie->bpm ||
   3574                 !trie_cmp->child[0].child_node != !trie->child[0].child_node ||
   3575                 !trie_cmp->child[1].child_node != !trie->child[1].child_node) {
   3576                 *cmp_result = 1;
   3577                 /* stop traverse on unequal */
   3578                 *state = TRIE_TRAVERSE_STATE_DONE;
   3579             }
   3580 
   3581             /* In case of v6, the skip len not equal does not mean the two
   3582              * tries are different, thus we print it and let user be aware
   3583              * and then continue.
   3584              */
   3585             if (trie_cmp->skip_len != trie->skip_len) {
   3586                 LOG_CLI(("AWARE:len %d - %d   addr 0x%x - 0x%x\n",
   3587                          trie_cmp->skip_len, trie->skip_len,
   3588                          trie_cmp->skip_addr, trie->skip_addr));
   3589             }
   3590             ptrie_cmp = trie_cmp;
   3591         }
   3592         TRIE_TRAVERSE_STOP(*state, rv);
   3593         /* make the ptrie delete safe */
   3594         if (*state != TRIE_TRAVERSE_STATE_DELETED) {
   3595             ptrie = trie;
   3596         }
   3597     }
   3598 
   3599     if (SOC_SUCCESS(rv)) {
   3600         rv = _trie_compare(ptrie, lc, 0, state, ptrie_cmp, NULL, cmp_result);
   3601         TRIE_TRAVERSE_STOP(*state, rv);
   3602     }
   3603     if (SOC_SUCCESS(rv)) {
   3604         rv = _trie_compare(ptrie, rc, 1, state, ptrie_cmp, NULL, cmp_result);
   3605     }
   3606     return rv;
   3607 }
   3608 
   3609 
   3610 int trie_compare(trie_t *trie_src, trie_t *trie_dst, int *equal)
   3611 {
   3612     trie_traverse_states_e_t state = TRIE_TRAVERSE_STATE_NONE;
   3613 
   3614     assert(trie_src && trie_dst && equal);
   3615 
   3616     *equal = 0;
   3617 
   3618     return _trie_compare(NULL, trie_src->trie, 0, &state, NULL, trie_dst->trie, equal);
   3619 }
   3620 
   3621 #if 0 
   3622 /****************/
   3623 /** unit tests **/
   3624 /****************/
   3625 #define _NUM_KEY_ (4 * 1024)
   3626 #define _VRF_LEN_ 16
   3627 /*#define VERBOSE 
   3628   #define LOG*/
   3629 /* use the followign diag shell command to run this test:
   3630  * tr c3sw test=tmu_trie_ut
   3631  */
   3632 typedef struct _payload_s {
   3633     trie_node_t node; /*trie node */
   3634     dq_t        listnode; /* list node */
   3635     union {
   3636         trie_t      *trie;
   3637         trie_node_t pfx_trie_node;
   3638     } info;
   3639     unsigned int key[BITS2WORDS(_MAX_KEY_LEN_)];
   3640     unsigned int len;
   3641 } payload_t;
   3642 
   3643 int ut_print_payload_node(trie_node_t *payload, void *datum)
   3644 {
   3645     payload_t *pyld;
   3646 
   3647     if (payload && payload->type == PAYLOAD) {
   3648         pyld = TRIE_ELEMENT_GET(payload_t*, payload, node);
   3649         LOG_CLI((BSL_META(" key[0x%08x:0x%08x] Length:%d \n"),
   3650                  pyld->key[0], pyld->key[1], pyld->len));
   3651     }
   3652     return SOC_E_NONE;
   3653 }
   3654 
   3655 int ut_print_prefix_payload_node(trie_node_t *payload, void *datum)
   3656 {
   3657     payload_t *pyld;
   3658 
   3659     if (payload && payload->type == PAYLOAD) {
   3660         pyld = TRIE_ELEMENT_GET(payload_t*, payload, info.pfx_trie_node);
   3661         LOG_CLI((BSL_META(" key[0x%08x:0x%08x] Length:%d \n"),
   3662                  pyld->key[0], pyld->key[1], pyld->len));
   3663     }
   3664     return SOC_E_NONE;
   3665 }
   3666 
   3667 int ut_check_duplicate(payload_t *pyld, int pyld_vector_size)
   3668 {
   3669     int i=0;
   3670 
   3671     assert(pyld);
   3672 
   3673     for (i=0; i < pyld_vector_size; i++) {
   3674         if (pyld[i].len == pyld[pyld_vector_size].len &&
   3675             pyld[i].key[0] == pyld[pyld_vector_size].key[0] && 
   3676             pyld[i].key[1] == pyld[pyld_vector_size].key[1]) {
   3677             break;
   3678         }
   3679     }
   3680 
   3681     return ((i == pyld_vector_size)?0:1);
   3682 }
   3683 
   3684 
   3685 int tmu_taps_util_get_bpm_pfx_ut(void) 
   3686 {
   3687     int rv;
   3688     unsigned int pfx_len=0;
   3689     unsigned int bpm[] = { 0x80, 0x00101010 }; /* 40th bit msb */
   3690 
   3691     /* v4 test */
   3692     rv = taps_get_bpm_pfx(&bpm[0], 48, _MAX_KEY_LEN_48_, &pfx_len);
   3693     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3694     if (pfx_len != 48-4) return SOC_E_FAIL;
   3695 
   3696     bpm[0] = 0;
   3697     bpm[1] = 0x00010000;
   3698     rv = taps_get_bpm_pfx(&bpm[0], 48, _MAX_KEY_LEN_48_, &pfx_len);
   3699     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3700     if (pfx_len != 48-16) return SOC_E_FAIL;
   3701 
   3702     bpm[0] = 0;
   3703     bpm[1] = 0x80000000;
   3704     rv = taps_get_bpm_pfx(&bpm[0], 48, _MAX_KEY_LEN_48_, &pfx_len);
   3705     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3706     if (pfx_len != 48-31) return SOC_E_FAIL;
   3707 
   3708     bpm[0] = 0x1;
   3709     bpm[1] = 0x80000000;
   3710     rv = taps_get_bpm_pfx(&bpm[0], 48, _MAX_KEY_LEN_48_, &pfx_len);
   3711     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3712     if (pfx_len != 48-31) return SOC_E_FAIL;
   3713 
   3714     bpm[0] = 0;
   3715     bpm[1] = 0;
   3716     rv = taps_get_bpm_pfx(&bpm[0], 48, _MAX_KEY_LEN_48_, &pfx_len);
   3717     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3718     if (pfx_len != 0) return SOC_E_FAIL;
   3719 
   3720     /* v6 test */
   3721     bpm[0] = 0x80;
   3722     bpm[1] = 0x00101010;
   3723     rv = taps_get_bpm_pfx(&bpm[0], 144, _MAX_KEY_LEN_144_, &pfx_len);
   3724     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3725     if (pfx_len != 144-4) return SOC_E_FAIL;
   3726 
   3727     bpm[0] = 0;
   3728     bpm[1] = 0x00010000;
   3729     rv = taps_get_bpm_pfx(&bpm[0], 144, _MAX_KEY_LEN_144_, &pfx_len);
   3730     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3731     if (pfx_len != 144-16) return SOC_E_FAIL;
   3732 
   3733     bpm[0] = 0;
   3734     bpm[1] = 0x80000000;
   3735     rv = taps_get_bpm_pfx(&bpm[0], 144, _MAX_KEY_LEN_144_, &pfx_len);
   3736     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3737     if (pfx_len != 144-31) return SOC_E_FAIL;
   3738 
   3739     bpm[0] = 0x1;
   3740     bpm[1] = 0x80000000;
   3741     rv = taps_get_bpm_pfx(&bpm[0], 144, _MAX_KEY_LEN_144_, &pfx_len);
   3742     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3743     if (pfx_len != 144-31) return SOC_E_FAIL;
   3744 
   3745     bpm[0] = 0;
   3746     bpm[1] = 0;
   3747     rv = taps_get_bpm_pfx(&bpm[0], 144, _MAX_KEY_LEN_144_, &pfx_len);
   3748     if (SOC_FAILURE(rv)) return SOC_E_FAIL;
   3749     if (pfx_len != 0) return SOC_E_FAIL;
   3750 
   3751     return SOC_E_NONE;
   3752 }
   3753 
   3754 int tmu_taps_kshift_ut(void) 
   3755 {
   3756     unsigned int key[] = { 0x1234, 0x12345678 }, length=0;
   3757 
   3758     /* v4 tests */
   3759     _key_shift_left(key, 8);
   3760     if (key[0] != 0x3412 && key[1] != 0x34567800) {
   3761         return SOC_E_FAIL;
   3762     }
   3763 
   3764     key[0] = 0;
   3765     key[1] = 0x12345678;
   3766     _key_shift_left(key, 15);    
   3767 
   3768     if (key[0] != (0x12345678 >> 17) && key[1] != (0x12345678 << 15)) {
   3769         return SOC_E_FAIL;
   3770     }
   3771 
   3772     key[0] = 0x1234;
   3773     key[1] = 0xdeadbeef;
   3774     _key_shift_left(key, 0);    
   3775     if (key[0] != 0x1234 && key[1] != 0xdeadbeef) {
   3776         return SOC_E_FAIL;
   3777     }
   3778 
   3779     key[0] = 0;
   3780     key[1] = 0;
   3781     _key_append(key, &length, 0xba5e, 16);
   3782     if (key[0] != 0 && key[1] != 0xba5e) {
   3783         return SOC_E_FAIL;
   3784     }
   3785 
   3786     _key_append(key, &length, 0x3a5eba11, 31);
   3787     if (key[0] != 0xba5e && key[1] != 0x3a5eba11) {
   3788         return SOC_E_FAIL;
   3789     }
   3790 
   3791     /* v6 tests */
   3792 
   3793     return SOC_E_NONE;
   3794 }
   3795 
   3796 int tmu_trie_split_ut(unsigned int seed) 
   3797 {
   3798     int index, rv = SOC_E_NONE, numkey=0, id=0;
   3799     trie_t *trie, *newtrie;
   3800     trie_node_t *newroot;
   3801     payload_t *pyld = sal_alloc(_NUM_KEY_ * sizeof(payload_t), "unit-test");
   3802     trie_node_t *pyldptr = NULL;
   3803     unsigned int pivot[_MAX_KEY_WORDS_], length;
   3804 
   3805     for (id=0; id < 4; id++) {
   3806         switch(id) {
   3807         case 0:  /* 1:1 split */
   3808             pyld[0].key[0] = 0; pyld[0].key[1] = 0x10; pyld[0].len = _VRF_LEN_ + 8;  /* v=0 p=0x10000000/8  */
   3809             pyld[1].key[0] = 0; pyld[1].key[1] = 0x1000; pyld[1].len = _VRF_LEN_ + 16; /* v=0 p=0x10000000/16 */
   3810             pyld[2].key[0] = 0; pyld[2].key[1] = 0x100000; pyld[2].len = _VRF_LEN_ + 24; /* v=0 p=0x10000000/24 */
   3811             pyld[3].key[0] = 0; pyld[3].key[1] = 0x10000000; pyld[3].len = _VRF_LEN_ + 32; /* v=0 p=0x10000000/48 */
   3812             numkey = 4;
   3813             break;
   3814         case 1: /* 1:1 split */
   3815             pyld[0].key[0] = 0; pyld[0].key[1] = 0x10000000; pyld[0].len = _VRF_LEN_ + 32; /* v=0 p=0x10000000/32 */
   3816             pyld[1].key[0] = 0; pyld[1].key[1] = 0x10000001; pyld[1].len = _VRF_LEN_ + 32; /* v=0 p=0x10000001/32 */
   3817             pyld[2].key[0] = 0; pyld[2].key[1] = 0x10000002; pyld[2].len = _VRF_LEN_ + 32; /* v=0 p=0x10000002/32 */
   3818             pyld[3].key[0] = 0; pyld[3].key[1] = 0x10000003; pyld[3].len = _VRF_LEN_ + 32; /* v=0 p=0x10000002/32 */
   3819             pyld[4].key[0] = 0; pyld[4].key[1] = 0x10000004; pyld[4].len = _VRF_LEN_ + 32; /* v=0 p=0x10000002/32 */
   3820             pyld[5].key[0] = 0; pyld[5].key[1] = 0x10000005; pyld[5].len = _VRF_LEN_ + 32; /* v=0 p=0x10000002/32 */
   3821             numkey = 6;
   3822             break;
   3823         case 2: /* 2:5 split */
   3824             pyld[0].key[0] = 0; pyld[0].key[1] = 0x100; pyld[0].len = _VRF_LEN_ + 12;
   3825             pyld[1].key[0] = 0; pyld[1].key[1] = 0x1011; pyld[1].len = _VRF_LEN_ + 16;
   3826             pyld[2].key[0] = 0; pyld[2].key[1] = 0x100000; pyld[2].len = _VRF_LEN_ + 24; 
   3827             pyld[3].key[0] = 0; pyld[3].key[1] = 0x1000000; pyld[3].len = _VRF_LEN_ + 28;
   3828             pyld[4].key[0] = 0; pyld[4].key[1] = 0x1001; pyld[4].len = _VRF_LEN_ + 16;
   3829             pyld[5].key[0] = 0; pyld[5].key[1] = 0x10011; pyld[5].len = _VRF_LEN_ + 20;
   3830             numkey = 6;
   3831             break;
   3832 
   3833         case 3:
   3834         {
   3835             int dup;
   3836 
   3837             if (seed == 0) {
   3838                 seed = sal_time();
   3839                 sal_srand(seed);
   3840             }
   3841 
   3842             index = 0;
   3843             LOG_CLI((BSL_META("Random test: %d Seed: 0x%x \n"), id, seed));
   3844             do {
   3845                 do {
   3846                     pyld[index].key[1] = (unsigned int) sal_rand();
   3847                     pyld[index].len = (unsigned int)sal_rand() % 32;
   3848                     pyld[index].len += _VRF_LEN_;
   3849 
   3850                     if (pyld[index].len <= 32) {
   3851                         pyld[index].key[0] = 0;
   3852                         pyld[index].key[1] &= MASK(pyld[index].len);
   3853                     }
   3854 
   3855                     if (pyld[index].len > 32) {
   3856                         pyld[index].key[0] = (unsigned int)sal_rand() % 16;                        
   3857                         pyld[index].key[0] &= MASK(pyld[index].len-32); 
   3858                     }
   3859 
   3860                     dup = ut_check_duplicate(pyld, index);
   3861                     if (dup) {                    
   3862                         LOG_CLI((BSL_META("\n Duplicate at index[%d]:"
   3863                                           "key[0x%08x:0x%08x] Retry!!!\n"), 
   3864                                  index, pyld[index].key[0],
   3865                                  pyld[index].key[1]));
   3866                     }
   3867                 } while(dup > 0);
   3868             } while(++index < _NUM_KEY_);
   3869 
   3870             numkey = index;
   3871        }
   3872        break;
   3873 
   3874         default:
   3875             return SOC_E_PARAM;
   3876         }
   3877 
   3878         trie_init(_MAX_KEY_LEN_, &trie);
   3879         trie_init(_MAX_KEY_LEN_, &newtrie);
   3880 
   3881         for(index=0; index < numkey && rv == SOC_E_NONE; index++) {
   3882             rv = trie_insert(trie, &pyld[index].key[0], NULL, pyld[index].len, &pyld[index].node);
   3883         }
   3884 
   3885         rv = trie_split(trie, _MAX_KEY_LEN_, FALSE, pivot, &length, &newroot, NULL, FALSE);
   3886         if (SOC_SUCCESS(rv)) {
   3887             LOG_CLI((BSL_META("\n Split Trie Pivot: 0x%08x 0x%08x "
   3888                               "Length: %d Root: %p \n"),
   3889                      pivot[0], pivot[1], length, newroot));
   3890             LOG_CLI((BSL_META(" $Payload Count Old Trie:%d New Trie:%d \n"),
   3891                      trie->trie->count, newroot->count));
   3892 
   3893             /* set new trie */
   3894             newtrie->trie = newroot;
   3895             newtrie->v6_key = trie->v6_key;
   3896 #ifdef VERBOSE
   3897             LOG_CLI((BSL_META("\n OLD Trie Dump ############: \n")));
   3898             trie_dump(trie, NULL, NULL);
   3899             LOG_CLI((BSL_META("\n SPLIT Trie Dump ############: \n")));
   3900             trie_dump(newtrie, NULL, NULL);
   3901 #endif
   3902             
   3903             for(index=0; index < numkey && rv == SOC_E_NONE; index++) {
   3904                 rv = trie_search(trie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   3905                 if (rv != SOC_E_NONE) {
   3906                     rv = trie_search(newtrie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   3907                     if (rv != SOC_E_NONE) {
   3908                         LOG_CLI((BSL_META("SEARCH: Key=0x%x 0x%x len %d SEARCH "
   3909                                           "idx:%d failed on both trie!!!!\n"), 
   3910                                  pyld[index].key[0], pyld[index].key[1],
   3911                                  pyld[index].len, index));
   3912                     } else {
   3913                         assert(pyldptr == &pyld[index].node);
   3914                     }
   3915                 } 
   3916             }
   3917             
   3918         }
   3919     }
   3920 
   3921     trie_destroy(trie);
   3922     trie_destroy(newtrie);
   3923     sal_free(pyld);
   3924     return rv;
   3925 }
   3926 
   3927 int tmu_taps_trie_ut(int id, unsigned int seed)
   3928 {
   3929     int index, rv = SOC_E_NONE, numkey=0, num_deleted=0;
   3930     trie_t *trie;
   3931     payload_t *pyld = sal_alloc(_NUM_KEY_ * sizeof(payload_t), "unit-test");
   3932     trie_node_t *pyldptr = NULL;
   3933     unsigned int result_len=0, result_key[_MAX_KEY_WORDS_];
   3934 
   3935     /* keys packed right to left (ie) most significant word starts at index 0*/
   3936 
   3937     switch(id) {
   3938     case 0:
   3939         pyld[0].key[0] = 0; pyld[0].key[1] = 0x10; pyld[0].len = _VRF_LEN_ + 8;  /* v=0 p=0x10000000/8  */
   3940         pyld[1].key[0] = 0; pyld[1].key[1] = 0x1000; pyld[1].len = _VRF_LEN_ + 16; /* v=0 p=0x10000000/16 */
   3941         pyld[2].key[0] = 0; pyld[2].key[1] = 0x100000; pyld[2].len = _VRF_LEN_ + 24; /* v=0 p=0x10000000/24 */
   3942         pyld[3].key[0] = 0; pyld[3].key[1] = 0x10000000; pyld[3].len = _VRF_LEN_ + 32; /* v=0 p=0x10000000/48 */
   3943         numkey = 4;
   3944         break;
   3945 
   3946     case 1:
   3947         pyld[0].key[0] = 0; pyld[0].key[1] = 0x123456; pyld[0].len  = _VRF_LEN_ + 24; /* v=0 p=0x12345678/24 */
   3948         pyld[1].key[0] = 0; pyld[1].key[1] = 0x246; pyld[1].len = _VRF_LEN_ + 13; /* v=0 p=0x12345678/13 */
   3949         pyld[2].key[0] = 0; pyld[2].key[1] = 0x24; pyld[2].len = _VRF_LEN_ + 9; /* v=0 p=0x12345678/9 */
   3950         numkey = 3;
   3951         break;
   3952 
   3953     case 2: /* dup routes on another vrf */
   3954         pyld[0].key[0] = 0; pyld[0].key[1] = 0x1123456; pyld[0].len = _VRF_LEN_ + 24; /* v=1 p=0x12345678/24 */
   3955         pyld[1].key[0] = 0; pyld[1].key[1] = 0x2246; pyld[1].len = _VRF_LEN_ + 13; /* v=1 p=0x12345678/13 */
   3956         pyld[2].key[0] = 0; pyld[2].key[1] = 0x224; pyld[2].len = _VRF_LEN_ + 9; /* v=1 p=0x12345678/9 */
   3957         numkey = 3;
   3958         break;
   3959 
   3960     case 3:
   3961         pyld[0].key[0] = 0; pyld[0].key[1] = 0x10000000; pyld[0].len = _VRF_LEN_ + 32; /* v=0 p=0x10000000/32 */
   3962         pyld[1].key[0] = 0; pyld[1].key[1] = 0x10000001; pyld[1].len = _VRF_LEN_ + 32; /* v=0 p=0x10000001/32 */
   3963         pyld[2].key[0] = 0; pyld[2].key[1] = 0x10000002; pyld[2].len = _VRF_LEN_ + 32; /* v=0 p=0x10000002/32 */
   3964         numkey = 3;
   3965         break;
   3966 
   3967     case 4:
   3968         pyld[0].key[0] = 0; pyld[0].key[1] = 0x12345670; pyld[0].len = _VRF_LEN_ + 32; /* v=0 p=0x12345670/32 */
   3969         pyld[1].key[0] = 0; pyld[1].key[1] = 0x12345671; pyld[1].len = _VRF_LEN_ + 32; /* v=0 p=0x12345671/32 */
   3970         pyld[2].key[0] = 0; pyld[2].key[1] = 0x91a2b38;  pyld[2].len = _VRF_LEN_ + 31; /* v=0 p=0x12345670/31 */
   3971         numkey = 3;
   3972         break;
   3973 
   3974     case 5:
   3975         pyld[0].key[0] = 0; pyld[0].key[1] = 0x20; pyld[0].len = _VRF_LEN_ + 8; /* v=0 p=0x20000000/8 */
   3976         pyld[1].key[0] = 0; pyld[1].key[1] = 0x8000; pyld[1].len = _VRF_LEN_ + 16; /* v=0 p=0x80000000/16 */
   3977         pyld[2].key[0] = 0; pyld[2].key[1] = 0; pyld[2].len = _VRF_LEN_ + 0; /* v=0 p=0/0 */
   3978         numkey = 3;
   3979         break;
   3980 
   3981     case 6:
   3982         {
   3983             int dup;
   3984 
   3985             if (seed == 0) {
   3986                 seed = sal_time();
   3987                 sal_srand(seed);
   3988             }
   3989             index = 0;
   3990             LOG_CLI((BSL_META("Random test: %d Seed: 0x%x \n"), id, seed));
   3991             do {
   3992                 do {
   3993                     pyld[index].key[1] = (unsigned int) sal_rand();
   3994                     pyld[index].len = (unsigned int)sal_rand() % 32;
   3995                     pyld[index].len += _VRF_LEN_;
   3996 
   3997                     if (pyld[index].len <= 32) {
   3998                         pyld[index].key[0] = 0;
   3999                         pyld[index].key[1] &= MASK(pyld[index].len);
   4000                     }
   4001 
   4002                     if (pyld[index].len > 32) {
   4003                         pyld[index].key[0] = (unsigned int)sal_rand() % 16;                        
   4004                         pyld[index].key[0] &= MASK(pyld[index].len-32); 
   4005                     }
   4006 
   4007                     dup = ut_check_duplicate(pyld, index);
   4008                     if (dup) {
   4009                             LOG_CLI((BSL_META("\n Duplicate at index[%d]:"
   4010                                               "key[0x%08x:0x%08x] Retry!!!\n"), 
   4011                                      index, pyld[index].key[0],
   4012                                      pyld[index].key[1]));
   4013                     }
   4014                 } while(dup > 0);
   4015             } while(++index < _NUM_KEY_);
   4016 
   4017             numkey = index;
   4018         }
   4019         break;
   4020 
   4021     default:
   4022         sal_free(pyld);      
   4023         return -1;
   4024     }
   4025 
   4026     trie_init(_MAX_KEY_LEN_, &trie);
   4027     LOG_CLI((BSL_META("\n Num keys to test= %d \n"), numkey));
   4028 
   4029     for(index=0; index < numkey && rv == SOC_E_NONE; index++) {
   4030         unsigned int vrf=0, i;
   4031         vrf = (pyld[index].len - _VRF_LEN_ == 32) ? 0:pyld[index].key[1] >> (pyld[index].len - _VRF_LEN_);
   4032         vrf |= pyld[index].key[0] << (32 - (pyld[index].len - _VRF_LEN_));
   4033 
   4034 #ifdef LOG
   4035         LOG_CLI((BSL_META("+ Inserted Key=0x%x 0x%x vpn=0x%x pfx=0x%x "
   4036                           "Len=%d idx:%d\n"), 
   4037                  pyld[index].key[0], pyld[index].key[1], vrf,
   4038                  pyld[index].key[1] & MASK(pyld[index].len - _VRF_LEN_), 
   4039                  pyld[index].len, index));
   4040 #endif
   4041         rv = trie_insert(trie, &pyld[index].key[0], NULL, pyld[index].len, &pyld[index].node);
   4042         if (rv != SOC_E_NONE) {
   4043             LOG_CLI((BSL_META("FAILED to Insert Key=0x%x 0x%x vpn=0x%x "
   4044                               "pfx=0x%x Len=%d idx:%d\n"), 
   4045                      pyld[index].key[0], pyld[index].key[1], vrf,
   4046                      pyld[index].key[1] & MASK(pyld[index].len - _VRF_LEN_), 
   4047                      pyld[index].len, index));
   4048         }
   4049 #define _VERBOSE_SEARCH_
   4050         /* search all keys & figure out breakage right away */
   4051         for (i=0; i <= index && rv == SOC_E_NONE; i++) {
   4052 #ifdef _VERBOSE_SEARCH_
   4053             result_key[0] = 0;
   4054             result_key[1] = 0;
   4055             result_len    = 0;
   4056             rv = trie_search_verbose(trie, &pyld[index].key[0], pyld[index].len, 
   4057                                      &pyldptr, &result_key[0], &result_len);
   4058 #else
   4059             rv = trie_search(trie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   4060 #endif
   4061             if (rv != SOC_E_NONE) {
   4062                 LOG_CLI((BSL_META("SEARCH: Key=0x%x 0x%x len %d SEARCH "
   4063                                   "idx:%d failed!!!!\n"), 
   4064                          pyld[index].key[0], pyld[index].key[1],
   4065                          pyld[index].len, index));
   4066                 break;
   4067             } else {
   4068                 assert(pyldptr == &pyld[index].node);
   4069 #ifdef _VERBOSE_SEARCH_
   4070                 if (pyld[index].key[0] != result_key[0] ||
   4071                     pyld[index].key[1] != result_key[1] ||
   4072                     pyld[index].len != result_len) {
   4073                     LOG_CLI((BSL_META(" Found key mismatches with the "
   4074                                       "expected Key !!!! \n")));
   4075                     rv = SOC_E_FAIL;
   4076                 }
   4077 #ifdef VERBOSE
   4078                 LOG_CLI((BSL_META("Lkup[%d] key/len: 0x%x 0x%x/%d "
   4079                                   "Found Key/len: 0x%x 0x%x/%d \n"),
   4080                          index ,pyld[index].key[0], pyld[index].key[1],
   4081                          pyld[index].len,
   4082                          result_key[0], result_key[1], result_len));
   4083 #endif
   4084 #endif
   4085             }
   4086         }
   4087     }
   4088 
   4089 #ifdef VERBOSE
   4090     LOG_CLI((BSL_META("\n============== TRIE DUMP ================\n")));
   4091     trie_dump(trie, NULL, NULL);
   4092     LOG_CLI((BSL_META("\n=========================================\n")));
   4093 #endif
   4094 
   4095     /* randomly pickup prefix & delete */
   4096     while(num_deleted < numkey && rv == SOC_E_NONE) {
   4097         index = sal_rand() % numkey;
   4098         if (pyld[index].len != 0xFFFFFFFF) {
   4099             rv = trie_search(trie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   4100             if (rv == SOC_E_NONE) {
   4101                 assert(pyldptr == &pyld[index].node);
   4102                 rv = trie_delete(trie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   4103 
   4104 #ifdef VERBOSE
   4105                 LOG_CLI((BSL_META("\n============== TRIE DUMP ================\n")));
   4106                 trie_dump(trie, NULL, NULL);
   4107 #endif
   4108                 if (rv == SOC_E_NONE) {
   4109 #ifdef LOG
   4110                     LOG_CLI((BSL_META("Deleted Key=0x%x 0x%x Len=%d idx:%d "
   4111                                       "Num-Key:%d\n"), 
   4112                              pyld[index].key[0], pyld[index].key[1], 
   4113                              pyld[index].len, index, num_deleted));
   4114 #endif
   4115                     pyld[index].len = 0xFFFFFFFF;
   4116                     num_deleted++;
   4117 
   4118                     /* search all keys & figure out breakage right away */
   4119                     for (index=0; index < numkey; index++) {
   4120                         if (pyld[index].len == 0xFFFFFFFF) continue;
   4121 
   4122                         rv = trie_search(trie, &pyld[index].key[0], pyld[index].len, &pyldptr);
   4123                         if (rv != SOC_E_NONE) {
   4124                             LOG_CLI((BSL_META("ALL SEARCH after delete: "
   4125                                               "Key=0x%x 0x%x len %d SEARCH "
   4126                                               "idx:%d failed!!!!\n"), 
   4127                                      pyld[index].key[0], pyld[index].key[1],
   4128                                      pyld[index].len, index));
   4129                             break;
   4130                         } else {
   4131                             assert(pyldptr == &pyld[index].node);
   4132                         }
   4133                     }
   4134                 } else {
   4135                     LOG_CLI((BSL_META("Deleted Key=0x%x 0x%x Len=%d idx:%d "
   4136                                       "FAILED!!!\n"), 
   4137                              pyld[index].key[0], pyld[index].key[1], 
   4138                              pyld[index].len, index));
   4139                     break;
   4140                 }
   4141             } else {
   4142                 LOG_CLI((BSL_META("SEARCH: Key=0x%x 0x%x len %d SEARCH "
   4143                                   "idx:%d failed!!!!\n"), 
   4144                          pyld[index].key[0], pyld[index].key[1],
   4145                          pyld[index].len, index));
   4146                 break;
   4147             }
   4148         }
   4149     }
   4150 
   4151     if (rv == SOC_E_NONE) {
   4152         LOG_CLI((BSL_META("\n TEST ID %d passed \n"), id));
   4153     }
   4154     else {  
   4155         LOG_CLI((BSL_META("\n TEST ID %d Failed Num Delete:%d !!!!!!!!\n"),
   4156                  id, num_deleted));
   4157     }
   4158 
   4159     sal_free(pyld);
   4160     trie_destroy(trie);
   4161     return rv;
   4162 }
   4163 
   4164 /**********************************************/
   4165 /* BPM unit tests */
   4166 /* test cases:
   4167  * 1 - insert pivot's with bpm bit masks
   4168  * 2 - propagate updated prefix bpm (add/del)
   4169  * 3 - fuse node bpm verification
   4170  * 4 - split bpm - nop
   4171  * 5 - */
   4172 
   4173 typedef struct _expect_datum_s {
   4174     dq_t list;
   4175     payload_t *pfx; 
   4176     trie_t *pfx_trie;
   4177 } expect_datum_t;
   4178 
   4179 int ut_bpm_build_expect_list(trie_node_t *payload, void *user_data)
   4180 {
   4181     int rv=SOC_E_NONE;
   4182 
   4183     if (payload && payload->type == PAYLOAD) {
   4184         trie_node_t *pyldptr;
   4185         payload_t *pivot;
   4186         expect_datum_t *datum = (expect_datum_t*)user_data;
   4187 
   4188         pivot = TRIE_ELEMENT_GET(payload_t*, payload, node);
   4189         /* if the inserted prefix is a best prefix, add the pivot to expected list */
   4190         rv = trie_find_lpm(datum->pfx_trie, &pivot->key[0], pivot->len, &pyldptr); 
   4191         assert(rv == SOC_E_NONE);
   4192         if (pyldptr == &datum->pfx->info.pfx_trie_node) {
   4193             /* if pivot is not equal to prefix add to expect list */
   4194             if (!(pivot->key[0] == datum->pfx->key[0] && 
   4195                   pivot->key[1] == datum->pfx->key[1] &&
   4196                   pivot->len    == datum->pfx->len)) {
   4197                 DQ_INSERT_HEAD(&datum->list, &pivot->listnode);
   4198             }
   4199         }
   4200     }
   4201 
   4202     return SOC_E_NONE;
   4203 }
   4204 
   4205 int ut_bpm_propagate_cb(trie_node_t *payload, trie_bpm_cb_info_t *cbinfo)
   4206 {
   4207     if (payload && cbinfo && payload->type == PAYLOAD) {
   4208         payload_t *pivot;
   4209         dq_p_t elem;
   4210         expect_datum_t *datum = (expect_datum_t*)cbinfo->user_data;
   4211 
   4212         pivot = TRIE_ELEMENT_GET(payload_t*, payload, node);
   4213         DQ_TRAVERSE(&datum->list, elem) {
   4214             payload_t *velem = DQ_ELEMENT_GET(payload_t*, elem, listnode); 
   4215             if (velem == pivot) {
   4216                 DQ_REMOVE(&pivot->listnode);
   4217                 break;
   4218             }
   4219         } DQ_TRAVERSE_END(&datum->list, elem);
   4220     }
   4221 
   4222     return SOC_E_NONE;
   4223 }
   4224 
   4225 int ut_bpm_propagate_empty_cb(trie_node_t *payload, trie_bpm_cb_info_t *cbinfo)
   4226 {
   4227     /* do nothing */
   4228     return SOC_E_NONE;
   4229 }
   4230 
   4231 void ut_bpm_dump_expect_list(expect_datum_t *datum, char *str)
   4232 {
   4233     dq_p_t elem;
   4234     if (datum) {
   4235         /* dump expected list */
   4236         LOG_CLI((BSL_META("%s \n"), str));
   4237         DQ_TRAVERSE(&datum->list, elem) {
   4238             payload_t *velem = DQ_ELEMENT_GET(payload_t*, elem, listnode); 
   4239             LOG_CLI((BSL_META(" Pivot: 0x%x 0x%x Len: %d \n"), 
   4240                      velem->key[0], velem->key[1], velem->len));
   4241         } DQ_TRAVERSE_END(&datum->list, elem);
   4242     }
   4243 }
   4244 
   4245 #define _MAX_TEST_PIVOTS_ (10)
   4246 #define _MAX_BKT_PFX_ (20)
   4247 #define _MAX_NUM_PICK (30)
   4248 
   4249 int tmu_taps_bpm_trie_ut(int id, unsigned int seed)
   4250 {
   4251     int rv = SOC_E_NONE, pivot=0, pfx=0, index=0, dup=0, domain=0;
   4252     trie_t *pfx_trie, *trie;
   4253     payload_t *pyld = sal_alloc(_MAX_BKT_PFX_ * _MAX_TEST_PIVOTS_ * sizeof(payload_t), "bpm-unit-test");
   4254     payload_t *pivot_pyld = sal_alloc(_MAX_TEST_PIVOTS_ * sizeof(payload_t), "bpm-unit-test");
   4255     trie_node_t *pyldptr = NULL, *newroot;
   4256     unsigned int bpm[BITS2WORDS(_MAX_KEY_LEN_)];
   4257     expect_datum_t datum;
   4258     trie_bpm_cb_info_t cbinfo;
   4259     int num_pick, bpm_pfx_len;
   4260 
   4261     sal_memset(pyld, 0, _MAX_BKT_PFX_ * _MAX_TEST_PIVOTS_ * sizeof(payload_t));
   4262     sal_memset(pivot_pyld, 0, _MAX_TEST_PIVOTS_ * sizeof(payload_t));
   4263 
   4264     if (seed == 0) {
   4265         seed = sal_time();
   4266         sal_srand(seed);
   4267     }    
   4268 
   4269     trie_init(_MAX_KEY_LEN_, &trie);
   4270     trie_init(_MAX_KEY_LEN_, &pfx_trie);
   4271 
   4272     /* populate a random pivot / prefix trie */
   4273     LOG_CLI((BSL_META("Random test: %d Seed: 0x%x \n"), id, seed));
   4274 
   4275     /* insert a vrf=0,* pivot */
   4276     pivot = 0;
   4277     pfx = 0;
   4278     pivot_pyld[pivot].key[1] = 0;
   4279     pivot_pyld[pivot].key[0] = 0;
   4280     pivot_pyld[pivot].len    = 0;
   4281     trie_init(_MAX_KEY_LEN_, &pivot_pyld[pivot].info.trie);
   4282     sal_memset(&bpm[0], 0,  BITS2WORDS(_MAX_KEY_LEN_) * sizeof(unsigned int));
   4283             
   4284     do {
   4285         rv = trie_insert(trie, &pivot_pyld[pivot].key[0], &bpm[0], 
   4286                          pivot_pyld[pivot].len, &pivot_pyld[pivot].node);
   4287         if (rv != SOC_E_NONE) {
   4288             LOG_CLI((BSL_META("FAILED to Insert PIVOT Key=0x%x 0x%x Len=%d idx:%d\n"), 
   4289                      pivot_pyld[pivot].key[0], pivot_pyld[pivot].key[1], 
   4290                      pivot_pyld[pivot].len, pivot));
   4291         } else {
   4292             if (pivot > 0) {
   4293                 /* choose a random pivot bucket to fill & split */
   4294                 domain = ((unsigned int) sal_rand()) % pivot;
   4295             } else {
   4296                 domain = 0;
   4297             }
   4298             
   4299             index = 0;
   4300             sal_memset(&bpm[0], 0,  BITS2WORDS(_MAX_KEY_LEN_) * sizeof(unsigned int));
   4301     
   4302             do {
   4303                 do {
   4304                     /* add prefix such that lpm of the prefix is the pivot to ensure
   4305                      * it goes into specific pivot domain */
   4306                     pyld[pfx+index].key[1] = (unsigned int) sal_rand();
   4307                     pyld[pfx+index].len = (unsigned int)sal_rand() % 32;
   4308                     pyld[pfx+index].len += _VRF_LEN_;
   4309 
   4310                     if (pyld[pfx+index].len <= 32) {
   4311                         pyld[pfx+index].key[0] = 0;
   4312                         pyld[pfx+index].key[1] &= MASK(pyld[pfx+index].len);
   4313                     }
   4314 
   4315                     if (pyld[pfx+index].len > 32) {
   4316                         pyld[pfx+index].key[0] = (unsigned int)sal_rand() % 16;                        
   4317                         pyld[pfx+index].key[0] &= MASK(pyld[pfx+index].len-32); 
   4318                     }
   4319 
   4320                     dup = ut_check_duplicate(pyld, pfx+index);
   4321                     if (!dup) {
   4322                         rv = trie_find_lpm(trie, &pyld[pfx+index].key[0], pyld[pfx+index].len, &pyldptr); 
   4323                         if (SOC_FAILURE(rv)) {
   4324                             LOG_CLI((BSL_META("\n !! Failed to find LPM pivot for "
   4325                                               "index[%d]:key[0x%08x:0x%08x] !!!!\n"),
   4326                                      pfx, pyld[pfx+index].key[0],
   4327                                      pyld[pfx+index].key[1]));
   4328                         } 
   4329                     }
   4330                 } while ((dup || (pyldptr != &pivot_pyld[domain].node)) && SOC_SUCCESS(rv));
   4331 
   4332                 if (SOC_SUCCESS(rv)) {
   4333                     rv =  trie_insert(pivot_pyld[domain].info.trie,
   4334                                       &pyld[pfx+index].key[0], NULL, 
   4335                                       pyld[pfx+index].len, &pyld[pfx+index].node);
   4336                     if (SOC_FAILURE(rv)) {
   4337                         LOG_CLI((BSL_META("\n !! Failed insert prefix into pivot trie"
   4338                                           " index[%d]:key[0x%08x:0x%08x] !!!!\n"),
   4339                                  pfx+index, pyld[pfx+index].key[0],
   4340                                  pyld[pfx+index].key[1]));
   4341                     } else {
   4342                         rv =  trie_insert(pfx_trie,
   4343                                           &pyld[pfx+index].key[0], NULL, 
   4344                                           pyld[pfx+index].len, &pyld[pfx+index].info.pfx_trie_node);     
   4345                         if (SOC_FAILURE(rv)) {
   4346                             LOG_CLI((BSL_META("\n !! Failed insert prefix into "
   4347                                               "prefix trie"
   4348                                               " index[%d]:key[0x%08x:0x%08x] !!!!\n"),
   4349                                      pfx+index, pyld[pfx+index].key[0],
   4350                                      pyld[pfx+index].key[1]));
   4351                         } else {
   4352                             index++;
   4353                         }                      
   4354                     }
   4355                 }
   4356 
   4357             } while(index < (_MAX_BKT_PFX_/2 - 1) && SOC_SUCCESS(rv));
   4358 
   4359             /* try to populate prefix where p == v */
   4360             if (pivot > 0) {
   4361                 /* 25% probability */
   4362                 if (((unsigned int) sal_rand() % 4) == 0) {
   4363                 }
   4364             }
   4365 
   4366 #ifdef VERBOSE
   4367             LOG_CLI((BSL_META("### Split Domain ID: %d \n"), domain));
   4368             for (i=0; i <= pivot; i++) {
   4369                 LOG_CLI((BSL_META("\n --- TRIE domain dump: Pivot: 0x%x 0x%x "
   4370                                   "len=%d ----- \n"),
   4371                          pivot_pyld[i].key[0], pivot_pyld[i].key[1],
   4372                          pivot_pyld[i].len));
   4373                 trie_dump(pivot_pyld[i].info.trie, ut_print_payload_node, NULL);
   4374             }
   4375 #endif
   4376 
   4377             if (SOC_SUCCESS(rv) && ++pivot < _MAX_TEST_PIVOTS_) {
   4378                 pfx += index;
   4379                 trie_init(_MAX_KEY_LEN_, &pivot_pyld[pivot].info.trie);
   4380                 /* split the domain & insert a new pivot */
   4381                 rv = trie_split(pivot_pyld[domain].info.trie,
   4382 				_MAX_KEY_LEN_, FALSE,
   4383                                 &pivot_pyld[pivot].key[0], 
   4384                                 &pivot_pyld[pivot].len, &newroot, 
   4385                                 &bpm[0], FALSE);
   4386                 if (SOC_SUCCESS(rv)) {
   4387                     pivot_pyld[pivot].info.trie->trie = newroot;
   4388                     pivot_pyld[pivot].info.trie->v6_key = pivot_pyld[domain].info.trie->v6_key;
   4389                     LOG_CLI((BSL_META("BPM for split pivot: 0x%x 0x%x / "
   4390                                       "%d = [0x%x 0x%x] \n"),
   4391                              pivot_pyld[pivot].key[0],
   4392                              pivot_pyld[pivot].key[1],
   4393                              pivot_pyld[pivot].len, bpm[0], bpm[1]));
   4394                 } else {
   4395                     LOG_CLI((BSL_META("\n !!! Failed to split domain trie for "
   4396                                       "domain: %d !!!\n"), domain));
   4397                 }
   4398             }
   4399         }
   4400     } while(pivot < _MAX_TEST_PIVOTS_ && SOC_SUCCESS(rv));
   4401 
   4402     /* pick up the root node on pivot trie & add a prefix shorter than the nearest child.
   4403      * This is ripple & create huge propagation */
   4404     /* insert *\/1 into the * bucket so huge propagation kicks in */
   4405     pyld[pfx].key[1] = (unsigned int) sal_rand() % 1;
   4406     pyld[pfx].key[0] = 0;
   4407     pyld[pfx].len    = 1;
   4408     do {
   4409         dup = ut_check_duplicate(pyld, pfx);
   4410         if (!dup) {
   4411             rv = trie_find_lpm(trie, &pyld[pfx].key[0], pyld[pfx].len, &pyldptr); 
   4412             if (SOC_FAILURE(rv)) {
   4413                 LOG_CLI((BSL_META("\n !! Failed to find LPM pivot for "
   4414                                   "index[%d]:key[0x%08x:0x%08x] !!!!\n"),
   4415                          pfx, pyld[pfx].key[0], pyld[pfx].key[1]));
   4416             } 
   4417         } else {
   4418             pyld[pfx].len++;
   4419         }
   4420     } while(dup && SOC_SUCCESS(rv));
   4421 
   4422     if (SOC_SUCCESS(rv)) {
   4423         rv =  trie_insert(pfx_trie,
   4424                           &pyld[pfx].key[0], NULL, 
   4425                           pyld[pfx].len, &pyld[pfx].info.pfx_trie_node);
   4426         if (SOC_FAILURE(rv)) {
   4427             LOG_CLI((BSL_META("\n !! Failed insert prefix into pivot trie"
   4428                               " index[%d]:key[0x%08x:0x%08x] !!!!\n"),
   4429                      pfx, pyld[pfx].key[0], pyld[pfx].key[1]));
   4430         } else {
   4431             DQ_INIT(&datum.list);
   4432             datum.pfx = &pyld[pfx];
   4433             datum.pfx_trie = pfx_trie;
   4434             /* create expected list of pivot to be propagated */
   4435             trie_traverse(trie, ut_bpm_build_expect_list, &datum, _TRIE_PREORDER_TRAVERSE);
   4436 
   4437             /* dump expected list */
   4438             ut_bpm_dump_expect_list(&datum, "-- Expected Propagation List --");
   4439         }
   4440     }
   4441 
   4442     sal_memset(&cbinfo, 0, sizeof(trie_bpm_cb_info_t));
   4443     cbinfo.user_data = &datum;
   4444     cbinfo.pfx = &pyld[pfx].key[0];
   4445     cbinfo.len = pyld[pfx].len;
   4446     if (pyldptr == NULL) {
   4447         assert(0); /* check here for coverity */
   4448     }
   4449     rv = trie_pivot_propagate_prefix(pyldptr,
   4450                                (TRIE_ELEMENT_GET(payload_t*, pyldptr, node))->len,
   4451                                &pyld[pfx].key[0], pyld[pfx].len,
   4452                                1, ut_bpm_propagate_cb, &cbinfo);
   4453     if (DQ_EMPTY(&datum.list)) {
   4454         LOG_CLI((BSL_META("++ Propagation Test Passed \n")));
   4455     } else {
   4456         LOG_CLI((BSL_META("!!!!! Propagation Test FAILED !!!!!\n")));
   4457         rv = SOC_E_FAIL;
   4458         ut_bpm_dump_expect_list(&datum, "!! Zombies on Propagation List !!");
   4459         assert(0);
   4460     }
   4461 
   4462     /* propagate a shorter prefix of an existing pivot 
   4463      * we should find the bpm
   4464      */
   4465     pfx++;
   4466     num_pick = 0;
   4467     do {
   4468 	/* randomly pick a pivot */
   4469 	index = ((unsigned int) sal_rand()) % pivot;
   4470 	
   4471 	/* create a prefix shorter */
   4472 	pyld[pfx].len    = ((unsigned int) sal_rand()) % pivot_pyld[index].len;
   4473 	pyld[pfx].key[1] = pivot_pyld[index].key[1]>>(pivot_pyld[index].len - pyld[pfx].len);
   4474 	pyld[pfx].key[0] = 0;
   4475 
   4476 	if (pyld[pfx].len >= 1) {
   4477 	    /* propagate add len=0 */
   4478 	    rv = trie_pivot_propagate_prefix(trie->trie,
   4479 				       (TRIE_ELEMENT_GET(payload_t*, trie->trie, node))->len,
   4480 				       &pyld[pfx].key[0], 0,
   4481 				       1, ut_bpm_propagate_empty_cb, 
   4482 				       &cbinfo);
   4483 
   4484 	    if (SOC_FAILURE(rv)) {
   4485             LOG_CLI((BSL_META("!!!!! BPM search Test FAILED to propagate "
   4486                               "add len=0!!!!!\n")));
   4487 		assert(0);
   4488 	    }
   4489 
   4490 	    /* propagate add */
   4491 	    rv = trie_pivot_propagate_prefix(trie->trie,
   4492 				       (TRIE_ELEMENT_GET(payload_t*, trie->trie, node))->len,
   4493 				       &pyld[pfx].key[0], pyld[pfx].len,
   4494 				       1, ut_bpm_propagate_empty_cb, 
   4495 				       &cbinfo);
   4496 	    if (SOC_FAILURE(rv)) {
   4497             LOG_CLI((BSL_META("!!!!! BPM search Test FAILED to propagate add \n"
   4498                               " index[%d]:key[0x%08x:0x%08x] len=%d!!!!\n"),
   4499                      pfx, pyld[pfx].key[0], pyld[pfx].key[1], pyld[pfx].len));
   4500 		assert(0);
   4501 	    }
   4502 
   4503 	    /* perform bpm lookup on the pivot, we should find the pyld[pfx].len */
   4504 	    rv = trie_find_prefix_bpm(trie, (unsigned int *)&(pivot_pyld[index].key[0]),
   4505 				      pivot_pyld[index].len, (unsigned int *)&bpm_pfx_len);
   4506 	    if (SOC_FAILURE(rv) || (bpm_pfx_len != pyld[pfx].len)) {
   4507             LOG_CLI((BSL_META("!!!!! BPM search Test FAILDED after propagate "
   4508                               "add !!!!!\n")));
   4509 		assert(0);		
   4510 	    }
   4511 
   4512 	    /* propagate delete */
   4513 	    rv = trie_pivot_propagate_prefix(trie->trie,
   4514 				       (TRIE_ELEMENT_GET(payload_t*, trie->trie, node))->len,
   4515 				       &pyld[pfx].key[0], pyld[pfx].len,
   4516 				       0, ut_bpm_propagate_empty_cb, 
   4517 				       &cbinfo);
   4518 	    
   4519 	    if (SOC_FAILURE(rv)) {
   4520             LOG_CLI((BSL_META("!!!!! BPM search Test FAILED to propagate add \n"
   4521                               " index[%d]:key[0x%08x:0x%08x] len=%d!!!!\n"),
   4522                      pfx, pyld[pfx].key[0], pyld[pfx].key[1], pyld[pfx].len));
   4523 		assert(0);
   4524 	    }
   4525 
   4526 	    /* perform bpm lookup on the pivot, we should find the len==0 */
   4527 	    rv = trie_find_prefix_bpm(trie, (unsigned int *)&(pivot_pyld[index].key[0]),
   4528 				      pivot_pyld[index].len, (unsigned int *)&bpm_pfx_len);
   4529 	    if (SOC_FAILURE(rv) || (bpm_pfx_len != 0)) {
   4530             LOG_CLI((BSL_META("!!!!! BPM search Test FAILDED after propagate "
   4531                               "delete !!!!!\n")));
   4532 		assert(0);		
   4533 	    }
   4534 
   4535 	    num_pick = _MAX_NUM_PICK+1;
   4536 	}
   4537 	num_pick++;
   4538     } while(num_pick<_MAX_NUM_PICK);
   4539 
   4540     if (num_pick <= _MAX_NUM_PICK) {
   4541         LOG_CLI((BSL_META("!!!!! BPM search Test 2 Skipped after "
   4542                           "tried %d times!!!!!\n"), _MAX_NUM_PICK));	
   4543     } else {
   4544         LOG_CLI((BSL_META("!!!!! BPM search Test 2 Passed!!!!!\n")));	
   4545     }
   4546 
   4547 #ifdef VERBOSE
   4548     LOG_CLI((BSL_META("\n ----- Prefix Trie dump ----- \n")));
   4549     trie_dump(pfx_trie, ut_print_prefix_payload_node, NULL);
   4550 #endif
   4551 
   4552     LOG_CLI((BSL_META("\n ++++++++ Trie dump ++++++++ \n")));
   4553     trie_dump(trie, ut_print_payload_node, NULL);
   4554 
   4555     /* clean up */
   4556     for (index=0; index < pivot; index++) {
   4557 #ifdef VERBOSE
   4558         LOG_CLI((BSL_META("\n ddddddd dump dddddddd \n")));
   4559         trie_dump(pivot_pyld[index].info.trie, ut_print_payload_node, NULL);
   4560 #endif
   4561         trie_destroy(pivot_pyld[index].info.trie);
   4562     }
   4563 
   4564     sal_free(pyld);
   4565     sal_free(pivot_pyld);
   4566     trie_destroy(trie);
   4567     trie_destroy(pfx_trie);
   4568     return rv;
   4569 }
   4570 
   4571 /**********************************************/
   4572 #endif 
   4573 
   4574 #endif /* BCM_TRIDENT2_SUPPORT */
   4575 #endif /* ALPM_ENABLE */
   4576