1f5baf8bbSAlexander V. Chernikov /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3f5baf8bbSAlexander V. Chernikov *
4f5baf8bbSAlexander V. Chernikov * Copyright (c) 2020 Alexander V. Chernikov
5f5baf8bbSAlexander V. Chernikov *
6f5baf8bbSAlexander V. Chernikov * Redistribution and use in source and binary forms, with or without
7f5baf8bbSAlexander V. Chernikov * modification, are permitted provided that the following conditions
8f5baf8bbSAlexander V. Chernikov * are met:
9f5baf8bbSAlexander V. Chernikov * 1. Redistributions of source code must retain the above copyright
10f5baf8bbSAlexander V. Chernikov * notice, this list of conditions and the following disclaimer.
11f5baf8bbSAlexander V. Chernikov * 2. Redistributions in binary form must reproduce the above copyright
12f5baf8bbSAlexander V. Chernikov * notice, this list of conditions and the following disclaimer in the
13f5baf8bbSAlexander V. Chernikov * documentation and/or other materials provided with the distribution.
14f5baf8bbSAlexander V. Chernikov *
15f5baf8bbSAlexander V. Chernikov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16f5baf8bbSAlexander V. Chernikov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17f5baf8bbSAlexander V. Chernikov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18f5baf8bbSAlexander V. Chernikov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19f5baf8bbSAlexander V. Chernikov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20f5baf8bbSAlexander V. Chernikov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21f5baf8bbSAlexander V. Chernikov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22f5baf8bbSAlexander V. Chernikov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23f5baf8bbSAlexander V. Chernikov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24f5baf8bbSAlexander V. Chernikov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25f5baf8bbSAlexander V. Chernikov * SUCH DAMAGE.
26f5baf8bbSAlexander V. Chernikov */
27f5baf8bbSAlexander V. Chernikov
28f5baf8bbSAlexander V. Chernikov #include <sys/cdefs.h>
29f5baf8bbSAlexander V. Chernikov #include "opt_inet6.h"
30f5baf8bbSAlexander V. Chernikov
31f5baf8bbSAlexander V. Chernikov #include <sys/param.h>
32f5baf8bbSAlexander V. Chernikov #include <sys/eventhandler.h>
33f5baf8bbSAlexander V. Chernikov #include <sys/kernel.h>
34f5baf8bbSAlexander V. Chernikov #include <sys/lock.h>
35f5baf8bbSAlexander V. Chernikov #include <sys/rmlock.h>
36f5baf8bbSAlexander V. Chernikov #include <sys/malloc.h>
37f5baf8bbSAlexander V. Chernikov #include <sys/mbuf.h>
38f5baf8bbSAlexander V. Chernikov #include <sys/module.h>
39f5baf8bbSAlexander V. Chernikov #include <sys/kernel.h>
40f5baf8bbSAlexander V. Chernikov #include <sys/priv.h>
41f5baf8bbSAlexander V. Chernikov #include <sys/proc.h>
42f5baf8bbSAlexander V. Chernikov #include <sys/socket.h>
43f5baf8bbSAlexander V. Chernikov #include <sys/socketvar.h>
44f5baf8bbSAlexander V. Chernikov #include <sys/sysctl.h>
45f5baf8bbSAlexander V. Chernikov #include <net/vnet.h>
46f5baf8bbSAlexander V. Chernikov
47f5baf8bbSAlexander V. Chernikov #include <net/if.h>
48f5baf8bbSAlexander V. Chernikov #include <net/if_var.h>
49f5baf8bbSAlexander V. Chernikov
50f5baf8bbSAlexander V. Chernikov #include <netinet/in.h>
51f5baf8bbSAlexander V. Chernikov #include <netinet/in_var.h>
52f5baf8bbSAlexander V. Chernikov #include <netinet/ip.h>
53f5baf8bbSAlexander V. Chernikov #include <netinet/ip_var.h>
54f5baf8bbSAlexander V. Chernikov #include <netinet/ip6.h>
55f5baf8bbSAlexander V. Chernikov #include <netinet6/ip6_var.h>
56f5baf8bbSAlexander V. Chernikov #include <netinet6/in6_fib.h>
57f5baf8bbSAlexander V. Chernikov
58f5baf8bbSAlexander V. Chernikov #include <net/route.h>
59f5baf8bbSAlexander V. Chernikov #include <net/route/nhop.h>
60f5baf8bbSAlexander V. Chernikov #include <net/route/route_ctl.h>
61f5baf8bbSAlexander V. Chernikov #include <net/route/route_var.h>
62f5baf8bbSAlexander V. Chernikov #include <net/route/fib_algo.h>
63f5baf8bbSAlexander V. Chernikov
64f5baf8bbSAlexander V. Chernikov /*
65f5baf8bbSAlexander V. Chernikov * Lockless radix lookup algo.
66f5baf8bbSAlexander V. Chernikov *
67f5baf8bbSAlexander V. Chernikov * Compiles immutable radix from the current routing table.
68f5baf8bbSAlexander V. Chernikov * Used with small amount of routes (<1000).
69f5baf8bbSAlexander V. Chernikov * As datastructure is immutable, it gets rebuild on each rtable change.
70f5baf8bbSAlexander V. Chernikov *
71f5baf8bbSAlexander V. Chernikov */
72f5baf8bbSAlexander V. Chernikov
73f5baf8bbSAlexander V. Chernikov #define KEY_LEN_INET6 (offsetof(struct sa_in6, sin6_addr) + sizeof(struct in6_addr))
74f5baf8bbSAlexander V. Chernikov #define OFF_LEN_INET6 (8 * offsetof(struct sa_in6, sin6_addr))
75f5baf8bbSAlexander V. Chernikov struct sa_in6 {
76f5baf8bbSAlexander V. Chernikov uint8_t sin6_len;
77f5baf8bbSAlexander V. Chernikov uint8_t sin6_family;
78f5baf8bbSAlexander V. Chernikov uint8_t pad[6];
79f5baf8bbSAlexander V. Chernikov struct in6_addr sin6_addr;
80f5baf8bbSAlexander V. Chernikov };
81f5baf8bbSAlexander V. Chernikov struct radix6_addr_entry {
82f5baf8bbSAlexander V. Chernikov struct radix_node rn[2];
83f5baf8bbSAlexander V. Chernikov struct sa_in6 addr;
84f5baf8bbSAlexander V. Chernikov struct nhop_object *nhop;
85f5baf8bbSAlexander V. Chernikov };
86f5baf8bbSAlexander V. Chernikov #define LRADIX6_ITEM_SZ roundup2(sizeof(struct radix6_addr_entry), CACHE_LINE_SIZE)
87f5baf8bbSAlexander V. Chernikov
88f5baf8bbSAlexander V. Chernikov struct lradix6_data {
89f5baf8bbSAlexander V. Chernikov struct radix_node_head *rnh;
90f5baf8bbSAlexander V. Chernikov struct fib_data *fd;
91f5baf8bbSAlexander V. Chernikov void *mem; // raw radix_mem pointer to free
92f5baf8bbSAlexander V. Chernikov void *radix_mem;
93f5baf8bbSAlexander V. Chernikov uint32_t alloc_items;
94f5baf8bbSAlexander V. Chernikov uint32_t num_items;
95f5baf8bbSAlexander V. Chernikov };
96f5baf8bbSAlexander V. Chernikov
97f5baf8bbSAlexander V. Chernikov static struct nhop_object *
lradix6_lookup(void * algo_data,const struct flm_lookup_key key,uint32_t scopeid)98f5baf8bbSAlexander V. Chernikov lradix6_lookup(void *algo_data, const struct flm_lookup_key key, uint32_t scopeid)
99f5baf8bbSAlexander V. Chernikov {
100f5baf8bbSAlexander V. Chernikov struct radix_node_head *rnh = (struct radix_node_head *)algo_data;
101f5baf8bbSAlexander V. Chernikov struct radix6_addr_entry *ent;
102f5baf8bbSAlexander V. Chernikov struct sa_in6 addr6 = {
103f5baf8bbSAlexander V. Chernikov .sin6_len = KEY_LEN_INET6,
104f5baf8bbSAlexander V. Chernikov .sin6_addr = *key.addr6,
105f5baf8bbSAlexander V. Chernikov };
106f5baf8bbSAlexander V. Chernikov if (IN6_IS_SCOPE_LINKLOCAL(key.addr6))
107f5baf8bbSAlexander V. Chernikov addr6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
1082defbe9fSAlexander V. Chernikov ent = (struct radix6_addr_entry *)(rn_match(&addr6, &rnh->rh));
109f5baf8bbSAlexander V. Chernikov if (ent != NULL)
110f5baf8bbSAlexander V. Chernikov return (ent->nhop);
111f5baf8bbSAlexander V. Chernikov return (NULL);
112f5baf8bbSAlexander V. Chernikov }
113f5baf8bbSAlexander V. Chernikov
114f5baf8bbSAlexander V. Chernikov static uint8_t
lradix6_get_pref(const struct rib_rtable_info * rinfo)115f5baf8bbSAlexander V. Chernikov lradix6_get_pref(const struct rib_rtable_info *rinfo)
116f5baf8bbSAlexander V. Chernikov {
117f5baf8bbSAlexander V. Chernikov
118f5baf8bbSAlexander V. Chernikov if (rinfo->num_prefixes < 10)
119f5baf8bbSAlexander V. Chernikov return (255);
120d5be41beSAlexander V. Chernikov else if (rinfo->num_prefixes < 10000)
121d5be41beSAlexander V. Chernikov return (255 - rinfo->num_prefixes / 40);
122f5baf8bbSAlexander V. Chernikov else
123f5baf8bbSAlexander V. Chernikov return (1);
124f5baf8bbSAlexander V. Chernikov }
125f5baf8bbSAlexander V. Chernikov
126f5baf8bbSAlexander V. Chernikov static enum flm_op_result
lradix6_init(uint32_t fibnum,struct fib_data * fd,void * _old_data,void ** _data)127f5baf8bbSAlexander V. Chernikov lradix6_init(uint32_t fibnum, struct fib_data *fd, void *_old_data, void **_data)
128f5baf8bbSAlexander V. Chernikov {
129f5baf8bbSAlexander V. Chernikov struct lradix6_data *lr;
130f5baf8bbSAlexander V. Chernikov struct rib_rtable_info rinfo;
131f5baf8bbSAlexander V. Chernikov uint32_t count;
132f5baf8bbSAlexander V. Chernikov void *mem;
133f5baf8bbSAlexander V. Chernikov
134f5baf8bbSAlexander V. Chernikov lr = malloc(sizeof(struct lradix6_data), M_RTABLE, M_NOWAIT | M_ZERO);
135f5baf8bbSAlexander V. Chernikov if (lr == NULL || !rn_inithead((void **)&lr->rnh, OFF_LEN_INET6))
136f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
137f5baf8bbSAlexander V. Chernikov fib_get_rtable_info(fib_get_rh(fd), &rinfo);
138f5baf8bbSAlexander V. Chernikov
139f5baf8bbSAlexander V. Chernikov count = rinfo.num_prefixes * 11 / 10;
140f5baf8bbSAlexander V. Chernikov // count+1 adds at least 1 cache line
141f5baf8bbSAlexander V. Chernikov mem = malloc((count + 1) * LRADIX6_ITEM_SZ, M_RTABLE, M_NOWAIT | M_ZERO);
142f5baf8bbSAlexander V. Chernikov if (mem == NULL)
143f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
144f5baf8bbSAlexander V. Chernikov lr->mem = mem;
145f5baf8bbSAlexander V. Chernikov lr->radix_mem = (void *)roundup2((uintptr_t)mem, CACHE_LINE_SIZE);
146f5baf8bbSAlexander V. Chernikov lr->alloc_items = count;
147f5baf8bbSAlexander V. Chernikov lr->fd = fd;
148f5baf8bbSAlexander V. Chernikov
149f5baf8bbSAlexander V. Chernikov *_data = lr;
150f5baf8bbSAlexander V. Chernikov
151f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
152f5baf8bbSAlexander V. Chernikov }
153f5baf8bbSAlexander V. Chernikov
154f5baf8bbSAlexander V. Chernikov static void
lradix6_destroy(void * _data)155f5baf8bbSAlexander V. Chernikov lradix6_destroy(void *_data)
156f5baf8bbSAlexander V. Chernikov {
157f5baf8bbSAlexander V. Chernikov struct lradix6_data *lr = (struct lradix6_data *)_data;
158f5baf8bbSAlexander V. Chernikov
159f5baf8bbSAlexander V. Chernikov if (lr->rnh != NULL)
160f5baf8bbSAlexander V. Chernikov rn_detachhead((void **)&lr->rnh);
161f5baf8bbSAlexander V. Chernikov if (lr->mem != NULL)
162f5baf8bbSAlexander V. Chernikov free(lr->mem, M_RTABLE);
163f5baf8bbSAlexander V. Chernikov free(lr, M_RTABLE);
164f5baf8bbSAlexander V. Chernikov }
165f5baf8bbSAlexander V. Chernikov
166f5baf8bbSAlexander V. Chernikov static enum flm_op_result
lradix6_add_route_cb(struct rtentry * rt,void * _data)167f5baf8bbSAlexander V. Chernikov lradix6_add_route_cb(struct rtentry *rt, void *_data)
168f5baf8bbSAlexander V. Chernikov {
169f5baf8bbSAlexander V. Chernikov struct lradix6_data *lr = (struct lradix6_data *)_data;
170f5baf8bbSAlexander V. Chernikov struct radix6_addr_entry *ae;
171f5baf8bbSAlexander V. Chernikov struct sockaddr_in6 *rt_dst, *rt_mask;
172f5baf8bbSAlexander V. Chernikov struct sa_in6 mask;
173f5baf8bbSAlexander V. Chernikov struct radix_node *rn;
174f5baf8bbSAlexander V. Chernikov struct nhop_object *nh;
175f5baf8bbSAlexander V. Chernikov
176f5baf8bbSAlexander V. Chernikov nh = rt_get_raw_nhop(rt);
177f5baf8bbSAlexander V. Chernikov
178f5baf8bbSAlexander V. Chernikov if (lr->num_items >= lr->alloc_items)
179f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
180f5baf8bbSAlexander V. Chernikov
181f5baf8bbSAlexander V. Chernikov ae = (struct radix6_addr_entry *)((char *)lr->radix_mem + lr->num_items * LRADIX6_ITEM_SZ);
182f5baf8bbSAlexander V. Chernikov lr->num_items++;
183f5baf8bbSAlexander V. Chernikov
184f5baf8bbSAlexander V. Chernikov ae->nhop = nh;
185f5baf8bbSAlexander V. Chernikov
186f5baf8bbSAlexander V. Chernikov rt_dst = (struct sockaddr_in6 *)rt_key(rt);
187f5baf8bbSAlexander V. Chernikov rt_mask = (struct sockaddr_in6 *)rt_mask(rt);
188f5baf8bbSAlexander V. Chernikov
189f5baf8bbSAlexander V. Chernikov ae->addr.sin6_len = KEY_LEN_INET6;
190f5baf8bbSAlexander V. Chernikov ae->addr.sin6_addr = rt_dst->sin6_addr;
191f5baf8bbSAlexander V. Chernikov
192f5baf8bbSAlexander V. Chernikov if (rt_mask != NULL) {
193f5baf8bbSAlexander V. Chernikov bzero(&mask, sizeof(mask));
194f5baf8bbSAlexander V. Chernikov mask.sin6_len = KEY_LEN_INET6;
195f5baf8bbSAlexander V. Chernikov mask.sin6_addr = rt_mask->sin6_addr;
196f5baf8bbSAlexander V. Chernikov rt_mask = (struct sockaddr_in6 *)&mask;
197f5baf8bbSAlexander V. Chernikov }
198f5baf8bbSAlexander V. Chernikov
199f5baf8bbSAlexander V. Chernikov rn = lr->rnh->rnh_addaddr((struct sockaddr *)&ae->addr,
200f5baf8bbSAlexander V. Chernikov (struct sockaddr *)rt_mask, &lr->rnh->rh, ae->rn);
201f5baf8bbSAlexander V. Chernikov if (rn == NULL)
202f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
203f5baf8bbSAlexander V. Chernikov
204f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
205f5baf8bbSAlexander V. Chernikov }
206f5baf8bbSAlexander V. Chernikov
207f5baf8bbSAlexander V. Chernikov static enum flm_op_result
lradix6_end_dump(void * _data,struct fib_dp * dp)208f5baf8bbSAlexander V. Chernikov lradix6_end_dump(void *_data, struct fib_dp *dp)
209f5baf8bbSAlexander V. Chernikov {
210f5baf8bbSAlexander V. Chernikov struct lradix6_data *lr = (struct lradix6_data *)_data;
211f5baf8bbSAlexander V. Chernikov
212f5baf8bbSAlexander V. Chernikov dp->f = lradix6_lookup;
213f5baf8bbSAlexander V. Chernikov dp->arg = lr->rnh;
214f5baf8bbSAlexander V. Chernikov
215f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
216f5baf8bbSAlexander V. Chernikov }
217f5baf8bbSAlexander V. Chernikov
218f5baf8bbSAlexander V. Chernikov static enum flm_op_result
lradix6_change_cb(struct rib_head * rnh,struct rib_cmd_info * rc,void * _data)219f5baf8bbSAlexander V. Chernikov lradix6_change_cb(struct rib_head *rnh, struct rib_cmd_info *rc,
220f5baf8bbSAlexander V. Chernikov void *_data)
221f5baf8bbSAlexander V. Chernikov {
222f5baf8bbSAlexander V. Chernikov
223f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
224f5baf8bbSAlexander V. Chernikov }
225f5baf8bbSAlexander V. Chernikov
226f5baf8bbSAlexander V. Chernikov struct fib_lookup_module flm_radix6_lockless = {
227f5baf8bbSAlexander V. Chernikov .flm_name = "radix6_lockless",
228f5baf8bbSAlexander V. Chernikov .flm_family = AF_INET6,
229f5baf8bbSAlexander V. Chernikov .flm_init_cb = lradix6_init,
230f5baf8bbSAlexander V. Chernikov .flm_destroy_cb = lradix6_destroy,
231f5baf8bbSAlexander V. Chernikov .flm_dump_rib_item_cb = lradix6_add_route_cb,
232f5baf8bbSAlexander V. Chernikov .flm_dump_end_cb = lradix6_end_dump,
233f5baf8bbSAlexander V. Chernikov .flm_change_rib_item_cb = lradix6_change_cb,
234f5baf8bbSAlexander V. Chernikov .flm_get_pref = lradix6_get_pref,
235f5baf8bbSAlexander V. Chernikov };
236f5baf8bbSAlexander V. Chernikov
237f5baf8bbSAlexander V. Chernikov /*
238f5baf8bbSAlexander V. Chernikov * Fallback lookup algorithm.
239f5baf8bbSAlexander V. Chernikov * This is a simple wrapper around system radix.
240f5baf8bbSAlexander V. Chernikov */
241f5baf8bbSAlexander V. Chernikov
242f5baf8bbSAlexander V. Chernikov struct radix6_data {
243f5baf8bbSAlexander V. Chernikov struct fib_data *fd;
244f5baf8bbSAlexander V. Chernikov struct rib_head *rh;
245f5baf8bbSAlexander V. Chernikov };
246f5baf8bbSAlexander V. Chernikov
247f5baf8bbSAlexander V. Chernikov static struct nhop_object *
radix6_lookup(void * algo_data,const struct flm_lookup_key key,uint32_t scopeid)248f5baf8bbSAlexander V. Chernikov radix6_lookup(void *algo_data, const struct flm_lookup_key key, uint32_t scopeid)
249f5baf8bbSAlexander V. Chernikov {
250f5baf8bbSAlexander V. Chernikov RIB_RLOCK_TRACKER;
251f5baf8bbSAlexander V. Chernikov struct rib_head *rh = (struct rib_head *)algo_data;
252f5baf8bbSAlexander V. Chernikov struct radix_node *rn;
253f5baf8bbSAlexander V. Chernikov struct nhop_object *nh;
254f5baf8bbSAlexander V. Chernikov
255f5baf8bbSAlexander V. Chernikov /* Prepare lookup key */
256f5baf8bbSAlexander V. Chernikov struct sockaddr_in6 sin6 = {
257f5baf8bbSAlexander V. Chernikov .sin6_family = AF_INET6,
258f5baf8bbSAlexander V. Chernikov .sin6_len = sizeof(struct sockaddr_in6),
259f5baf8bbSAlexander V. Chernikov .sin6_addr = *key.addr6,
260f5baf8bbSAlexander V. Chernikov };
261f5baf8bbSAlexander V. Chernikov if (IN6_IS_SCOPE_LINKLOCAL(key.addr6))
262f5baf8bbSAlexander V. Chernikov sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
263f5baf8bbSAlexander V. Chernikov
264f5baf8bbSAlexander V. Chernikov nh = NULL;
265f5baf8bbSAlexander V. Chernikov RIB_RLOCK(rh);
2662defbe9fSAlexander V. Chernikov rn = rn_match((void *)&sin6, &rh->head);
267f5baf8bbSAlexander V. Chernikov if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0))
268f5baf8bbSAlexander V. Chernikov nh = (RNTORT(rn))->rt_nhop;
269f5baf8bbSAlexander V. Chernikov RIB_RUNLOCK(rh);
270f5baf8bbSAlexander V. Chernikov
271f5baf8bbSAlexander V. Chernikov return (nh);
272f5baf8bbSAlexander V. Chernikov }
273f5baf8bbSAlexander V. Chernikov
274f5baf8bbSAlexander V. Chernikov struct nhop_object *
fib6_radix_lookup_nh(uint32_t fibnum,const struct in6_addr * dst6,uint32_t scopeid)275f5baf8bbSAlexander V. Chernikov fib6_radix_lookup_nh(uint32_t fibnum, const struct in6_addr *dst6, uint32_t scopeid)
276f5baf8bbSAlexander V. Chernikov {
277f5baf8bbSAlexander V. Chernikov struct rib_head *rh = rh = rt_tables_get_rnh(fibnum, AF_INET6);
278f5baf8bbSAlexander V. Chernikov const struct flm_lookup_key key = { .addr6 = dst6 };
279f5baf8bbSAlexander V. Chernikov
280f5baf8bbSAlexander V. Chernikov if (rh == NULL)
281f5baf8bbSAlexander V. Chernikov return (NULL);
282f5baf8bbSAlexander V. Chernikov
283f5baf8bbSAlexander V. Chernikov return (radix6_lookup(rh, key, scopeid));
284f5baf8bbSAlexander V. Chernikov }
285f5baf8bbSAlexander V. Chernikov
286f5baf8bbSAlexander V. Chernikov static uint8_t
radix6_get_pref(const struct rib_rtable_info * rinfo)287f5baf8bbSAlexander V. Chernikov radix6_get_pref(const struct rib_rtable_info *rinfo)
288f5baf8bbSAlexander V. Chernikov {
289f5baf8bbSAlexander V. Chernikov
290f5baf8bbSAlexander V. Chernikov return (50);
291f5baf8bbSAlexander V. Chernikov }
292f5baf8bbSAlexander V. Chernikov
293f5baf8bbSAlexander V. Chernikov static enum flm_op_result
radix6_init(uint32_t fibnum,struct fib_data * fd,void * _old_data,void ** _data)294f5baf8bbSAlexander V. Chernikov radix6_init(uint32_t fibnum, struct fib_data *fd, void *_old_data, void **_data)
295f5baf8bbSAlexander V. Chernikov {
296f5baf8bbSAlexander V. Chernikov struct radix6_data *r6;
297f5baf8bbSAlexander V. Chernikov
298f5baf8bbSAlexander V. Chernikov r6 = malloc(sizeof(struct radix6_data), M_RTABLE, M_NOWAIT | M_ZERO);
299f5baf8bbSAlexander V. Chernikov if (r6 == NULL)
300f5baf8bbSAlexander V. Chernikov return (FLM_REBUILD);
301f5baf8bbSAlexander V. Chernikov r6->fd = fd;
302f5baf8bbSAlexander V. Chernikov r6->rh = fib_get_rh(fd);
303f5baf8bbSAlexander V. Chernikov
304f5baf8bbSAlexander V. Chernikov *_data = r6;
305f5baf8bbSAlexander V. Chernikov
306f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
307f5baf8bbSAlexander V. Chernikov }
308f5baf8bbSAlexander V. Chernikov
309f5baf8bbSAlexander V. Chernikov static void
radix6_destroy(void * _data)310f5baf8bbSAlexander V. Chernikov radix6_destroy(void *_data)
311f5baf8bbSAlexander V. Chernikov {
312f5baf8bbSAlexander V. Chernikov
313f5baf8bbSAlexander V. Chernikov free(_data, M_RTABLE);
314f5baf8bbSAlexander V. Chernikov }
315f5baf8bbSAlexander V. Chernikov
316f5baf8bbSAlexander V. Chernikov static enum flm_op_result
radix6_add_route_cb(struct rtentry * rt,void * _data)317f5baf8bbSAlexander V. Chernikov radix6_add_route_cb(struct rtentry *rt, void *_data)
318f5baf8bbSAlexander V. Chernikov {
319f5baf8bbSAlexander V. Chernikov
320f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
321f5baf8bbSAlexander V. Chernikov }
322f5baf8bbSAlexander V. Chernikov
323f5baf8bbSAlexander V. Chernikov static enum flm_op_result
radix6_end_dump(void * _data,struct fib_dp * dp)324f5baf8bbSAlexander V. Chernikov radix6_end_dump(void *_data, struct fib_dp *dp)
325f5baf8bbSAlexander V. Chernikov {
326f5baf8bbSAlexander V. Chernikov struct radix6_data *r6 = (struct radix6_data *)_data;
327f5baf8bbSAlexander V. Chernikov
328f5baf8bbSAlexander V. Chernikov dp->f = radix6_lookup;
329f5baf8bbSAlexander V. Chernikov dp->arg = r6->rh;
330f5baf8bbSAlexander V. Chernikov
331f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
332f5baf8bbSAlexander V. Chernikov }
333f5baf8bbSAlexander V. Chernikov
334f5baf8bbSAlexander V. Chernikov static enum flm_op_result
radix6_change_cb(struct rib_head * rnh,struct rib_cmd_info * rc,void * _data)335f5baf8bbSAlexander V. Chernikov radix6_change_cb(struct rib_head *rnh, struct rib_cmd_info *rc,
336f5baf8bbSAlexander V. Chernikov void *_data)
337f5baf8bbSAlexander V. Chernikov {
338f5baf8bbSAlexander V. Chernikov
339f5baf8bbSAlexander V. Chernikov return (FLM_SUCCESS);
340f5baf8bbSAlexander V. Chernikov }
341f5baf8bbSAlexander V. Chernikov
342f5baf8bbSAlexander V. Chernikov struct fib_lookup_module flm_radix6 = {
343f5baf8bbSAlexander V. Chernikov .flm_name = "radix6",
344f5baf8bbSAlexander V. Chernikov .flm_family = AF_INET6,
345f5baf8bbSAlexander V. Chernikov .flm_init_cb = radix6_init,
346f5baf8bbSAlexander V. Chernikov .flm_destroy_cb = radix6_destroy,
347f5baf8bbSAlexander V. Chernikov .flm_dump_rib_item_cb = radix6_add_route_cb,
348f5baf8bbSAlexander V. Chernikov .flm_dump_end_cb = radix6_end_dump,
349f5baf8bbSAlexander V. Chernikov .flm_change_rib_item_cb = radix6_change_cb,
350f5baf8bbSAlexander V. Chernikov .flm_get_pref = radix6_get_pref,
351f5baf8bbSAlexander V. Chernikov };
352f5baf8bbSAlexander V. Chernikov
353f5baf8bbSAlexander V. Chernikov static void
fib6_algo_init(void)354f5baf8bbSAlexander V. Chernikov fib6_algo_init(void)
355f5baf8bbSAlexander V. Chernikov {
356f5baf8bbSAlexander V. Chernikov
357f5baf8bbSAlexander V. Chernikov fib_module_register(&flm_radix6_lockless);
358f5baf8bbSAlexander V. Chernikov fib_module_register(&flm_radix6);
359f5baf8bbSAlexander V. Chernikov }
360f5baf8bbSAlexander V. Chernikov SYSINIT(fib6_algo_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, fib6_algo_init, NULL);
361