OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [net/] [radix.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      sys/net/radix.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: radix.c,v 1.4 1996/09/05 08:42:32 mickey Exp $        */
34
/*      $NetBSD: radix.c,v 1.11 1996/03/16 23:55:36 christos Exp $      */
35
 
36
/*
37
 * Copyright (c) 1988, 1989, 1993
38
 *      The Regents of the University of California.  All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. All advertising materials mentioning features or use of this software
49
 *    must display the following acknowledgement:
50
 *      This product includes software developed by the University of
51
 *      California, Berkeley and its contributors.
52
 * 4. Neither the name of the University nor the names of its contributors
53
 *    may be used to endorse or promote products derived from this software
54
 *    without specific prior written permission.
55
 *
56
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66
 * SUCH DAMAGE.
67
 *
68
 *      @(#)radix.c     8.4 (Berkeley) 11/2/94
69
 */
70
 
71
/*
72
 * Routines to build and maintain radix trees for routing lookups.
73
 */
74
#include <sys/param.h>
75
#ifdef _KERNEL
76
#ifndef __ECOS
77
#include <sys/systm.h>
78
#include <sys/syslog.h>
79
#endif
80
#include <sys/malloc.h>
81
#define M_DONTWAIT M_NOWAIT
82
#include <sys/domain.h>
83
#else
84
#include <stdlib.h>
85
#endif
86
#include <net/radix.h>
87
 
88
int     max_keylen;
89
struct radix_mask *rn_mkfreelist;
90
struct radix_node_head *mask_rnhead;
91
static char *addmask_key;
92
static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1};
93
static char *rn_zeros, *rn_ones;
94
 
95
#define rn_masktop (mask_rnhead->rnh_treetop)
96
#undef Bcmp
97
#define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))
98
 
99
 
100
static int rn_satsifies_leaf __P((char *, struct radix_node *, int));
101
static int rn_lexobetter __P((void *, void *));
102
static struct radix_mask *rn_new_radix_mask __P((struct radix_node *,
103
                                                 struct radix_mask *));
104
/*
105
 * The data structure for the keys is a radix tree with one way
106
 * branching removed.  The index rn_b at an internal node n represents a bit
107
 * position to be tested.  The tree is arranged so that all descendants
108
 * of a node n have keys whose bits all agree up to position rn_b - 1.
109
 * (We say the index of n is rn_b.)
110
 *
111
 * There is at least one descendant which has a one bit at position rn_b,
112
 * and at least one with a zero there.
113
 *
114
 * A route is determined by a pair of key and mask.  We require that the
115
 * bit-wise logical and of the key and mask to be the key.
116
 * We define the index of a route to associated with the mask to be
117
 * the first bit number in the mask where 0 occurs (with bit number 0
118
 * representing the highest order bit).
119
 *
120
 * We say a mask is normal if every bit is 0, past the index of the mask.
121
 * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
122
 * and m is a normal mask, then the route applies to every descendant of n.
123
 * If the index(m) < rn_b, this implies the trailing last few bits of k
124
 * before bit b are all 0, (and hence consequently true of every descendant
125
 * of n), so the route applies to all descendants of the node as well.
126
 *
127
 * Similar logic shows that a non-normal mask m such that
128
 * index(m) <= index(n) could potentially apply to many children of n.
129
 * Thus, for each non-host route, we attach its mask to a list at an internal
130
 * node as high in the tree as we can go.
131
 *
132
 * The present version of the code makes use of normal routes in short-
133
 * circuiting an explict mask and compare operation when testing whether
134
 * a key satisfies a normal route, and also in remembering the unique leaf
135
 * that governs a subtree.
136
 */
137
 
138
struct radix_node *
139
rn_search(v_arg, head)
140
        void *v_arg;
141
        struct radix_node *head;
142
{
143
        register struct radix_node *x;
144
        register caddr_t v;
145
 
146
        for (x = head, v = v_arg; x->rn_b >= 0;) {
147
                if (x->rn_bmask & v[x->rn_off])
148
                        x = x->rn_r;
149
                else
150
                        x = x->rn_l;
151
        }
152
        return (x);
153
}
154
 
