1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/trie.h> 30*7c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/filters.h> 31*7c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/classifier.h> 32*7c478bd9Sstevel@tonic-gate #include <inet/ip6.h> 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate /* trie data structure used for classifying IP addresses and TCP/UDP ports */ 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #define ZERO 0 37*7c478bd9Sstevel@tonic-gate #define ONE 1 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate /* Statics */ 41*7c478bd9Sstevel@tonic-gate static void t_split(node_t **, uint8_t, uint8_t); 42*7c478bd9Sstevel@tonic-gate static boolean_t t_traverse_delete(node_t **, uint8_t, key_t, uint32_t, 43*7c478bd9Sstevel@tonic-gate uint32_t, trie_id_t **); 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * create_node(flag) 47*7c478bd9Sstevel@tonic-gate * 48*7c478bd9Sstevel@tonic-gate * generates a pointer to a new trie node 49*7c478bd9Sstevel@tonic-gate * flag is passed to kmem_alloc 50*7c478bd9Sstevel@tonic-gate * returns NULL to signify memory error 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate node_t * 53*7c478bd9Sstevel@tonic-gate create_node(int flag) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate node_t *buf = kmem_cache_alloc(trie_node_cache, flag); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 58*7c478bd9Sstevel@tonic-gate return (NULL); 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate buf->elements = NULL; 61*7c478bd9Sstevel@tonic-gate buf->zero = NULL; 62*7c478bd9Sstevel@tonic-gate buf->one = NULL; 63*7c478bd9Sstevel@tonic-gate buf->pos = 0; 64*7c478bd9Sstevel@tonic-gate buf->bits = 0; 65*7c478bd9Sstevel@tonic-gate buf->val = 0; 66*7c478bd9Sstevel@tonic-gate buf->mask = 0; 67*7c478bd9Sstevel@tonic-gate buf->isroot = 0; 68*7c478bd9Sstevel@tonic-gate return (buf); 69*7c478bd9Sstevel@tonic-gate } 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate /* 73*7c478bd9Sstevel@tonic-gate * t_split(c_node, pos, key_len) 74*7c478bd9Sstevel@tonic-gate * 75*7c478bd9Sstevel@tonic-gate * performs a split on c_node for the following three cases: 76*7c478bd9Sstevel@tonic-gate * 1 a mismatch occured between the insert key and the value at the node 77*7c478bd9Sstevel@tonic-gate * 2 the insert key specifies a shorter key than the one at the node 78*7c478bd9Sstevel@tonic-gate * 3 the insert key specifies a longer key than the one at the node 79*7c478bd9Sstevel@tonic-gate * cases 1 and 2 are handled in the same way 80*7c478bd9Sstevel@tonic-gate * when t_split returns, c_node->one and c_node->zero must != NULL 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * (note: we assume a key_len = n (where in the real world n = 16 | 32), 83*7c478bd9Sstevel@tonic-gate * and a "key" in this example is actaully some value of key_len n that 84*7c478bd9Sstevel@tonic-gate * has its high order bits masked. 85*7c478bd9Sstevel@tonic-gate * For example: key = 1011 with key_len = 8, would actaully be the key:mask 86*7c478bd9Sstevel@tonic-gate * combo 1011xxxx:11110000. I am using short keys for ease of example) 87*7c478bd9Sstevel@tonic-gate * Case 1 and 2: 88*7c478bd9Sstevel@tonic-gate * 89*7c478bd9Sstevel@tonic-gate * assume 8 bit keys for all examples 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * trie A contains keys 111011, 0, 10 92*7c478bd9Sstevel@tonic-gate * * 93*7c478bd9Sstevel@tonic-gate * / \ 94*7c478bd9Sstevel@tonic-gate * * 95*7c478bd9Sstevel@tonic-gate * / \ 96*7c478bd9Sstevel@tonic-gate * * * bits = 4 pos = 5 val = 1011 mask = 00111100 97*7c478bd9Sstevel@tonic-gate * inserting 111100 would result in the following split 98*7c478bd9Sstevel@tonic-gate * * 99*7c478bd9Sstevel@tonic-gate * / \ 100*7c478bd9Sstevel@tonic-gate * * 101*7c478bd9Sstevel@tonic-gate * / \ 102*7c478bd9Sstevel@tonic-gate * * bits = 1 pos = 5 val = 1 mask = 00100000 103*7c478bd9Sstevel@tonic-gate * / \ 104*7c478bd9Sstevel@tonic-gate * bits = 2 pos = 3 val=11* * (to be inserted: (bits = 2 pos = 3 val = 00 105*7c478bd9Sstevel@tonic-gate * mask = 00001100 mask = 00001100)) 106*7c478bd9Sstevel@tonic-gate * 107*7c478bd9Sstevel@tonic-gate * Case 3: 108*7c478bd9Sstevel@tonic-gate * 109*7c478bd9Sstevel@tonic-gate * trie A same as above, before insert 110*7c478bd9Sstevel@tonic-gate * inserting key 11101111 would results in the following split 111*7c478bd9Sstevel@tonic-gate * * 112*7c478bd9Sstevel@tonic-gate * / \ 113*7c478bd9Sstevel@tonic-gate * * 114*7c478bd9Sstevel@tonic-gate * / \ 115*7c478bd9Sstevel@tonic-gate * * * bits = 4 pos = 5 val = 1011 mask = 00111100 116*7c478bd9Sstevel@tonic-gate * / \ 117*7c478bd9Sstevel@tonic-gate * * * (to be inserted: bits = 1 pos = 0 val = 1 mask = 00000001) 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 120*7c478bd9Sstevel@tonic-gate static void 121*7c478bd9Sstevel@tonic-gate t_split(node_t **c_node, uint8_t pos, uint8_t key_len) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate uint8_t old_bits = 0; 124*7c478bd9Sstevel@tonic-gate uint8_t i; 125*7c478bd9Sstevel@tonic-gate int bit; 126*7c478bd9Sstevel@tonic-gate node_t *nodep = *c_node; 127*7c478bd9Sstevel@tonic-gate node_t *tnodep = NULL; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* check if case is that the mask is longer */ 130*7c478bd9Sstevel@tonic-gate if (pos == (nodep->pos - nodep->bits)) { 131*7c478bd9Sstevel@tonic-gate /* pos is past the last bit covered at this node */ 132*7c478bd9Sstevel@tonic-gate ASSERT(nodep->one == NULL); 133*7c478bd9Sstevel@tonic-gate ASSERT(nodep->zero == NULL); 134*7c478bd9Sstevel@tonic-gate nodep->one = create_node(KM_SLEEP); 135*7c478bd9Sstevel@tonic-gate nodep->zero = create_node(KM_SLEEP); 136*7c478bd9Sstevel@tonic-gate } else { /* pos > (nodep->pos - nodep->bits) */ 137*7c478bd9Sstevel@tonic-gate old_bits = nodep->bits; /* save old bits entry */ 138*7c478bd9Sstevel@tonic-gate /* nodep->pos will remain the same */ 139*7c478bd9Sstevel@tonic-gate nodep->bits = nodep->pos - pos; 140*7c478bd9Sstevel@tonic-gate /* find the mismatch bit */ 141*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(nodep->val, pos, key_len); 142*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { 143*7c478bd9Sstevel@tonic-gate if ((nodep->one == NULL) && (nodep->zero == NULL)) { 144*7c478bd9Sstevel@tonic-gate nodep->one = create_node(KM_SLEEP); 145*7c478bd9Sstevel@tonic-gate nodep->zero = create_node(KM_SLEEP); 146*7c478bd9Sstevel@tonic-gate } else { 147*7c478bd9Sstevel@tonic-gate tnodep = create_node(KM_SLEEP); 148*7c478bd9Sstevel@tonic-gate tnodep->one = nodep->one; 149*7c478bd9Sstevel@tonic-gate tnodep->zero = nodep->zero; 150*7c478bd9Sstevel@tonic-gate nodep->zero = tnodep; 151*7c478bd9Sstevel@tonic-gate nodep->one = create_node(KM_SLEEP); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate /* pos is before the last bit covered at this node */ 154*7c478bd9Sstevel@tonic-gate nodep->zero->pos = pos - 1; /* link is one bit */ 155*7c478bd9Sstevel@tonic-gate /* bits gets remaining bits minus the link */ 156*7c478bd9Sstevel@tonic-gate nodep->zero->bits = (old_bits - nodep->bits) - 1; 157*7c478bd9Sstevel@tonic-gate /* set bits that are covered by this node */ 158*7c478bd9Sstevel@tonic-gate for (i = 0; i < nodep->zero->bits; ++i) { 159*7c478bd9Sstevel@tonic-gate SETBIT(nodep->zero->val, 160*7c478bd9Sstevel@tonic-gate (nodep->zero->pos - i), 161*7c478bd9Sstevel@tonic-gate EXTRACTBIT(nodep->val, 162*7c478bd9Sstevel@tonic-gate (nodep->zero->pos - i), key_len), 163*7c478bd9Sstevel@tonic-gate key_len); 164*7c478bd9Sstevel@tonic-gate SETBIT(nodep->zero->mask, 165*7c478bd9Sstevel@tonic-gate (nodep->zero->pos - i), 1, key_len); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate nodep->zero->elements = nodep->elements; 168*7c478bd9Sstevel@tonic-gate nodep->elements = NULL; 169*7c478bd9Sstevel@tonic-gate } else { /* bit == ONE */ 170*7c478bd9Sstevel@tonic-gate if ((nodep->one == NULL) && (nodep->zero == NULL)) { 171*7c478bd9Sstevel@tonic-gate nodep->one = create_node(KM_SLEEP); 172*7c478bd9Sstevel@tonic-gate nodep->zero = create_node(KM_SLEEP); 173*7c478bd9Sstevel@tonic-gate } else { 174*7c478bd9Sstevel@tonic-gate tnodep = create_node(KM_SLEEP); 175*7c478bd9Sstevel@tonic-gate tnodep->one = nodep->one; 176*7c478bd9Sstevel@tonic-gate tnodep->zero = nodep->zero; 177*7c478bd9Sstevel@tonic-gate nodep->one = tnodep; 178*7c478bd9Sstevel@tonic-gate nodep->zero = create_node(KM_SLEEP); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate /* pos is before the last bit covered at this node */ 181*7c478bd9Sstevel@tonic-gate nodep->one->pos = pos - 1; /* link is one bit */ 182*7c478bd9Sstevel@tonic-gate /* bits gets remaining bits minus the link */ 183*7c478bd9Sstevel@tonic-gate nodep->one->bits = (old_bits - nodep->bits) - 1; 184*7c478bd9Sstevel@tonic-gate /* set bits that are covered by this node */ 185*7c478bd9Sstevel@tonic-gate for (i = 0; i < nodep->one->bits; ++i) { 186*7c478bd9Sstevel@tonic-gate SETBIT(nodep->one->val, (nodep->one->pos - i), 187*7c478bd9Sstevel@tonic-gate EXTRACTBIT(nodep->val, 188*7c478bd9Sstevel@tonic-gate (nodep->one->pos - i), key_len), 189*7c478bd9Sstevel@tonic-gate key_len); 190*7c478bd9Sstevel@tonic-gate SETBIT(nodep->one->mask, 191*7c478bd9Sstevel@tonic-gate (nodep->one->pos - i), 1, key_len); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate nodep->one->elements = nodep->elements; 194*7c478bd9Sstevel@tonic-gate nodep->elements = NULL; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* clear bits no longer covered by this node, from pos=>0 */ 198*7c478bd9Sstevel@tonic-gate for (i = 0; i <= pos; ++i) { 199*7c478bd9Sstevel@tonic-gate UNSETBIT(nodep->val, i, key_len); 200*7c478bd9Sstevel@tonic-gate UNSETBIT(nodep->mask, i, key_len); 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* 206*7c478bd9Sstevel@tonic-gate * t_insert(tid, id, key, mask) 207*7c478bd9Sstevel@tonic-gate * 208*7c478bd9Sstevel@tonic-gate * inserts a new value, id, into the trie, tid->trie with the input key 209*7c478bd9Sstevel@tonic-gate * - if node exists, id is appended to element list at the node, if id does 210*7c478bd9Sstevel@tonic-gate * not already exist. 211*7c478bd9Sstevel@tonic-gate * - if node does not exist, a new node is created and id is the head of a new 212*7c478bd9Sstevel@tonic-gate * element list 213*7c478bd9Sstevel@tonic-gate * return DONTCARE_VALUE if mask == 0, otherwise NORMAL_VALUE 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate int 216*7c478bd9Sstevel@tonic-gate t_insert(trie_id_t *tid, key_t id, uint32_t key, uint32_t mask) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate node_t *c_node; 219*7c478bd9Sstevel@tonic-gate int bit; 220*7c478bd9Sstevel@tonic-gate uint8_t pos; 221*7c478bd9Sstevel@tonic-gate uint8_t key_len = (uint8_t)tid->key_len; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* don't insert if don't care */ 224*7c478bd9Sstevel@tonic-gate if (mask == 0) { 225*7c478bd9Sstevel@tonic-gate ++tid->stats.num_dontcare; 226*7c478bd9Sstevel@tonic-gate return (DONTCARE_VALUE); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_WRITER); 230*7c478bd9Sstevel@tonic-gate c_node = tid->trie; /* point at trie root */ 231*7c478bd9Sstevel@tonic-gate key &= mask; /* apply mask */ 232*7c478bd9Sstevel@tonic-gate /* traverse trie to the correct position */ 233*7c478bd9Sstevel@tonic-gate for (pos = key_len; pos > 0; --pos) { 234*7c478bd9Sstevel@tonic-gate /* check if bit is significant */ 235*7c478bd9Sstevel@tonic-gate /* bit in key is significant if it is covered by the mask */ 236*7c478bd9Sstevel@tonic-gate if (EXTRACTBIT(mask, (pos - 1), key_len) != 1) { 237*7c478bd9Sstevel@tonic-gate /* check if this is a path compressed internal node */ 238*7c478bd9Sstevel@tonic-gate if (c_node->bits > 0) { 239*7c478bd9Sstevel@tonic-gate /* check if split is needed */ 240*7c478bd9Sstevel@tonic-gate if ((pos - 1) > (c_node->pos - c_node->bits)) { 241*7c478bd9Sstevel@tonic-gate t_split(&c_node, (pos - 1), key_len); 242*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one != NULL); 243*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero != NULL); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate break; 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate /* extra bit at current position */ 249*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(key, (pos - 1), key_len); 250*7c478bd9Sstevel@tonic-gate /* check if this is a path compressed internal node */ 251*7c478bd9Sstevel@tonic-gate if (c_node->bits > 0) { /* path compressed node */ 252*7c478bd9Sstevel@tonic-gate /* check if split is needed */ 253*7c478bd9Sstevel@tonic-gate if ((pos - 1) > (c_node->pos - c_node->bits)) { 254*7c478bd9Sstevel@tonic-gate /* testing for mismatch */ 255*7c478bd9Sstevel@tonic-gate if (bit != EXTRACTBIT(c_node->val, (pos - 1), 256*7c478bd9Sstevel@tonic-gate key_len)) { 257*7c478bd9Sstevel@tonic-gate t_split(&c_node, (pos - 1), key_len); 258*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one != NULL); 259*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero != NULL); 260*7c478bd9Sstevel@tonic-gate } else { 261*7c478bd9Sstevel@tonic-gate continue; /* bits match, so go on */ 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate } else if ((pos - 1) == (c_node->pos - c_node->bits)) { 264*7c478bd9Sstevel@tonic-gate /* check if at a leaf node with elements */ 265*7c478bd9Sstevel@tonic-gate if ((c_node->one == NULL) && 266*7c478bd9Sstevel@tonic-gate (c_node->zero == NULL) && 267*7c478bd9Sstevel@tonic-gate (c_node->elements != NULL)) { 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * this case occurs when mask for key 270*7c478bd9Sstevel@tonic-gate * is longer than mask for key at 271*7c478bd9Sstevel@tonic-gate * current node 272*7c478bd9Sstevel@tonic-gate */ 273*7c478bd9Sstevel@tonic-gate t_split(&c_node, (pos - 1), key_len); 274*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one != NULL); 275*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero != NULL); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate } /* else continue onto child */ 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { 280*7c478bd9Sstevel@tonic-gate if (c_node->zero == NULL) { /* leaf node */ 281*7c478bd9Sstevel@tonic-gate if (c_node->bits == 0) { 282*7c478bd9Sstevel@tonic-gate c_node->pos = (pos - 1); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate c_node->bits++; 285*7c478bd9Sstevel@tonic-gate /* bit at pos for node value should be 0 */ 286*7c478bd9Sstevel@tonic-gate UNSETBIT(c_node->val, (pos - 1), key_len); 287*7c478bd9Sstevel@tonic-gate SETBIT(c_node->mask, (pos - 1), 1, key_len); 288*7c478bd9Sstevel@tonic-gate } else { 289*7c478bd9Sstevel@tonic-gate /* assert that trie is path compressed */ 290*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one != NULL); 291*7c478bd9Sstevel@tonic-gate c_node = c_node->zero; /* internal node */ 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate } else { /* ONE bit */ 294*7c478bd9Sstevel@tonic-gate if (c_node->one == NULL) { /* leaf node */ 295*7c478bd9Sstevel@tonic-gate if (c_node->bits == 0) { 296*7c478bd9Sstevel@tonic-gate c_node->pos = (pos - 1); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate c_node->bits++; 299*7c478bd9Sstevel@tonic-gate /* bit at pos for node value should be 1 */ 300*7c478bd9Sstevel@tonic-gate SETBIT(c_node->val, (pos - 1), 1, key_len); 301*7c478bd9Sstevel@tonic-gate SETBIT(c_node->mask, (pos - 1), 1, key_len); 302*7c478bd9Sstevel@tonic-gate } else { 303*7c478bd9Sstevel@tonic-gate /* assert that trie is path compressed */ 304*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero != NULL); 305*7c478bd9Sstevel@tonic-gate c_node = c_node->one; /* internal node */ 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate /* insert at node */ 310*7c478bd9Sstevel@tonic-gate (void) ipgpc_list_insert(&c_node->elements, id); 311*7c478bd9Sstevel@tonic-gate /* update stats */ 312*7c478bd9Sstevel@tonic-gate ++tid->stats.num_inserted; 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * check if this is the first key to be inserted that is not a 315*7c478bd9Sstevel@tonic-gate * don't care (*) 316*7c478bd9Sstevel@tonic-gate */ 317*7c478bd9Sstevel@tonic-gate if (tid->info.dontcareonly == B_TRUE) { 318*7c478bd9Sstevel@tonic-gate tid->info.dontcareonly = B_FALSE; 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 321*7c478bd9Sstevel@tonic-gate return (NORMAL_VALUE); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate /* 325*7c478bd9Sstevel@tonic-gate * t_insert6(tid, id, key, mask) 326*7c478bd9Sstevel@tonic-gate * 327*7c478bd9Sstevel@tonic-gate * specific to inserting keys of 128 bits in length 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate int 330*7c478bd9Sstevel@tonic-gate t_insert6(trie_id_t *tid, key_t id, in6_addr_t key, in6_addr_t mask) 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate node_t *c_node; 333*7c478bd9Sstevel@tonic-gate int bit, i; 334*7c478bd9Sstevel@tonic-gate uint8_t pos; 335*7c478bd9Sstevel@tonic-gate uint8_t type_len = IP_ABITS; 336*7c478bd9Sstevel@tonic-gate in6_addr_t zero_addr = IN6ADDR_ANY_INIT; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* don't insert if don't care */ 339*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&mask, &zero_addr)) { 340*7c478bd9Sstevel@tonic-gate ++tid->stats.num_dontcare; 341*7c478bd9Sstevel@tonic-gate return (DONTCARE_VALUE); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_WRITER); 345*7c478bd9Sstevel@tonic-gate c_node = tid->trie; /* point at root of trie */ 346*7c478bd9Sstevel@tonic-gate V6_MASK_COPY(key, mask, key); /* apply mask to key */ 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * A IPv6 address is structured as an array of four uint32_t 349*7c478bd9Sstevel@tonic-gate * values. The highest order of the bits are located in array[0] 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; ++i) { 352*7c478bd9Sstevel@tonic-gate /* traverse trie to the correct position */ 353*7c478bd9Sstevel@tonic-gate for (pos = type_len; pos > 0; --pos) { 354*7c478bd9Sstevel@tonic-gate /* check if bit is significant */ 355*7c478bd9Sstevel@tonic-gate if (EXTRACTBIT(mask.s6_addr32[i], (pos - 1), type_len) 356*7c478bd9Sstevel@tonic-gate != ONE) { 357*7c478bd9Sstevel@tonic-gate break; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(key.s6_addr32[i], (pos - 1), type_len); 360*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { 361*7c478bd9Sstevel@tonic-gate if (c_node->zero == NULL) { 362*7c478bd9Sstevel@tonic-gate c_node->zero = create_node(KM_SLEEP); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate c_node = c_node->zero; 365*7c478bd9Sstevel@tonic-gate } else { /* ONE bit */ 366*7c478bd9Sstevel@tonic-gate if (c_node->one == NULL) { 367*7c478bd9Sstevel@tonic-gate c_node->one = create_node(KM_SLEEP); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate c_node = c_node->one; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate /* insert at node */ 375*7c478bd9Sstevel@tonic-gate (void) ipgpc_list_insert(&c_node->elements, id); 376*7c478bd9Sstevel@tonic-gate /* update stats */ 377*7c478bd9Sstevel@tonic-gate ++tid->stats.num_inserted; 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * check if this is the first key to be inserted that is not a 380*7c478bd9Sstevel@tonic-gate * don't care (*) 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate if (tid->info.dontcareonly == B_TRUE) { 383*7c478bd9Sstevel@tonic-gate tid->info.dontcareonly = B_FALSE; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 386*7c478bd9Sstevel@tonic-gate return (NORMAL_VALUE); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * t_traverse_delete(in_node, pos, id, key, mask, tid) 391*7c478bd9Sstevel@tonic-gate * 392*7c478bd9Sstevel@tonic-gate * used to traverse to the node containing id, as found under key 393*7c478bd9Sstevel@tonic-gate * once id is found, it is removed from the trie. 394*7c478bd9Sstevel@tonic-gate * Upon removing the id from a given node in the trie, path compression 395*7c478bd9Sstevel@tonic-gate * will be applied to nodes that are no longer compressed. 396*7c478bd9Sstevel@tonic-gate * If the id is successfully removed, tid->stats are updated 397*7c478bd9Sstevel@tonic-gate */ 398*7c478bd9Sstevel@tonic-gate static boolean_t 399*7c478bd9Sstevel@tonic-gate t_traverse_delete(node_t **in_node, uint8_t pos, key_t id, uint32_t key, 400*7c478bd9Sstevel@tonic-gate uint32_t mask, trie_id_t **tid) 401*7c478bd9Sstevel@tonic-gate { 402*7c478bd9Sstevel@tonic-gate node_t *c_node = *in_node; 403*7c478bd9Sstevel@tonic-gate node_t *t_node; 404*7c478bd9Sstevel@tonic-gate int bit; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate if (c_node == NULL) { 407*7c478bd9Sstevel@tonic-gate return (B_FALSE); /* base failure case */ 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate /* we've found the node the id is probably at */ 411*7c478bd9Sstevel@tonic-gate if ((pos == 0) || 412*7c478bd9Sstevel@tonic-gate (EXTRACTBIT(mask, (pos - 1), (uint8_t)(*tid)->key_len) != 1)) { 413*7c478bd9Sstevel@tonic-gate if (ipgpc_list_remove(&c_node->elements, id) == B_FALSE) { 414*7c478bd9Sstevel@tonic-gate ipgpc0dbg(("t_traverse_delete: id %d does not " \ 415*7c478bd9Sstevel@tonic-gate "exist in trie\n", id)); 416*7c478bd9Sstevel@tonic-gate return (B_FALSE); /* key does not exist at node */ 417*7c478bd9Sstevel@tonic-gate } else { 418*7c478bd9Sstevel@tonic-gate /* update stats */ 419*7c478bd9Sstevel@tonic-gate --(*tid)->stats.num_inserted; 420*7c478bd9Sstevel@tonic-gate /* check if 0 values are inserted in this trie */ 421*7c478bd9Sstevel@tonic-gate if ((*tid)->stats.num_inserted == 0) { 422*7c478bd9Sstevel@tonic-gate /* update dontcareonly boolean */ 423*7c478bd9Sstevel@tonic-gate (*tid)->info.dontcareonly = B_TRUE; 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate /* check if node has zero elements, is a LEAF node */ 427*7c478bd9Sstevel@tonic-gate if ((c_node->elements == NULL) && 428*7c478bd9Sstevel@tonic-gate ((c_node->one == NULL) && (c_node->zero == NULL))) { 429*7c478bd9Sstevel@tonic-gate /* make sure we don't delete the root */ 430*7c478bd9Sstevel@tonic-gate if (c_node->isroot != 1) { 431*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, c_node); 432*7c478bd9Sstevel@tonic-gate return (B_TRUE); 433*7c478bd9Sstevel@tonic-gate } else { 434*7c478bd9Sstevel@tonic-gate /* this is the root, just zero out the info */ 435*7c478bd9Sstevel@tonic-gate c_node->pos = 0; 436*7c478bd9Sstevel@tonic-gate c_node->bits = 0; 437*7c478bd9Sstevel@tonic-gate c_node->val = 0; 438*7c478bd9Sstevel@tonic-gate c_node->mask = 0; 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate return (B_FALSE); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate /* check to see if node describes bits to skip */ 445*7c478bd9Sstevel@tonic-gate if (c_node->bits > 0) { 446*7c478bd9Sstevel@tonic-gate if ((key & c_node->mask) != c_node->val) { 447*7c478bd9Sstevel@tonic-gate ipgpc0dbg(("t_traverse_delete: id %d does not " \ 448*7c478bd9Sstevel@tonic-gate "exist in trie\n", id)); 449*7c478bd9Sstevel@tonic-gate return (B_FALSE); /* key does not exist at node */ 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate pos = (c_node->pos - c_node->bits) + 1; 452*7c478bd9Sstevel@tonic-gate /* search should continue if mask and pos are valid */ 453*7c478bd9Sstevel@tonic-gate if ((pos == 0) || 454*7c478bd9Sstevel@tonic-gate (EXTRACTBIT(mask, (pos - 1), (uint8_t)(*tid)->key_len) 455*7c478bd9Sstevel@tonic-gate != 1)) { 456*7c478bd9Sstevel@tonic-gate /* this node probably contains the id */ 457*7c478bd9Sstevel@tonic-gate if (ipgpc_list_remove(&c_node->elements, 458*7c478bd9Sstevel@tonic-gate id) == B_FALSE) { 459*7c478bd9Sstevel@tonic-gate ipgpc0dbg(("t_traverse_delete: id %d does" \ 460*7c478bd9Sstevel@tonic-gate "not exist in trie\n", id)); 461*7c478bd9Sstevel@tonic-gate return (B_FALSE); 462*7c478bd9Sstevel@tonic-gate } else { 463*7c478bd9Sstevel@tonic-gate /* update stats */ 464*7c478bd9Sstevel@tonic-gate --(*tid)->stats.num_inserted; 465*7c478bd9Sstevel@tonic-gate /* check if 0 values are inserted */ 466*7c478bd9Sstevel@tonic-gate if ((*tid)->stats.num_inserted == 0) { 467*7c478bd9Sstevel@tonic-gate /* update dontcare boolean */ 468*7c478bd9Sstevel@tonic-gate (*tid)->info.dontcareonly = B_TRUE; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate /* check if node has zero elements & is a LEAF node */ 472*7c478bd9Sstevel@tonic-gate if ((c_node->elements == NULL) && 473*7c478bd9Sstevel@tonic-gate ((c_node->one == NULL) && 474*7c478bd9Sstevel@tonic-gate (c_node->zero == NULL))) { 475*7c478bd9Sstevel@tonic-gate /* make sure we don't delete the root */ 476*7c478bd9Sstevel@tonic-gate if (c_node->isroot != 1) { 477*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, 478*7c478bd9Sstevel@tonic-gate c_node); 479*7c478bd9Sstevel@tonic-gate return (B_TRUE); 480*7c478bd9Sstevel@tonic-gate } else { 481*7c478bd9Sstevel@tonic-gate /* this is the root, zero out info */ 482*7c478bd9Sstevel@tonic-gate c_node->pos = 0; 483*7c478bd9Sstevel@tonic-gate c_node->bits = 0; 484*7c478bd9Sstevel@tonic-gate c_node->val = 0; 485*7c478bd9Sstevel@tonic-gate c_node->mask = 0; 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate return (B_FALSE); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate /* extract next bit and test */ 492*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(key, (pos - 1), (uint8_t)(*tid)->key_len); 493*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { 494*7c478bd9Sstevel@tonic-gate if (t_traverse_delete(&c_node->zero, (pos - 1), id, key, mask, 495*7c478bd9Sstevel@tonic-gate tid) == B_TRUE) { 496*7c478bd9Sstevel@tonic-gate c_node->zero = NULL; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate } else { /* ONE bit */ 499*7c478bd9Sstevel@tonic-gate if (t_traverse_delete(&c_node->one, (pos - 1), id, key, mask, 500*7c478bd9Sstevel@tonic-gate tid) == B_TRUE) { 501*7c478bd9Sstevel@tonic-gate c_node->one = NULL; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate /* 505*7c478bd9Sstevel@tonic-gate * non path-compressed nodes will contain one child and no elements 506*7c478bd9Sstevel@tonic-gate * what occurs here: 507*7c478bd9Sstevel@tonic-gate * * 508*7c478bd9Sstevel@tonic-gate * / \ 509*7c478bd9Sstevel@tonic-gate * * * <-- p_node->elements == NULL 510*7c478bd9Sstevel@tonic-gate * / 511*7c478bd9Sstevel@tonic-gate * * <-- c_node->elements = foo 512*7c478bd9Sstevel@tonic-gate * / \ 513*7c478bd9Sstevel@tonic-gate * * * <-- children of c_node 514*7c478bd9Sstevel@tonic-gate * after: 515*7c478bd9Sstevel@tonic-gate * * 516*7c478bd9Sstevel@tonic-gate * / \ 517*7c478bd9Sstevel@tonic-gate * * * <-- p_node->elements = foo 518*7c478bd9Sstevel@tonic-gate * / \ 519*7c478bd9Sstevel@tonic-gate * * * <-- p_node adopts children of c_node 520*7c478bd9Sstevel@tonic-gate */ 521*7c478bd9Sstevel@tonic-gate if ((c_node->one == NULL) && (c_node->zero != NULL)) { 522*7c478bd9Sstevel@tonic-gate if (c_node->elements == NULL) { 523*7c478bd9Sstevel@tonic-gate /* move child elements to parent */ 524*7c478bd9Sstevel@tonic-gate c_node->elements = c_node->zero->elements; 525*7c478bd9Sstevel@tonic-gate /* be sure to include the link in the bits */ 526*7c478bd9Sstevel@tonic-gate c_node->bits += c_node->zero->bits + 1; 527*7c478bd9Sstevel@tonic-gate /* c_node->pos will remain the same */ 528*7c478bd9Sstevel@tonic-gate c_node->mask |= c_node->zero->mask; 529*7c478bd9Sstevel@tonic-gate /* don't forget to mark the link */ 530*7c478bd9Sstevel@tonic-gate SETBIT(c_node->mask, (pos - 1), 1, 531*7c478bd9Sstevel@tonic-gate (uint8_t)(*tid)->key_len); 532*7c478bd9Sstevel@tonic-gate c_node->val |= c_node->zero->val; 533*7c478bd9Sstevel@tonic-gate /* don't forget to mark the link */ 534*7c478bd9Sstevel@tonic-gate UNSETBIT(c_node->val, (pos - 1), 535*7c478bd9Sstevel@tonic-gate (uint8_t)(*tid)->key_len); 536*7c478bd9Sstevel@tonic-gate /* adopt children */ 537*7c478bd9Sstevel@tonic-gate t_node = c_node->zero; 538*7c478bd9Sstevel@tonic-gate c_node->one = c_node->zero->one; 539*7c478bd9Sstevel@tonic-gate c_node->zero = c_node->zero->zero; 540*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, t_node); 541*7c478bd9Sstevel@tonic-gate } else { 542*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero->one == NULL); 543*7c478bd9Sstevel@tonic-gate ASSERT(c_node->zero->zero == NULL); 544*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, c_node->zero); 545*7c478bd9Sstevel@tonic-gate c_node->zero = NULL; 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate } else if ((c_node->one != NULL) && (c_node->zero == NULL)) { 548*7c478bd9Sstevel@tonic-gate if (c_node->elements == NULL) { 549*7c478bd9Sstevel@tonic-gate /* move child elements to parent */ 550*7c478bd9Sstevel@tonic-gate c_node->elements = c_node->one->elements; 551*7c478bd9Sstevel@tonic-gate /* be sure to include the link in the bits */ 552*7c478bd9Sstevel@tonic-gate c_node->bits += c_node->one->bits + 1; 553*7c478bd9Sstevel@tonic-gate /* c_node->pos will remain the same */ 554*7c478bd9Sstevel@tonic-gate c_node->mask |= c_node->one->mask; 555*7c478bd9Sstevel@tonic-gate /* don't forget to mark the link */ 556*7c478bd9Sstevel@tonic-gate SETBIT(c_node->mask, (pos - 1), 1, 557*7c478bd9Sstevel@tonic-gate (uint8_t)(*tid)->key_len); 558*7c478bd9Sstevel@tonic-gate c_node->val |= c_node->one->val; 559*7c478bd9Sstevel@tonic-gate /* don't forget to mark the link */ 560*7c478bd9Sstevel@tonic-gate SETBIT(c_node->val, (pos - 1), 1, 561*7c478bd9Sstevel@tonic-gate (uint8_t)(*tid)->key_len); 562*7c478bd9Sstevel@tonic-gate /* adopt children */ 563*7c478bd9Sstevel@tonic-gate t_node = c_node->one; 564*7c478bd9Sstevel@tonic-gate c_node->zero = c_node->one->zero; 565*7c478bd9Sstevel@tonic-gate c_node->one = c_node->one->one; 566*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, t_node); 567*7c478bd9Sstevel@tonic-gate } else { 568*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one->one == NULL); 569*7c478bd9Sstevel@tonic-gate ASSERT(c_node->one->zero == NULL); 570*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, c_node->one); 571*7c478bd9Sstevel@tonic-gate c_node->one = NULL; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate /* check if node has zero elements, is a LEAF node */ 575*7c478bd9Sstevel@tonic-gate if ((c_node->elements == NULL) && 576*7c478bd9Sstevel@tonic-gate ((c_node->one == NULL) && (c_node->zero == NULL))) { 577*7c478bd9Sstevel@tonic-gate /* make sure we don't delete the root */ 578*7c478bd9Sstevel@tonic-gate if (c_node->isroot != 1) { 579*7c478bd9Sstevel@tonic-gate kmem_cache_free(trie_node_cache, c_node); 580*7c478bd9Sstevel@tonic-gate return (B_TRUE); 581*7c478bd9Sstevel@tonic-gate } else { 582*7c478bd9Sstevel@tonic-gate /* this is the root, just zero out the info */ 583*7c478bd9Sstevel@tonic-gate c_node->pos = 0; 584*7c478bd9Sstevel@tonic-gate c_node->bits = 0; 585*7c478bd9Sstevel@tonic-gate c_node->val = 0; 586*7c478bd9Sstevel@tonic-gate c_node->mask = 0; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate return (B_FALSE); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* 595*7c478bd9Sstevel@tonic-gate * t_remove(tid, id, key, mask) 596*7c478bd9Sstevel@tonic-gate * 597*7c478bd9Sstevel@tonic-gate * removes a value associated with an id from the trie 598*7c478bd9Sstevel@tonic-gate * - if the item does not exist, nothing is removed 599*7c478bd9Sstevel@tonic-gate * - if more than one id share the same key, only the id specified is removed 600*7c478bd9Sstevel@tonic-gate */ 601*7c478bd9Sstevel@tonic-gate void 602*7c478bd9Sstevel@tonic-gate t_remove(trie_id_t *tid, key_t id, uint32_t key, uint32_t mask) 603*7c478bd9Sstevel@tonic-gate { 604*7c478bd9Sstevel@tonic-gate node_t *c_node; 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* don't cares are not inserted */ 607*7c478bd9Sstevel@tonic-gate if (mask == 0) { 608*7c478bd9Sstevel@tonic-gate --tid->stats.num_dontcare; 609*7c478bd9Sstevel@tonic-gate return; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate key &= mask; /* apply mask */ 613*7c478bd9Sstevel@tonic-gate /* traverse to node containing id and remove the id from the trie */ 614*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_WRITER); 615*7c478bd9Sstevel@tonic-gate c_node = tid->trie; 616*7c478bd9Sstevel@tonic-gate (void) t_traverse_delete(&c_node, (uint8_t)tid->key_len, id, key, mask, 617*7c478bd9Sstevel@tonic-gate &tid); 618*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate /* 622*7c478bd9Sstevel@tonic-gate * t_remove6(tid, id, key, mask) 623*7c478bd9Sstevel@tonic-gate * 624*7c478bd9Sstevel@tonic-gate * specific to removing key of 128 bits in length 625*7c478bd9Sstevel@tonic-gate */ 626*7c478bd9Sstevel@tonic-gate void 627*7c478bd9Sstevel@tonic-gate t_remove6(trie_id_t *tid, key_t id, in6_addr_t key, in6_addr_t mask) 628*7c478bd9Sstevel@tonic-gate { 629*7c478bd9Sstevel@tonic-gate node_t *c_node; 630*7c478bd9Sstevel@tonic-gate int bit, i; 631*7c478bd9Sstevel@tonic-gate uint8_t pos; 632*7c478bd9Sstevel@tonic-gate uint8_t type_len = IP_ABITS; 633*7c478bd9Sstevel@tonic-gate in6_addr_t zero_addr = IN6ADDR_ANY_INIT; 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate /* don't cares are not inserted */ 636*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&mask, &zero_addr)) { 637*7c478bd9Sstevel@tonic-gate --tid->stats.num_dontcare; 638*7c478bd9Sstevel@tonic-gate return; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_WRITER); 642*7c478bd9Sstevel@tonic-gate c_node = tid->trie; /* point at root of trie */ 643*7c478bd9Sstevel@tonic-gate V6_MASK_COPY(key, mask, key); 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * A IPv6 address is structured as an array of four uint32_t 646*7c478bd9Sstevel@tonic-gate * values. The higest order of the bits are located in array[0] 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; ++i) { 649*7c478bd9Sstevel@tonic-gate /* traverse trie to the correct position */ 650*7c478bd9Sstevel@tonic-gate for (pos = type_len; pos > 0; --pos) { 651*7c478bd9Sstevel@tonic-gate /* check if bit is significant */ 652*7c478bd9Sstevel@tonic-gate if (EXTRACTBIT(mask.s6_addr32[i], (pos - 1), type_len) 653*7c478bd9Sstevel@tonic-gate != ONE) { 654*7c478bd9Sstevel@tonic-gate break; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(key.s6_addr32[i], (pos - 1), type_len); 657*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { 658*7c478bd9Sstevel@tonic-gate if (c_node->zero == NULL) { 659*7c478bd9Sstevel@tonic-gate break; 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate c_node = c_node->zero; 662*7c478bd9Sstevel@tonic-gate } else { /* ONE bit */ 663*7c478bd9Sstevel@tonic-gate if (c_node->one == NULL) { 664*7c478bd9Sstevel@tonic-gate break; 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate c_node = c_node->one; 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate if (c_node != NULL) { 672*7c478bd9Sstevel@tonic-gate if (ipgpc_list_remove(&c_node->elements, id)) { 673*7c478bd9Sstevel@tonic-gate /* update stats */ 674*7c478bd9Sstevel@tonic-gate --tid->stats.num_inserted; 675*7c478bd9Sstevel@tonic-gate /* 676*7c478bd9Sstevel@tonic-gate * check to see if only dontcare's are inserted 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate if (tid->stats.num_inserted <= 0) { 679*7c478bd9Sstevel@tonic-gate tid->info.dontcareonly = B_TRUE; 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* 688*7c478bd9Sstevel@tonic-gate * t_retrieve(tid, key, fid_table) 689*7c478bd9Sstevel@tonic-gate * 690*7c478bd9Sstevel@tonic-gate * returns the number of found filters that match the input key 691*7c478bd9Sstevel@tonic-gate * - each value that matches either a partial or exact match on the key 692*7c478bd9Sstevel@tonic-gate * is inserted into the fid_table 693*7c478bd9Sstevel@tonic-gate * - some nodes may contain multiple id's, all items will be inserted 694*7c478bd9Sstevel@tonic-gate * into the fid_table 695*7c478bd9Sstevel@tonic-gate * - the find stops when an edge node is reached, the left and right nodes 696*7c478bd9Sstevel@tonic-gate * for the current node are null 697*7c478bd9Sstevel@tonic-gate * - 0 is returned if no matches are found, otherwise the number of matches 698*7c478bd9Sstevel@tonic-gate * is returned 699*7c478bd9Sstevel@tonic-gate * - (-1) is returned if a memory error occurred 700*7c478bd9Sstevel@tonic-gate */ 701*7c478bd9Sstevel@tonic-gate int 702*7c478bd9Sstevel@tonic-gate t_retrieve(trie_id_t *tid, uint32_t key, ht_match_t *fid_table) 703*7c478bd9Sstevel@tonic-gate { 704*7c478bd9Sstevel@tonic-gate int bit; 705*7c478bd9Sstevel@tonic-gate uint8_t pos; 706*7c478bd9Sstevel@tonic-gate int num_found = 0; 707*7c478bd9Sstevel@tonic-gate int ret; 708*7c478bd9Sstevel@tonic-gate node_t *c_node; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_READER); 711*7c478bd9Sstevel@tonic-gate c_node = tid->trie; /* point at root of trie */ 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* ensure trie structure is allocated */ 714*7c478bd9Sstevel@tonic-gate if (c_node == NULL) { 715*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 716*7c478bd9Sstevel@tonic-gate return (num_found); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate /* 719*7c478bd9Sstevel@tonic-gate * foreach node encountered in the search, collect elements and append 720*7c478bd9Sstevel@tonic-gate * to a list to be returned 721*7c478bd9Sstevel@tonic-gate */ 722*7c478bd9Sstevel@tonic-gate for (pos = (uint8_t)tid->key_len; pos > 0; --pos) { 723*7c478bd9Sstevel@tonic-gate /* check node for bits to check */ 724*7c478bd9Sstevel@tonic-gate if (c_node->bits > 0) { 725*7c478bd9Sstevel@tonic-gate if ((key & c_node->mask) != c_node->val) { 726*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 727*7c478bd9Sstevel@tonic-gate return (num_found); /* search is done */ 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate /* pos is set to next bit not covered by node */ 730*7c478bd9Sstevel@tonic-gate if ((pos = (c_node->pos - c_node->bits) + 1) == 0) { 731*7c478bd9Sstevel@tonic-gate /* if node covers rest of bits in key */ 732*7c478bd9Sstevel@tonic-gate break; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate /* check node for elements */ 736*7c478bd9Sstevel@tonic-gate if (c_node->elements != NULL) { 737*7c478bd9Sstevel@tonic-gate if ((ret = ipgpc_mark_found(tid->info.mask, 738*7c478bd9Sstevel@tonic-gate c_node->elements, fid_table)) == -1) { 739*7c478bd9Sstevel@tonic-gate /* signifies a memory error */ 740*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 741*7c478bd9Sstevel@tonic-gate return (-1); 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate num_found += ret; /* increment num_found */ 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate bit = EXTRACTBIT(key, (pos - 1), (uint8_t)tid->key_len); 747*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { /* choose leaf */ 748*7c478bd9Sstevel@tonic-gate c_node = c_node->zero; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate } else { /* bit == ONE */ 751*7c478bd9Sstevel@tonic-gate c_node = c_node->one; 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate if (c_node == NULL) { 755*7c478bd9Sstevel@tonic-gate /* search is finished, edge node reached */ 756*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 757*7c478bd9Sstevel@tonic-gate return (num_found); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate /* see if current node contains elements */ 761*7c478bd9Sstevel@tonic-gate if (c_node->elements != NULL) { 762*7c478bd9Sstevel@tonic-gate if ((ret = ipgpc_mark_found(tid->info.mask, c_node->elements, 763*7c478bd9Sstevel@tonic-gate fid_table)) == -1) { 764*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 765*7c478bd9Sstevel@tonic-gate return (-1); /* signifies a memory error */ 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate num_found += ret; /* increment num_found */ 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 770*7c478bd9Sstevel@tonic-gate return (num_found); 771*7c478bd9Sstevel@tonic-gate } 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate /* 774*7c478bd9Sstevel@tonic-gate * t_retrieve6(tid, key, fid_table) 775*7c478bd9Sstevel@tonic-gate * 776*7c478bd9Sstevel@tonic-gate * specific to retrieving keys of 128 bits in length 777*7c478bd9Sstevel@tonic-gate */ 778*7c478bd9Sstevel@tonic-gate int 779*7c478bd9Sstevel@tonic-gate t_retrieve6(trie_id_t *tid, in6_addr_t key, ht_match_t *fid_table) 780*7c478bd9Sstevel@tonic-gate { 781*7c478bd9Sstevel@tonic-gate int bit, i; 782*7c478bd9Sstevel@tonic-gate uint8_t pos; 783*7c478bd9Sstevel@tonic-gate int num_found = 0; 784*7c478bd9Sstevel@tonic-gate int ret; 785*7c478bd9Sstevel@tonic-gate node_t *c_node; 786*7c478bd9Sstevel@tonic-gate uint8_t type_len = IP_ABITS; 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate rw_enter(&tid->rw_lock, RW_READER); 789*7c478bd9Sstevel@tonic-gate c_node = tid->trie; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate /* ensure trie structure is allocated */ 792*7c478bd9Sstevel@tonic-gate if (c_node == NULL) { 793*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 794*7c478bd9Sstevel@tonic-gate return (num_found); 795*7c478bd9Sstevel@tonic-gate } 796*7c478bd9Sstevel@tonic-gate /* 797*7c478bd9Sstevel@tonic-gate * A IPv6 address is structured as an array of four uint32_t 798*7c478bd9Sstevel@tonic-gate * values. The higest order of the bits are located in array[0] 799*7c478bd9Sstevel@tonic-gate */ 800*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; ++i) { 801*7c478bd9Sstevel@tonic-gate /* 802*7c478bd9Sstevel@tonic-gate * foreach node encountered in the search, collect elements 803*7c478bd9Sstevel@tonic-gate * and append to a list to be returned 804*7c478bd9Sstevel@tonic-gate */ 805*7c478bd9Sstevel@tonic-gate for (pos = type_len; pos > 0; --pos) { 806*7c478bd9Sstevel@tonic-gate /* extract bit at pos */ 807*7c478bd9Sstevel@tonic-gate bit = 808*7c478bd9Sstevel@tonic-gate EXTRACTBIT(key.s6_addr32[i], (pos - 1), type_len); 809*7c478bd9Sstevel@tonic-gate if (bit == ZERO) { /* choose leaf */ 810*7c478bd9Sstevel@tonic-gate c_node = c_node->zero; 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate } else { 813*7c478bd9Sstevel@tonic-gate c_node = c_node->one; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate if (c_node == NULL) { 817*7c478bd9Sstevel@tonic-gate /* search is finished, edge node reached */ 818*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 819*7c478bd9Sstevel@tonic-gate return (num_found); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate /* see if current node contains elements */ 822*7c478bd9Sstevel@tonic-gate if (c_node->elements != NULL) { 823*7c478bd9Sstevel@tonic-gate if ((ret = ipgpc_mark_found(tid->info.mask, 824*7c478bd9Sstevel@tonic-gate c_node->elements, fid_table)) == -1) { 825*7c478bd9Sstevel@tonic-gate /* signifies a memory error */ 826*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 827*7c478bd9Sstevel@tonic-gate return (-1); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate num_found += ret; /* increment num_found */ 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate rw_exit(&tid->rw_lock); 834*7c478bd9Sstevel@tonic-gate return (num_found); 835*7c478bd9Sstevel@tonic-gate } 836