2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 Neil Cafferkey
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 * Copyright (c) 1988, 1989 Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)radix.c 7.9 (Berkeley) 2/4/91
61 * Routines to build and maintain radix trees for routing lookups.
64 #include <sys/param.h>
65 #include <net/radix.h>
66 #include <sys/malloc.h>
67 #include <sys/systm.h>
68 #define M_DONTWAIT M_NOWAIT
70 #include <net/radix_protos.h>
72 struct radix_node_head
*mask_rnhead
=NULL
;
73 #define rn_maskhead mask_rnhead->rnh_treetop
74 struct radix_mask
*rn_mkfreelist
= NULL
;
75 struct radix_node_head
*radix_node_head
= NULL
;
76 struct radix_node_head
*rt_tables
[AF_MAX
+1] = {0};
79 #define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))
81 * The data structure for the keys is a radix tree with one way
82 * branching removed. The index rn_b at an internal node n represents a bit
83 * position to be tested. The tree is arranged so that all descendants
84 * of a node n have keys whose bits all agree up to position rn_b - 1.
85 * (We say the index of n is rn_b.)
87 * There is at least one descendant which has a one bit at position rn_b,
88 * and at least one with a zero there.
90 * A route is determined by a pair of key and mask. We require that the
91 * bit-wise logical and of the key and mask to be the key.
92 * We define the index of a route to associated with the mask to be
93 * the first bit number in the mask where 0 occurs (with bit number 0
94 * representing the highest order bit).
96 * We say a mask is normal if every bit is 0, past the index of the mask.
97 * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
98 * and m is a normal mask, then the route applies to every descendant of n.
99 * If the index(m) < rn_b, this implies the trailing last few bits of k
100 * before bit b are all 0, (and hence consequently true of every descendant
101 * of n), so the route applies to all descendants of the node as well.
103 * The present version of the code makes no use of normal routes,
104 * but similar logic shows that a non-normal mask m such that
105 * index(m) <= index(n) could potentially apply to many children of n.
106 * Thus, for each non-host route, we attach its mask to a list at an internal
107 * node as high in the tree as we can go.
112 struct radix_node
*head
;
115 register struct radix_node
*x
;
117 for (x
= head
; x
->rn_b
>= 0;) {
118 if (x
->rn_bmask
& v
[x
->rn_off
])
127 rn_search_m(v
, head
, m
)
128 struct radix_node
*head
;
129 register caddr_t v
, m
;
131 register struct radix_node
*x
;
133 for (x
= head
; x
->rn_b
>= 0;) {
134 if ((x
->rn_bmask
& m
[x
->rn_off
]) &&
135 (x
->rn_bmask
& v
[x
->rn_off
]))
144 static int gotOddMasks
= 0;
145 static char maskedKey
[MAXKEYLEN
] = {0};
149 struct radix_node
*head
;
152 register struct radix_node
*t
= head
, *x
;
153 register caddr_t cp
= v
, cp2
, cp3
;
154 caddr_t cplim
, mstart
;
155 struct radix_node
*saved_t
;
156 int off
= t
->rn_off
, vlen
= *(u_char
*)cp
, matched_off
;
159 * Open code rn_search(v, head) to avoid overhead of extra
162 for (; t
->rn_b
>= 0; ) {
163 if (t
->rn_bmask
& cp
[t
->rn_off
])
169 * See if we match exactly as a host destination
171 cp
+= off
; cp2
= t
->rn_key
+ off
; cplim
= v
+ vlen
;
172 for (; cp
< cplim
; cp
++, cp2
++)
176 * This extra grot is in case we are explicitly asked
177 * to look up the default. Ugh!
179 if ((t
->rn_flags
& RNF_ROOT
) && t
->rn_dupedkey
)
183 matched_off
= cp
- v
;
188 * Even if we don't match exactly as a hosts;
189 * we may match if the leaf we wound up at is
192 cp3
= matched_off
+ t
->rn_mask
;
193 cp2
= matched_off
+ t
->rn_key
;
194 for (; cp
< cplim
; cp
++)
195 if ((*cp2
++ ^ *cp
) & *cp3
++)
199 cp
= matched_off
+ v
;
201 } while (t
= t
->rn_dupedkey
);
203 /* start searching up the tree */
205 register struct radix_mask
*m
;
207 if (m
= t
->rn_mklist
) {
209 * After doing measurements here, it may
210 * turn out to be faster to open code
211 * rn_search_m here instead of always
212 * copying and masking.
214 off
= MIN(t
->rn_off
, matched_off
);
215 mstart
= maskedKey
+ off
;
218 cp3
= m
->rm_mask
+ off
;
219 for (cp
= v
+ off
; cp
< cplim
;)
220 *cp2
++ = *cp
++ & *cp3
++;
221 x
= rn_search(maskedKey
, t
);
222 while (x
&& x
->rn_mask
!= m
->rm_mask
)
225 (Bcmp(mstart
, x
->rn_key
+ off
,
228 } while (m
= m
->rm_mklist
);
236 struct radix_node
*rn_clist
= NULL
;
241 rn_newpair(v
, b
, nodes
)
244 struct radix_node nodes
[2];
246 register struct radix_node
*tt
= nodes
, *t
= tt
+ 1;
247 t
->rn_b
= b
; t
->rn_bmask
= 0x80 >> (b
& 7);
248 t
->rn_l
= tt
; t
->rn_off
= b
>> 3;
249 tt
->rn_b
= -1; tt
->rn_key
= v
; tt
->rn_p
= t
;
250 tt
->rn_flags
= t
->rn_flags
= RNF_ACTIVE
;
252 tt
->rn_info
= rn_nodenum
++; t
->rn_info
= rn_nodenum
++;
253 tt
->rn_twin
= t
; tt
->rn_ybro
= rn_clist
; rn_clist
= tt
;
260 rn_insert(v
, head
, dupentry
, nodes
)
262 struct radix_node
*head
;
264 struct radix_node nodes
[2];
266 int head_off
= head
->rn_off
, vlen
= (int)*((u_char
*)v
);
267 register struct radix_node
*t
= rn_search(v
, head
);
268 register caddr_t cp
= v
+ head_off
;
270 struct radix_node
*tt
;
272 *find first bit at which v and t->rn_key differ
275 register caddr_t cp2
= t
->rn_key
+ head_off
;
276 register int cmp_res
;
277 caddr_t cplim
= v
+ vlen
;
286 cmp_res
= (cp
[-1] ^ cp2
[-1]) & 0xff;
287 for (b
= (cp
- v
) << 3; cmp_res
; b
--)
291 register struct radix_node
*p
, *x
= head
;
295 if (cp
[x
->rn_off
] & x
->rn_bmask
)
298 } while (b
> (unsigned) x
->rn_b
); /* x->rn_b < b && x->rn_b >= 0 */
301 printf("Going In:\n"), traverse(p
);
303 t
= rn_newpair(v
, b
, nodes
); tt
= t
->rn_l
;
304 if ((cp
[p
->rn_off
] & p
->rn_bmask
) == 0)
308 x
->rn_p
= t
; t
->rn_p
= p
; /* frees x, p as temp vars below */
309 if ((cp
[t
->rn_off
] & t
->rn_bmask
) == 0) {
312 t
->rn_r
= tt
; t
->rn_l
= x
;
316 printf("Coming out:\n"), traverse(p
);
323 rn_addmask(netmask
, search
, skip
)
328 register struct radix_node
*x
;
329 register caddr_t cp
, cplim
;
330 register int b
, mlen
, j
;
333 mlen
= *(u_char
*)netmask
;
335 x
= rn_search(netmask
, rn_maskhead
);
336 mlen
= *(u_char
*)netmask
;
337 if (Bcmp(netmask
, x
->rn_key
, mlen
) == 0)
340 R_Malloc(x
, struct radix_node
*, MAXKEYLEN
+ 2 * sizeof (*x
));
343 Bzero(x
, MAXKEYLEN
+ 2 * sizeof (*x
));
344 cp
= (caddr_t
)(x
+ 2);
345 Bcopy(netmask
, cp
, mlen
);
347 x
= rn_insert(netmask
, rn_maskhead
, &maskduplicated
, x
);
349 * Calculate index of mask.
351 cplim
= netmask
+ mlen
;
352 for (cp
= netmask
+ skip
; cp
< cplim
; cp
++)
353 if (*(u_char
*)cp
!= 0xff)
355 b
= (cp
- netmask
) << 3;
359 for (j
= 0x80; j
; b
++, j
>>= 1)
369 rn_addroute(v
, netmask
, head
, treenodes
)
370 struct radix_node
*head
;
372 struct radix_node treenodes
[2];
375 register struct radix_node
*t
, *x
=NULL
, *tt
;
377 int mlen
, keyduplicated
;
378 caddr_t cplim
; unsigned char *maskp
;
379 struct radix_mask
*m
, **mp
;
380 struct radix_node
*saved_tt
;
383 * In dealing with non-contiguous masks, there may be
384 * many different routes which have the same mask.
385 * We will find it useful to have a unique pointer to
386 * the mask to speed avoiding duplicate references at
387 * nodes and possibly save time in calculating indices.
390 x
= rn_search(netmask
, rn_maskhead
);
391 mlen
= *(u_char
*)netmask
;
392 if (Bcmp(netmask
, x
->rn_key
, mlen
) != 0) {
393 x
= rn_addmask(netmask
, 0, head
->rn_off
);
401 * Deal with duplicated keys: attach node to previous instance
403 saved_tt
= tt
= rn_insert(v
, head
, &keyduplicated
, treenodes
);
406 if (tt
->rn_mask
== netmask
)
409 } while (tt
= tt
->rn_dupedkey
);
411 * If the mask is not duplicated, we wouldn't
412 * find it among possible duplicate key entries
413 * anyway, so the above test doesn't hurt.
415 * XXX: we really ought to sort the masks
416 * for a duplicated key the same way as in a masklist.
417 * It is an unfortunate pain having to relocate
418 * the head of the list.
420 t
->rn_dupedkey
= tt
= treenodes
;
422 t
=tt
+1; tt
->rn_info
= rn_nodenum
++; t
->rn_info
= rn_nodenum
++;
423 tt
->rn_twin
= t
; tt
->rn_ybro
= rn_clist
; rn_clist
= tt
;
426 tt
->rn_key
= (caddr_t
) v
;
428 tt
->rn_flags
= t
->rn_flags
& ~RNF_ROOT
;
434 tt
->rn_mask
= netmask
;
438 b_leaf
= -1 - t
->rn_b
;
439 if (t
->rn_r
== saved_tt
) x
= t
->rn_l
; else x
= t
->rn_r
;
440 /* Promote general routes from below */
442 if (x
->rn_mask
&& (x
->rn_b
>= b_leaf
) && x
->rn_mklist
== 0) {
447 m
->rm_mask
= x
->rn_mask
;
448 x
->rn_mklist
= t
->rn_mklist
= m
;
451 } else if (x
->rn_mklist
) {
453 * Skip over masks whose index is > that of new node
455 for (mp
= &x
->rn_mklist
; m
= *mp
; mp
= &m
->rm_mklist
)
456 if (m
->rm_b
>= b_leaf
)
458 t
->rn_mklist
= m
; *mp
= 0;
460 /* Add new route to highest possible ancestor's list */
461 if ((netmask
== 0) || (b
> t
->rn_b
))
462 return tt
; /* can't lift at all */
467 } while (b
<= t
->rn_b
&& x
!= head
);
469 * Search through routes associated with node to
470 * insert new route according to index.
471 * For nodes of equal index, place more specific
474 cplim
= netmask
+ mlen
;
475 for (mp
= &x
->rn_mklist
; m
= *mp
; mp
= &m
->rm_mklist
) {
476 if (m
->rm_b
< b_leaf
)
478 if (m
->rm_b
> b_leaf
)
480 if (m
->rm_mask
== netmask
) {
485 maskp
= (u_char
*)m
->rm_mask
;
486 for (cp
= netmask
; cp
< cplim
; cp
++)
487 if (*(u_char
*)cp
> *maskp
++)
493 printf("Mask for route not entered\n");
498 m
->rm_mask
= netmask
;
506 rn_delete(v
, netmask
, head
)
508 struct radix_node
*head
;
510 register struct radix_node
*t
, *p
, *x
= head
;
511 register struct radix_node
*tt
= rn_search(v
, x
);
512 int b
, head_off
= x
->rn_off
, vlen
= * (u_char
*) v
;
513 struct radix_mask
*m
, *saved_m
, **mp
;
514 struct radix_node
*dupedkey
, *saved_tt
= tt
;
517 Bcmp(v
+ head_off
, tt
->rn_key
+ head_off
, vlen
- head_off
))
520 * Delete our route from mask lists.
522 if (dupedkey
= tt
->rn_dupedkey
) {
524 netmask
= rn_search(netmask
, rn_maskhead
)->rn_key
;
525 while (tt
->rn_mask
!= netmask
)
526 if ((tt
= tt
->rn_dupedkey
) == 0)
529 if (tt
->rn_mask
== 0 || (saved_m
= m
= tt
->rn_mklist
) == 0)
531 if (m
->rm_mask
!= tt
->rn_mask
) {
532 printf("rn_delete: inconsistent annotation\n");
535 if (--m
->rm_refs
>= 0)
540 goto on1
; /* Wasn't lifted at all */
544 } while (b
<= t
->rn_b
&& x
!= head
);
545 for (mp
= &x
->rn_mklist
; m
= *mp
; mp
= &m
->rm_mklist
)
552 printf("rn_delete: couldn't find our annotation\n");
555 * Eliminate us from tree
557 if (tt
->rn_flags
& RNF_ROOT
)
560 /* Get us out of the creation list */
561 for (t
= rn_clist
; t
&& t
->rn_ybro
!= tt
; t
= t
->rn_ybro
) {}
562 if (t
) t
->rn_ybro
= tt
->rn_ybro
;
563 #endif /* RN_DEBUG */
566 if (tt
== saved_tt
) {
567 x
= dupedkey
; x
->rn_p
= t
;
568 if (t
->rn_l
== tt
) t
->rn_l
= x
; else t
->rn_r
= x
;
570 x
++; t
= tt
+ 1; *x
= *t
; p
= t
->rn_p
;
572 x
++; b
= x
->rn_info
; t
= tt
+ 1; *x
= *t
; p
= t
->rn_p
;
575 if (p
->rn_l
== t
) p
->rn_l
= x
; else p
->rn_r
= x
;
576 x
->rn_l
->rn_p
= x
; x
->rn_r
->rn_p
= x
;
578 for (p
= saved_tt
; p
&& p
->rn_dupedkey
!= tt
;)
580 if (p
) p
->rn_dupedkey
= tt
->rn_dupedkey
;
581 else printf("rn_delete: couldn't find us\n");
585 if (t
->rn_l
== tt
) x
= t
->rn_r
; else x
= t
->rn_l
;
587 if (p
->rn_r
== t
) p
->rn_r
= x
; else p
->rn_l
= x
;
590 * Demote routes attached to us.
594 for (mp
= &x
->rn_mklist
; m
= *mp
;)
598 for (m
= t
->rn_mklist
; m
;) {
599 struct radix_mask
*mm
= m
->rm_mklist
;
600 if (m
== x
->rn_mklist
&& (--(m
->rm_refs
) < 0)) {
604 printf("%s %lx at %lx\n",
605 "rn_delete: Orphaned Mask",
606 (u_long
)m
, (u_long
)x
);
612 * We may be holding an active internal node in the tree.
619 b
= t
->rn_info
; *t
= *x
; t
->rn_info
= b
;
621 t
->rn_l
->rn_p
= t
; t
->rn_r
->rn_p
= t
;
623 if (p
->rn_l
== x
) p
->rn_l
= t
; else p
->rn_r
= t
;
626 tt
->rn_flags
&= ~RNF_ACTIVE
;
627 tt
[1].rn_flags
&= ~RNF_ACTIVE
;
630 char rn_zeros
[MAXKEYLEN
] = {0}, rn_ones
[MAXKEYLEN
] = {0};
633 rn_inithead(head
, off
, af
)
634 struct radix_node_head
**head
;
638 register struct radix_node_head
*rnh
;
639 register struct radix_node
*t
, *tt
, *ttt
;
642 R_Malloc(rnh
, struct radix_node_head
*, sizeof (*rnh
));
645 Bzero(rnh
, sizeof (*rnh
));
647 t
= rn_newpair(rn_zeros
, off
, rnh
->rnh_nodes
);
648 ttt
= rnh
->rnh_nodes
+ 2;
652 tt
->rn_flags
= t
->rn_flags
= RNF_ROOT
| RNF_ACTIVE
;
655 ttt
->rn_key
= rn_ones
;
657 rnh
->rnh_treetop
= t
;
658 if (radix_node_head
== 0) {
659 caddr_t cp
= rn_ones
, cplim
= rn_ones
+ MAXKEYLEN
;
662 if (rn_inithead(&radix_node_head
, 0, 0) == 0) {
667 mask_rnhead
= radix_node_head
;
669 rnh
->rnh_next
= radix_node_head
->rnh_next
;
670 if (radix_node_head
!= rnh
)
671 radix_node_head
->rnh_next
= rnh
;