155
struct radix_node *
156
rn_search_m(v_arg, head, m_arg)
157
        struct radix_node *head;
158
        void *v_arg, *m_arg;
159
{
160
        register struct radix_node *x;
161
        register caddr_t v = v_arg, m = m_arg;
162
 
163
        for (x = head; x->rn_b >= 0;) {
164
                if ((x->rn_bmask & m[x->rn_off]) &&
165
                    (x->rn_bmask & v[x->rn_off]))
166
                        x = x->rn_r;
167
                else
168
                        x = x->rn_l;
169
        }
170
        return x;
171
}
172
 
173
int
174
rn_refines(m_arg, n_arg)
175
        void *m_arg, *n_arg;
176
{
177
        register caddr_t m = m_arg, n = n_arg;
178
        register caddr_t lim, lim2 = lim = n + *(u_char *)n;
179
        int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
180
        int masks_are_equal = 1;
181
 
182
        if (longer > 0)
183
                lim -= longer;
184
        while (n < lim) {
185
                if (*n & ~(*m))
186
                        return 0;
187
                if (*n++ != *m++)
188
                        masks_are_equal = 0;
189
        }
190
        while (n < lim2)
191
                if (*n++)
192
                        return 0;
193
        if (masks_are_equal && (longer < 0))
194
                for (lim2 = m - longer; m < lim2; )
195
                        if (*m++)
196
                                return 1;
197
        return (!masks_are_equal);
198
}
199
 
200
struct radix_node *
201
rn_lookup(v_arg, m_arg, head)
202
        void *v_arg, *m_arg;
203
        struct radix_node_head *head;
204
{
205
        register struct radix_node *x;
206
        caddr_t netmask = 0;
207
 
208
        if (m_arg) {
209
                if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0)
210
                        return (0);
211
                netmask = x->rn_key;
212
        }
213
        x = rn_match(v_arg, head);
214
        if (x && netmask) {
215
                while (x && x->rn_mask != netmask)
216
                        x = x->rn_dupedkey;
217
        }
218
        return x;
219
}
220
 
221
static int
222
rn_satsifies_leaf(trial, leaf, skip)
223
        char *trial;
224
        register struct radix_node *leaf;
225
        int skip;
226
{
227
        register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
228
        char *cplim;
229
        int length = min(*(u_char *)cp, *(u_char *)cp2);
230
 
231
        if (cp3 == 0)
232
                cp3 = rn_ones;
233
        else
234
                length = min(length, *(u_char *)cp3);
235
        cplim = cp + length; cp3 += skip; cp2 += skip;
236
        for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
237
                if ((*cp ^ *cp2) & *cp3)
238
                        return 0;
239
        return 1;
240
}
241
 
242
struct radix_node *
243
rn_match(v_arg, head)
244
        void *v_arg;
245
        struct radix_node_head *head;
246
{
247
        caddr_t v = v_arg;
248
        register struct radix_node *t = head->rnh_treetop, *x;
249
        register caddr_t cp = v, cp2;
250
        caddr_t cplim;
251
        struct radix_node *saved_t, *top = t;
252
        int off = t->rn_off, vlen = *(u_char *)cp, matched_off;
253
        register int test, b, rn_b;
254
 
255
        /*
256
         * Open code rn_search(v, top) to avoid overhead of extra
257
         * subroutine call.
258
         */
259
        for (; t->rn_b >= 0; ) {
260
                if (t->rn_bmask & cp[t->rn_off])
261
                        t = t->rn_r;
262
                else
263
                        t = t->rn_l;
264
        }
265
        /*
266
         * See if we match exactly as a host destination
267
         * or at least learn how many bits match, for normal mask finesse.
268
         *
269
         * It doesn't hurt us to limit how many bytes to check
270
         * to the length of the mask, since if it matches we had a genuine
271
         * match and the leaf we have is the most specific one anyway;
272
         * if it didn't match with a shorter length it would fail
273
         * with a long one.  This wins big for class B&C netmasks which
274
         * are probably the most common case...
275
         */
276
        if (t->rn_mask)
277
                vlen = *(u_char *)t->rn_mask;
278
        cp += off; cp2 = t->rn_key + off; cplim = v + vlen;
279
        for (; cp < cplim; cp++, cp2++)
280
                if (*cp != *cp2)
281
                        goto on1;
282
        /*
283
         * This extra grot is in case we are explicitly asked
284
         * to look up the default.  Ugh!
285
         */
286
        if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey)
287
                t = t->rn_dupedkey;
288
        return t;
289
on1:
290
        test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
291
        for (b = 7; (test >>= 1) > 0;)
292
                b--;
293
        matched_off = cp - v;
294
        b += matched_off << 3;
295
        rn_b = -1 - b;
296
        /*
297
         * If there is a host route in a duped-key chain, it will be first.
298
         */
299
        if ((saved_t = t)->rn_mask == 0)
300
                t = t->rn_dupedkey;
301
        for (; t; t = t->rn_dupedkey)
302
                /*
303
                 * Even if we don't match exactly as a host,
304
                 * we may match if the leaf we wound up at is
305
                 * a route to a net.
306
                 */
307
                if (t->rn_flags & RNF_NORMAL) {
308
                        if (rn_b <= t->rn_b)
309
                                return t;
310
                } else if (rn_satsifies_leaf(v, t, matched_off))
311
                                return t;
312
        t = saved_t;
313
        /* start searching up the tree */
314
        do {
315
                register struct radix_mask *m;
316
                t = t->rn_p;
317
                if ((m = t->rn_mklist) != NULL) {
318
                        /*
319
                         * If non-contiguous masks ever become important
320
                         * we can restore the masking and open coding of
321
                         * the search and satisfaction test and put the
322
                         * calculation of "off" back before the "do".
323
                         */
324
                        do {
325
                                if (m->rm_flags & RNF_NORMAL) {
326
                                        if (rn_b <= m->rm_b)
327
                                                return (m->rm_leaf);
328
                                } else {
329
                                        off = min(t->rn_off, matched_off);
330
                                        x = rn_search_m(v, t, m->rm_mask);
331
                                        while (x && x->rn_mask != m->rm_mask)
332
                                                x = x->rn_dupedkey;
333
                                        if (x && rn_satsifies_leaf(v, x, off))
334
                                                    return x;
335
                                }
336
                        } while ((m = m->rm_mklist) != NULL);
337
                }
338
        } while (t != top);
339
        return 0;
340
}
341
 
342
#ifdef RN_DEBUG
343
int     rn_nodenum;
344
struct  radix_node *rn_clist;
345
int     rn_saveinfo;
346
int     rn_debug =  1;
347
#endif
348
 
349
struct radix_node *
350
rn_newpair(v, b, nodes)
351
        void *v;
352
        int b;
353
        struct radix_node nodes[2];
354
{
355
        register struct radix_node *tt = nodes, *t = tt + 1;
356
        t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7);
357
        t->rn_l = tt; t->rn_off = b >> 3;
358
        tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t;
359
        tt->rn_flags = t->rn_flags = RNF_ACTIVE;
360
#ifdef RN_DEBUG
361
        tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
362
        tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
363
#endif
364
        return t;
365
}
366
 
367
struct radix_node *
368
rn_insert(v_arg, head, dupentry, nodes)
369
        void *v_arg;
370
        struct radix_node_head *head;
371
        int *dupentry;
372
        struct radix_node nodes[2];
373
{
374
        caddr_t v = v_arg;
375
        struct radix_node *top = head->rnh_treetop;
376
        int head_off = top->rn_off, vlen = (int)*((u_char *)v);
377
        register struct radix_node *t = rn_search(v_arg, top);
378
        register caddr_t cp = v + head_off;
379
        register int b;
380
        struct radix_node *tt;
381
        /*
382
         * Find first bit at which v and t->rn_key differ
383
         */
384
    {
385
        register caddr_t cp2 = t->rn_key + head_off;
386
        register int cmp_res;
387
        caddr_t cplim = v + vlen;
388
 
389
        while (cp < cplim)
390
                if (*cp2++ != *cp++)
391
                        goto on1;
392
        *dupentry = 1;
393
        return t;
394
on1:
395
        *dupentry = 0;
396
        cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
397
        for (b = (cp - v) << 3; cmp_res; b--)
398
                cmp_res >>= 1;
399
    }
400
    {
401
        register struct radix_node *p, *x = top;
402
        cp = v;
403
        do {
404
                p = x;
405
                if (cp[x->rn_off] & x->rn_bmask)
406
                        x = x->rn_r;
407
                else x = x->rn_l;
408
        } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */
409
#ifdef __ECOS
410
#else
411
#ifdef RN_DEBUG
412
        if (rn_debug)
413
                log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
414
#endif
415
#endif
416
        t = rn_newpair(v_arg, b, nodes); tt = t->rn_l;
417
        if ((cp[p->rn_off] & p->rn_bmask) == 0)
418
                p->rn_l = t;
419
        else
420
                p->rn_r = t;
421
        x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */
422
        if ((cp[t->rn_off] & t->rn_bmask) == 0) {
423
                t->rn_r = x;
424
        } else {
425
                t->rn_r = tt; t->rn_l = x;
426
        }
427
#ifdef __ECOS
428
#else
429
#ifdef RN_DEBUG
430
        if (rn_debug)
431
                log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p);
432
#endif
433
#endif
434
    }
435
        return (tt);
436
}
437
 
438
struct radix_node *
439
rn_addmask(n_arg, search, skip)
440
        int search, skip;
441
        void *n_arg;
442
{
443
        caddr_t netmask = (caddr_t)n_arg;
444
        register struct radix_node *x;
445
        register caddr_t cp, cplim;
446
        register int b = 0, mlen, j;
447
        int maskduplicated, m0, isnormal;
448
        struct radix_node *saved_x;
449
        static int last_zeroed = 0;
450
 
451
        if ((mlen = *(u_char *)netmask) > max_keylen)
452
                mlen = max_keylen;
453
        if (skip == 0)
454
                skip = 1;
455
        if (mlen <= skip)
456
                return (mask_rnhead->rnh_nodes);
457
        if (skip > 1)
458
                Bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
459
        if ((m0 = mlen) > skip)
460
                Bcopy(netmask + skip, addmask_key + skip, mlen - skip);
461
        /*
462
         * Trim trailing zeroes.
463
         */
464
        for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
465
                cp--;
466
        mlen = cp - addmask_key;
467
        if (mlen <= skip) {
468
                if (m0 >= last_zeroed)
469
                        last_zeroed = mlen;
470
                return (mask_rnhead->rnh_nodes);
471
        }
472
        if (m0 < last_zeroed)
473
                Bzero(addmask_key + m0, last_zeroed - m0);
474
        *addmask_key = last_zeroed = mlen;
475
        x = rn_search(addmask_key, rn_masktop);
476
        if (Bcmp(addmask_key, x->rn_key, mlen) != 0)
477
                x = 0;
478
        if (x || search)
479
                return (x);
480
        R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x));
481
        if ((saved_x = x) == 0)
482
                return (0);
483
        Bzero(x, max_keylen + 2 * sizeof (*x));
484
        netmask = cp = (caddr_t)(x + 2);
485
        Bcopy(addmask_key, cp, mlen);
486
        x = rn_insert(cp, mask_rnhead, &maskduplicated, x);
487
        if (maskduplicated) {
488
#ifdef __ECOS
489
#else
490
                log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
491
#endif
492
                Free(saved_x);
493
                return (x);
494
        }
495
        /*
496
         * Calculate index of mask, and check for normalcy.
497
         */
498
        cplim = netmask + mlen; isnormal = 1;
499
        for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;)
500
                cp++;
501
        if (cp != cplim) {
502
                for (j = 0x80; (j & *cp) != 0; j >>= 1)
503
                        b++;
504
                if (*cp != normal_chars[b] || cp != (cplim - 1))
505
                        isnormal = 0;
506
        }
507
        b += (cp - netmask) << 3;
508
        x->rn_b = -1 - b;
509
        if (isnormal)
510
                x->rn_flags |= RNF_NORMAL;
511
        return (x);
512
}
513
 
514
static int      /* XXX: arbitrary ordering for non-contiguous masks */
515
rn_lexobetter(m_arg, n_arg)
516
        void *m_arg, *n_arg;
517
{
518
        register u_char *mp = m_arg, *np = n_arg, *lim;
519
 
520
        if (*mp > *np)
521
                return 1;  /* not really, but need to check longer one first */
522
        if (*mp == *np)
523
                for (lim = mp + *mp; mp < lim;)
524
                        if (*mp++ > *np++)
525
                                return 1;
526
        return 0;
527
}
528
 
529
static struct radix_mask *
530
rn_new_radix_mask(tt, next)
531
        register struct radix_node *tt;
532
        register struct radix_mask *next;
533
{
534
        register struct radix_mask *m;
535
 
536
        MKGet(m);
537
        if (m == 0) {
538
#ifdef __ECOS
539
#else
540
                log(LOG_ERR, "Mask for route not entered\n");
541
#endif
542
                return (0);
543
        }
544
        Bzero(m, sizeof *m);
545
        m->rm_b = tt->rn_b;
546
        m->rm_flags = tt->rn_flags;
547
        if (tt->rn_flags & RNF_NORMAL)
548
                m->rm_leaf = tt;
549
        else
550
                m->rm_mask = tt->rn_mask;
551
        m->rm_mklist = next;
552
        tt->rn_mklist = m;
553
        return m;
554
}
555
 
556
struct radix_node *
557
rn_addroute(v_arg, n_arg, head, treenodes)
558
        void *v_arg, *n_arg;
559
        struct radix_node_head *head;
560
        struct radix_node treenodes[2];
561
{
562
        caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
563
        register struct radix_node *t, *x = NULL, *tt;
564
        struct radix_node *saved_tt, *top = head->rnh_treetop;
565
        short b = 0, b_leaf = 0;
566
        int keyduplicated;
567
        caddr_t mmask;
568
        struct radix_mask *m, **mp;
569
 
570
        /*
571
         * In dealing with non-contiguous masks, there may be
572
         * many different routes which have the same mask.
573
         * We will find it useful to have a unique pointer to
574
         * the mask to speed avoiding duplicate references at
575
         * nodes and possibly save time in calculating indices.
576
         */
577
        if (netmask)  {
578
                if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0)
579
                        return (0);
580
                b_leaf = x->rn_b;
581
                b = -1 - x->rn_b;
582
                netmask = x->rn_key;
583
        }
584
        /*
585
         * Deal with duplicated keys: attach node to previous instance
586
         */
587
        saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
588
        if (keyduplicated) {
589
                for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
590
                        if (tt->rn_mask == netmask)
591
                                return (0);
592
                        if (netmask == 0 ||
593
                            (tt->rn_mask &&
594
                             ((b_leaf < tt->rn_b) || /* index(netmask) > node */
595
                               rn_refines(netmask, tt->rn_mask) ||
596
                               rn_lexobetter(netmask, tt->rn_mask))))
597
                                break;
598
                }
599
                /*
600
                 * If the mask is not duplicated, we wouldn't
601
                 * find it among possible duplicate key entries
602
                 * anyway, so the above test doesn't hurt.
603
                 *
604
                 * We sort the masks for a duplicated key the same way as
605
                 * in a masklist -- most specific to least specific.
606
                 * This may require the unfortunate nuisance of relocating
607
                 * the head of the list.
608
                 */
609
                if (tt == saved_tt) {
610
                        struct  radix_node *xx = x;
611
                        /* link in at head of list */
612
                        (tt = treenodes)->rn_dupedkey = t;
613
                        tt->rn_flags = t->rn_flags;
614
                        tt->rn_p = x = t->rn_p;
615
                        if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt;
616
                        saved_tt = tt; x = xx;
617
                } else {
618
                        (tt = treenodes)->rn_dupedkey = t->rn_dupedkey;
619
                        t->rn_dupedkey = tt;
620
                }
621
#ifdef RN_DEBUG
622
                t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
623
                tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
624
#endif
625
                tt->rn_key = (caddr_t) v;
626
                tt->rn_b = -1;
627
                tt->rn_flags = RNF_ACTIVE;
628
        }
629
        /*
630
         * Put mask in tree.
631
         */
632
        if (netmask) {
633
                tt->rn_mask = netmask;
634
                tt->rn_b = x->rn_b;
635
                tt->rn_flags |= x->rn_flags & RNF_NORMAL;
636
        }
637
        t = saved_tt->rn_p;
638
        if (keyduplicated)
639
                goto on2;
640
        b_leaf = -1 - t->rn_b;
641
        if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r;
642
        /* Promote general routes from below */
643
        if (x->rn_b < 0) {
644
            for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
645
                if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) {
646
                        *mp = m = rn_new_radix_mask(x, 0);
647
                        if (m)
648
                                mp = &m->rm_mklist;
649
                }
650
        } else if (x->rn_mklist) {
651
                /*
652
                 * Skip over masks whose index is > that of new node
653
                 */
654
                for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist)
655
                        if (m->rm_b >= b_leaf)
656
                                break;
657
                t->rn_mklist = m; *mp = 0;
658
        }
659
on2:
660
        /* Add new route to highest possible ancestor's list */
661
        if ((netmask == 0) || (b > t->rn_b ))
662
                return tt; /* can't lift at all */
663
        b_leaf = tt->rn_b;
664
        do {
665
                x = t;
666
                t = t->rn_p;
667
        } while (b <= t->rn_b && x != top);
668
        /*
669
         * Search through routes associated with node to
670
         * insert new route according to index.
671
         * Need same criteria as when sorting dupedkeys to avoid
672
         * double loop on deletion.
673
         */
674
        for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist) {
675
                if (m->rm_b < b_leaf)
676
                        continue;
677
                if (m->rm_b > b_leaf)
678
                        break;
679
                if (m->rm_flags & RNF_NORMAL) {
680
                        mmask = m->rm_leaf->rn_mask;
681
                        if (tt->rn_flags & RNF_NORMAL) {
682
#ifdef __ECOS
683
#else
684
                                log(LOG_ERR,
685
                                   "Non-unique normal route, mask not entered");
686
#endif
687
                                return tt;
688
                        }
689
                } else
690
                        mmask = m->rm_mask;
691
                if (mmask == netmask) {
692
                        m->rm_refs++;
693
                        tt->rn_mklist = m;
694
                        return tt;
695
                }
696
                if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask))
697
                        break;
698
        }
699
        *mp = rn_new_radix_mask(tt, *mp);
700
        return tt;
701
}
702
 
703
struct radix_node *
704
rn_delete(v_arg, netmask_arg, head)
705
        void *v_arg, *netmask_arg;
706
        struct radix_node_head *head;
707
{
708
        register struct radix_node *t, *p, *x, *tt;
709
        struct radix_mask *m, *saved_m, **mp;
710
        struct radix_node *dupedkey, *saved_tt, *top;
711
        caddr_t v, netmask;
712
        int b, head_off, vlen;
713
 
714
        v = v_arg;
715
        netmask = netmask_arg;
716
        x = head->rnh_treetop;
717
        tt = rn_search(v, x);
718
        head_off = x->rn_off;
719
        vlen =  *(u_char *)v;
720
        saved_tt = tt;
721
        top = x;
722
        if (tt == 0 ||
723
            Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
724
                return (0);
725
        /*
726
         * Delete our route from mask lists.
727
         */
728
        if (netmask) {
729
                if ((x = rn_addmask(netmask, 1, head_off)) == 0)
730
                        return (0);
731
                netmask = x->rn_key;
732
                while (tt->rn_mask != netmask)
733
                        if ((tt = tt->rn_dupedkey) == 0)
734
                                return (0);
735
        }
736
        if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
737
                goto on1;
738
        if (tt->rn_flags & RNF_NORMAL) {
739
                if (m->rm_leaf != tt || m->rm_refs > 0) {
740
#ifdef __ECOS
741
#else
742
                        log(LOG_ERR, "rn_delete: inconsistent annotation\n");
743
#endif
744
                        return 0;  /* dangling ref could cause disaster */
745
                }
746
        } else {
747
                if (m->rm_mask != tt->rn_mask) {
748
#ifdef __ECOS
749
#else
750
                        log(LOG_ERR, "rn_delete: inconsistent annotation\n");
751
#endif
752
                        goto on1;
753
                }
754
                if (--m->rm_refs >= 0)
755
                        goto on1;
756
        }
757
        b = -1 - tt->rn_b;
758
        t = saved_tt->rn_p;
759
        if (b > t->rn_b)
760
                goto on1; /* Wasn't lifted at all */
761
        do {
762
                x = t;
763
                t = t->rn_p;
764
        } while (b <= t->rn_b && x != top);
765
        for (mp = &x->rn_mklist; (m = *mp) != NULL; mp = &m->rm_mklist)
766
                if (m == saved_m) {
767
                        *mp = m->rm_mklist;
768
                        MKFree(m);
769
                        break;
770
                }
771
        if (m == 0) {
772
#ifdef __ECOS
773
#else
774
                log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
775
#endif
776
                if (tt->rn_flags & RNF_NORMAL)
777
                        return (0); /* Dangling ref to us */
778
        }
779
on1:
780
        /*
781
         * Eliminate us from tree
782
         */
783
        if (tt->rn_flags & RNF_ROOT)
784
                return (0);
785
#ifdef RN_DEBUG
786
        /* Get us out of the creation list */
787
        for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {}
788
        if (t) t->rn_ybro = tt->rn_ybro;
789
#endif
790
        t = tt->rn_p;
791
        if ((dupedkey = saved_tt->rn_dupedkey) != 0) {
792
                if (tt == saved_tt) {
793
                        x = dupedkey; x->rn_p = t;
794
                        if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x;
795
                } else {
796
                        for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
797
                                p = p->rn_dupedkey;
798
                        if (p) p->rn_dupedkey = tt->rn_dupedkey;
799
#ifdef __ECOS
800
#else
801
                        else log(LOG_ERR, "rn_delete: couldn't find us\n");
802
#endif
803
                }
804
                t = tt + 1;
805
                if  (t->rn_flags & RNF_ACTIVE) {
806
#ifndef RN_DEBUG
807
                        *++x = *t; p = t->rn_p;
808
#else
809
                        b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p;
810
#endif
811
                        if (p->rn_l == t) p->rn_l = x; else p->rn_r = x;
812
                        x->rn_l->rn_p = x; x->rn_r->rn_p = x;
813
                }
814
                goto out;
815
        }
816
        if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l;
817
        p = t->rn_p;
818
        if (p->rn_r == t) p->rn_r = x; else p->rn_l = x;
819
        x->rn_p = p;
820
        /*
821
         * Demote routes attached to us.
822
         */
823
        if (t->rn_mklist) {
824
                if (x->rn_b >= 0) {
825
                        for (mp = &x->rn_mklist; (m = *mp) != NULL;)
826
                                mp = &m->rm_mklist;
827
                        *mp = t->rn_mklist;
828
                } else {
829
                        /* If there are any key,mask pairs in a sibling
830
                           duped-key chain, some subset will appear sorted
831
                           in the same order attached to our mklist */
832
                        for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
833
                                if (m == x->rn_mklist) {
834
                                        struct radix_mask *mm = m->rm_mklist;
835
                                        x->rn_mklist = 0;
836
                                        if (--(m->rm_refs) < 0)
837
                                                MKFree(m);
838
                                        m = mm;
839
                                }
840
#ifdef __ECOS
841
#else
842
                        if (m)
843
                                log(LOG_ERR, "%s %p at %p\n",
844
                                            "rn_delete: Orphaned Mask", m, x);
845
#endif
846
                }
847
        }
848
        /*
849
         * We may be holding an active internal node in the tree.
850
         */
851
        x = tt + 1;
852
        if (t != x) {
853
#ifndef RN_DEBUG
854
                *t = *x;
855
#else
856
                b = t->rn_info; *t = *x; t->rn_info = b;
857
#endif
858
                t->rn_l->rn_p = t; t->rn_r->rn_p = t;
859
                p = x->rn_p;
860
                if (p->rn_l == x) p->rn_l = t; else p->rn_r = t;
861
        }
862
out:
863
        tt->rn_flags &= ~RNF_ACTIVE;
864
        tt[1].rn_flags &= ~RNF_ACTIVE;
865
        return (tt);
866
}
867
 
868
int
869
rn_walktree(h, f, w)
870
        struct radix_node_head *h;
871
        register int (*f) __P((struct radix_node *, void *));
872
        void *w;
873
{
874
        int error;
875
        struct radix_node *base, *next;
876
        register struct radix_node *rn = h->rnh_treetop;
877
        /*
878
         * This gets complicated because we may delete the node
879
         * while applying the function f to it, so we need to calculate
880
         * the successor node in advance.
881
         */
882
        /* First time through node, go left */
883
        while (rn->rn_b >= 0)
884
                rn = rn->rn_l;
885
        for (;;) {
886
                base = rn;
887
                /* If at right child go back up, otherwise, go right */
888
                while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0)
889
                        rn = rn->rn_p;
890
                /* Find the next *leaf* since next node might vanish, too */
891
                for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;)
892
                        rn = rn->rn_l;
893
                next = rn;
894
                /* Process leaves */
895
                while ((rn = base) != NULL) {
896
                        base = rn->rn_dupedkey;
897
                        if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w)))
898
                                return (error);
899
                }
900
                rn = next;
901
                if (rn->rn_flags & RNF_ROOT)
902
                        return (0);
903
        }
904
        /* NOTREACHED */
905
}
906
 
907
int
908
rn_inithead(head, off)
909
        void **head;
910
        int off;
911
{
912
        register struct radix_node_head *rnh;
913
        register struct radix_node *t, *tt, *ttt;
914
        if (*head)
915
                return (1);
916
        R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh));
917
        if (rnh == 0)
918
                return (0);
919
        Bzero(rnh, sizeof (*rnh));
920
        *head = rnh;
921
        t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
922
        ttt = rnh->rnh_nodes + 2;
923
        t->rn_r = ttt;
924
        t->rn_p = t;
925
        tt = t->rn_l;
926
        tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
927
        tt->rn_b = -1 - off;
928
        *ttt = *tt;
929
        ttt->rn_key = rn_ones;
930
        rnh->rnh_addaddr = rn_addroute;
931
        rnh->rnh_deladdr = rn_delete;
932
        rnh->rnh_matchaddr = rn_match;
933
        rnh->rnh_lookup = rn_lookup;
934
        rnh->rnh_walktree = rn_walktree;
935
        rnh->rnh_treetop = t;
936
        return (1);
937
}
938
 
939
void
940
rn_init()
941
{
942
        char *cp, *cplim;
943
#ifdef _KERNEL
944
        struct domain *dom;
945
 
946
        for (dom = domains; dom; dom = dom->dom_next)
947
                if (dom->dom_maxrtkey > max_keylen)
948
                        max_keylen = dom->dom_maxrtkey;
949
#endif
950
        if (max_keylen == 0) {
951
#ifdef __ECOS
952
#else
953
                log(LOG_ERR,
954
                    "rn_init: radix functions require max_keylen be set\n");
955
#endif
956
                return;
957
        }
958
        R_Malloc(rn_zeros, char *, 3 * max_keylen);
959
        if (rn_zeros == NULL)
960
                panic("rn_init");
961
        Bzero(rn_zeros, 3 * max_keylen);
962
        rn_ones = cp = rn_zeros + max_keylen;
963
        addmask_key = cplim = rn_ones + max_keylen;
964
        while (cp < cplim)
965
                *cp++ = -1;
966
        if (rn_inithead((void **)&mask_rnhead, 0) == 0)
967
                panic("rn_init 2");
968
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.