tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[patch] hide forwarding table implementation (radix trie)



This patch hides the radix-trie implementation of the forwarding
table so that we will have an easier time replacing it with something
different, even if it is a second radix-trie implementation.  Comments?

Dave

-- 
David Young             OJC Technologies
dyoung%ojctech.com@localhost      Urbana, IL * (217) 344-0444 x24
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.1005
diff -u -p -r1.1005 files
--- sys/conf/files      20 Mar 2011 17:54:02 -0000      1.1005
+++ sys/conf/files      28 Mar 2011 22:07:59 -0000
@@ -1654,6 +1659,7 @@ file      net/radix.c
 file   net/raw_cb.c
 file   net/raw_usrreq.c
 file   net/route.c
+file   net/rtbl.c
 file   net/rtsock.c
 file   net/slcompress.c                sl | ppp | strip | (irip & irip_vj)
 file   net/zlib.c                      (ppp & ppp_deflate) | ipsec | 
opencrypto | vnd_compression
Index: sys/net/route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.124
diff -u -p -r1.124 route.c
--- sys/net/route.c     1 Feb 2011 01:39:20 -0000       1.124
+++ sys/net/route.c     28 Mar 2011 22:08:05 -0000
@@ -96,6 +96,7 @@
 __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.124 2011/02/01 01:39:20 matt Exp $");
 
 #include <sys/param.h>
+#include <sys/kmem.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 #include <sys/callout.h>
@@ -125,7 +126,6 @@ __KERNEL_RCSID(0, "$NetBSD: route.c,v 1.
 #endif /* RTFLUSH_DEBUG */
 
 struct rtstat  rtstat;
-struct radix_node_head *rt_tables[AF_MAX+1];
 
 int    rttrash;                /* routes not in table but not freed */
 
@@ -252,16 +244,6 @@ rt_set_ifa(struct rtentry *rt, struct if
        rt_set_ifa1(rt, ifa);
 }
 
-void
-rtable_init(void **table)
-{
-       struct domain *dom;
-       DOMAIN_FOREACH(dom)
-               if (dom->dom_rtattach)
-                       dom->dom_rtattach(&table[dom->dom_family],
-                           dom->dom_rtoffset);
-}
-
 static int
 route_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
     void *arg0, void *arg1, void *arg2, void *arg3)
@@ -295,7 +277,7 @@ rt_init(void)
            NULL, IPL_SOFTNET);
 
        rn_init();      /* initialize all zeroes, all ones, mask table */
-       rtable_init((void **)rt_tables);
+       rtbl_init();
 
        route_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
            route_listener_cb, NULL);
@@ -338,16 +320,14 @@ rtcache(struct route *ro)
 struct rtentry *
 rtalloc1(const struct sockaddr *dst, int report)
 {
-       struct radix_node_head *rnh = rt_tables[dst->sa_family];
+       rtbl_t *rtbl = rt_gettable(dst->sa_family);
        struct rtentry *rt;
-       struct radix_node *rn;
        struct rtentry *newrt = NULL;
        struct rt_addrinfo info;
        int  s = splsoftnet(), err = 0, msgtype = RTM_MISS;
 
-       if (rnh && (rn = rnh->rnh_matchaddr(dst, rnh)) &&
-           ((rn->rn_flags & RNF_ROOT) == 0)) {
-               newrt = rt = (struct rtentry *)rn;
+       if (rtbl != NULL && (rt = rt_matchaddr(rtbl, dst)) != NULL) {
+               newrt = rt;
                if (report && (rt->rt_flags & RTF_CLONING)) {
                        err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0,
                            &newrt);
@@ -395,8 +375,7 @@ rtfree(struct rtentry *rt)
                panic("rtfree");
        rt->rt_refcnt--;
        if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
-               if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
-                       panic ("rtfree 2");
+               rt_assert_inactive(rt);
                rttrash--;
                if (rt->rt_refcnt < 0) {
                        printf("rtfree: %p not freed (neg refs)\n", rt);
@@ -697,10 +676,9 @@ int
 rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
 {
        int s = splsoftnet();
-       int error = 0;
+       int error = 0, rc;
        struct rtentry *rt, *crt;
-       struct radix_node *rn;
-       struct radix_node_head *rnh;
+       rtbl_t *rtbl;
        struct ifaddr *ifa, *ifa2;
        struct sockaddr_storage maskeddst;
        const struct sockaddr *dst = info->rti_info[RTAX_DST];
@@ -709,7 +687,7 @@ rtrequest1(int req, struct rt_addrinfo *
        int flags = info->rti_flags;
 #define senderr(x) { error = x ; goto bad; }
 
-       if ((rnh = rt_tables[dst->sa_family]) == NULL)
+       if ((rtbl = rt_gettable(dst->sa_family)) == NULL)
                senderr(ESRCH);
        if (flags & RTF_HOST)
                netmask = NULL;
@@ -720,18 +698,14 @@ rtrequest1(int req, struct rt_addrinfo *
                            netmask);
                        dst = (struct sockaddr *)&maskeddst;
                }
-               if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == NULL)
+               if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
                        senderr(ESRCH);
-               rt = (struct rtentry *)rn;
                if ((rt->rt_flags & RTF_CLONING) != 0) {
                        /* clean up any cloned children */
                        rtflushclone(dst->sa_family, rt);
                }
-               if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL)
+               if ((rt = rt_deladdr(rtbl, dst, netmask)) == NULL)
                        senderr(ESRCH);
-               if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
-                       panic ("rtrequest delete");
-               rt = (struct rtentry *)rn;
                if (rt->rt_gwroute) {
                        RTFREE(rt->rt_gwroute);
                        rt->rt_gwroute = NULL;
@@ -817,21 +791,19 @@ rtrequest1(int req, struct rt_addrinfo *
                        rt->rt_parent->rt_refcnt++;
                }
                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
-               rn = rnh->rnh_addaddr(rt_getkey(rt), netmask, rnh,
-                   rt->rt_nodes);
+               rc = rt_addaddr(rtbl, rt, netmask);
                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
-               if (rn == NULL && (crt = rtalloc1(rt_getkey(rt), 0)) != NULL) {
+               if (rc != 0 && (crt = rtalloc1(rt_getkey(rt), 0)) != NULL) {
                        /* overwrite cloned route */
                        if ((crt->rt_flags & RTF_CLONED) != 0) {
                                rtdeletemsg(crt);
-                               rn = rnh->rnh_addaddr(rt_getkey(rt),
-                                   netmask, rnh, rt->rt_nodes);
+                               rc = rt_addaddr(rtbl, rt, netmask);
                        }
                        RTFREE(crt);
                        RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
                }
                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
-               if (rn == NULL) {
+               if (rc != 0) {
                        IFAFREE(ifa);
                        if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent)
                                rtfree(rt->rt_parent);
@@ -839,7 +811,7 @@ rtrequest1(int req, struct rt_addrinfo *
                                rtfree(rt->rt_gwroute);
                        rt_destroy(rt);
                        pool_put(&rtentry_pool, rt);
-                       senderr(EEXIST);
+                       senderr(rc);
                }
                RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
                if (ifa->ifa_rtrequest)
@@ -861,11 +833,9 @@ rtrequest1(int req, struct rt_addrinfo *
                            netmask);
                        dst = (struct sockaddr *)&maskeddst;
                }
-               rn = rnh->rnh_lookup(dst, netmask, rnh);
-               if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
+               if ((rt = rt_lookup(rtbl, dst, netmask)) == NULL)
                        senderr(ESRCH);
                if (ret_nrt != NULL) {
-                       rt = (struct rtentry *)rn;
                        *ret_nrt = rt;
                        rt->rt_refcnt++;
                }
@@ -1391,29 +1361,6 @@ rtcache_setdst(struct route *ro, const s
        return 0;
 }
 
-static int
-rt_walktree_visitor(struct radix_node *rn, void *v)
-{
-       struct rtwalk *rw = (struct rtwalk *)v;
-
-       return (*rw->rw_f)((struct rtentry *)rn, rw->rw_v);
-}
-
-int
-rt_walktree(sa_family_t family, int (*f)(struct rtentry *, void *), void *v)
-{
-       struct radix_node_head *rnh = rt_tables[family];
-       struct rtwalk rw;
-
-       if (rnh == NULL)
-               return 0;
-
-       rw.rw_f = f;
-       rw.rw_v = v;
-
-       return rn_walktree(rnh, rt_walktree_visitor, &rw);
-}
-
 const struct sockaddr *
 rt_settag(struct rtentry *rt, const struct sockaddr *tag)
 {
Index: sys/net/route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.78
diff -u -p -r1.78 route.h
--- sys/net/route.h     1 Feb 2011 01:39:20 -0000       1.78
+++ sys/net/route.h     28 Mar 2011 22:08:05 -0000
@@ -309,8 +308,15 @@ struct rttimer_queue {
 };
 
 
+struct rtbl;
+typedef struct rtbl rtbl_t;
+
 #ifdef _KERNEL
 
+struct rtbl {
+       struct radix_node_head t_rnh;
+};
+
 struct rt_walkarg {
        int     w_op;
        int     w_arg;
@@ -347,7 +353,6 @@ struct route_info {
 
 extern struct  route_info route_info;
 extern struct  rtstat  rtstat;
-extern struct  radix_node_head *rt_tables[AF_MAX+1];
 
 struct socket;
 struct dom_rtlist;
@@ -375,7 +380,6 @@ void         rt_timer_queue_destroy(struct rtti
 void    rt_timer_remove_all(struct rtentry *, int);
 unsigned long  rt_timer_count(struct rttimer_queue *);
 void    rt_timer_timer(void *);
-void    rtable_init(void **);
 void    rtcache(struct route *);
 void    rtflushall(int);
 struct rtentry *
@@ -425,8 +429,6 @@ out:
        return rt->_rt_key;
 }
 
-struct rtentry *rtfindparent(struct radix_node_head *, struct route *);
-
 struct rtentry *rtcache_init(struct route *);
 struct rtentry *rtcache_init_noclone(struct route *);
 void   rtcache_copy(struct route *, const struct route *);
@@ -502,9 +504,19 @@ RTFREE(struct rtentry *rt)
                rt->rt_refcnt--;
 }
 
-int
-rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
+int rt_walktree(sa_family_t, int (*)(struct rtentry *, void *), void *);
 void route_enqueue(struct mbuf *, int);
+int rt_inithead(rtbl_t **, int);
+struct rtentry *rt_matchaddr(rtbl_t *, const struct sockaddr *);
+int rt_addaddr(rtbl_t *, struct rtentry *, const struct sockaddr *);
+struct rtentry *rt_lookup(rtbl_t *, const struct sockaddr *,
+    const struct sockaddr *);
+struct rtentry *rt_deladdr(rtbl_t *, const struct sockaddr *,
+    const struct sockaddr *);
+void rtbl_init(void);
+rtbl_t *rt_gettable(sa_family_t);
+void rt_assert_inactive(const struct rtentry *);
 
 #endif /* _KERNEL */
+
 #endif /* !_NET_ROUTE_H_ */
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.134
diff -u -p -r1.134 rtsock.c
--- sys/net/rtsock.c    10 Feb 2011 07:42:18 -0000      1.134
+++ sys/net/rtsock.c    28 Mar 2011 22:08:06 -0000
@@ -231,19 +231,6 @@ COMPATNAME(route_usrreq)(struct socket *
        return error;
 }
 
-static const struct sockaddr *
-intern_netmask(const struct sockaddr *mask)
-{
-       struct radix_node *rn;
-       extern struct radix_node_head *mask_rnhead;
-
-       if (mask != NULL &&
-           (rn = rn_search(mask, mask_rnhead->rnh_treetop)))
-               mask = (const struct sockaddr *)rn->rn_key;
-
-       return mask;
-}
-
 /*ARGSUSED*/
 int
 COMPATNAME(route_output)(struct mbuf *m, ...)
@@ -351,20 +340,12 @@ COMPATNAME(route_output)(struct mbuf *m,
                if (error != 0)
                        senderr(error);
                if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
-                       struct radix_node *rn;
-
                        if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt),
                            info.rti_info[RTAX_DST]->sa_len) != 0)
                                senderr(ESRCH);
-                       info.rti_info[RTAX_NETMASK] = intern_netmask(
-                           info.rti_info[RTAX_NETMASK]);
-                       for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
-                               if (info.rti_info[RTAX_NETMASK] ==
-                                   (const struct sockaddr *)rn->rn_mask)
-                                       break;
-                       if (rn == NULL)
+                       if (info.rti_info[RTAX_NETMASK] == NULL &&
+                           rt_mask(rt) != NULL)
                                senderr(ETOOMANYREFS);
-                       rt = (struct rtentry *)rn;
                }
 
                switch (rtm->rtm_type) {
Index: sys/netatalk/at_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netatalk/at_proto.c,v
retrieving revision 1.16
diff -u -p -r1.16 at_proto.c
--- sys/netatalk/at_proto.c     24 Apr 2008 11:38:37 -0000      1.16
+++ sys/netatalk/at_proto.c     28 Mar 2011 22:08:06 -0000
@@ -73,7 +73,7 @@ struct domain atalkdomain = {
        .dom_dispose = NULL,
        .dom_protosw = atalksw,
        .dom_protoswNPROTOSW = &atalksw[__arraycount(atalksw)],
-       .dom_rtattach = rn_inithead,
+       .dom_rtattach = rt_inithead,
        .dom_rtoffset = 32,
        .dom_maxrtkey = sizeof(struct sockaddr_at),
        .dom_ifattach = NULL,
Index: sys/netinet/in_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/in_proto.c,v
retrieving revision 1.99
diff -u -p -r1.99 in_proto.c
--- sys/netinet/in_proto.c      16 Sep 2009 15:23:05 -0000      1.99
+++ sys/netinet/in_proto.c      28 Mar 2011 22:08:06 -0000
@@ -467,7 +467,7 @@ struct domain inetdomain = {
        .dom_externalize = NULL, .dom_dispose = NULL,
        .dom_protosw = inetsw,
        .dom_protoswNPROTOSW = &inetsw[__arraycount(inetsw)],
-       .dom_rtattach = rn_inithead,
+       .dom_rtattach = rt_inithead,
        .dom_rtoffset = 32,
        .dom_maxrtkey = sizeof(struct ip_pack4),
 #ifdef IPSELSRC
Index: sys/netinet6/in6_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.89
diff -u -p -r1.89 in6_proto.c
--- sys/netinet6/in6_proto.c    24 Aug 2010 00:07:00 -0000      1.89
+++ sys/netinet6/in6_proto.c    28 Mar 2011 22:08:07 -0000
@@ -412,7 +412,7 @@ struct domain inet6domain = {
        .dom_init = NULL, .dom_externalize = NULL, .dom_dispose = NULL,
        .dom_protosw = (const struct protosw *)inet6sw,
        .dom_protoswNPROTOSW = (const struct protosw 
*)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])],
-       .dom_rtattach = rn_inithead,
+       .dom_rtattach = rt_inithead,
        .dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
        .dom_maxrtkey = sizeof(struct ip_pack6),
        .dom_ifattach = in6_domifattach, .dom_ifdetach = in6_domifdetach,
Index: sys/netiso/iso_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netiso/iso_proto.c,v
retrieving revision 1.28
diff -u -p -r1.28 iso_proto.c
--- sys/netiso/iso_proto.c      24 Apr 2008 11:38:38 -0000      1.28
+++ sys/netiso/iso_proto.c      28 Mar 2011 22:08:07 -0000
@@ -261,8 +261,8 @@ struct domain   isodomain = {
        .dom_dispose = NULL,
        .dom_protosw = isosw,
        .dom_protoswNPROTOSW = &isosw[sizeof(isosw) / sizeof(isosw[0])],
-       .dom_rtattach = rn_inithead,            /* rtattach */
-       .dom_rtoffset = 48,                     /* rtoffset */
+       .dom_rtattach = rt_inithead,
+       .dom_rtoffset = 48,
        .dom_maxrtkey = sizeof(struct sockaddr_iso),    /* maxkeylen */
        .dom_ifattach = NULL,
        .dom_ifdetach = NULL,
Index: sys/netmpls/mpls_proto.c
===================================================================
RCS file: /cvsroot/src/sys/netmpls/mpls_proto.c,v
retrieving revision 1.1
diff -u -p -r1.1 mpls_proto.c
--- sys/netmpls/mpls_proto.c    26 Jun 2010 14:24:29 -0000      1.1
+++ sys/netmpls/mpls_proto.c    28 Mar 2011 22:08:07 -0000
@@ -102,7 +102,7 @@ struct domain mplsdomain = {
        .dom_dispose = NULL, 
        .dom_protosw = mplssw,
        .dom_protoswNPROTOSW = &mplssw[__arraycount(mplssw)],
-       .dom_rtattach = rn_inithead,
+       .dom_rtattach = rt_inithead,
        .dom_rtoffset = offsetof(struct sockaddr_mpls, smpls_addr) << 3,
        .dom_maxrtkey = sizeof(union mpls_shim),
        .dom_ifattach = NULL,
Index: sys/nfs/nfs_export.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_export.c,v
retrieving revision 1.49
diff -u -p -r1.49 nfs_export.c
--- sys/nfs/nfs_export.c        19 Nov 2010 06:44:46 -0000      1.49
+++ sys/nfs/nfs_export.c        28 Mar 2011 22:08:07 -0000
@@ -561,7 +561,7 @@ hang_addrlist(struct mount *mp, struct n
                 */
                DOMAIN_FOREACH(dom) {
                        if (dom->dom_family == i && dom->dom_rtattach) {
-                               dom->dom_rtattach((void **)&nep->ne_rtable[i],
+                               rn_inithead((void **)&nep->ne_rtable[i],
                                        dom->dom_rtoffset);
                                break;
                        }
Index: sys/rump/librump/rumpnet/Makefile.rumpnet
===================================================================
RCS file: /cvsroot/src/sys/rump/librump/rumpnet/Makefile.rumpnet,v
retrieving revision 1.11
diff -u -p -r1.11 Makefile.rumpnet
--- sys/rump/librump/rumpnet/Makefile.rumpnet   1 Feb 2011 01:39:21 -0000       
1.11
+++ sys/rump/librump/rumpnet/Makefile.rumpnet   28 Mar 2011 22:08:08 -0000
@@ -20,6 +20,7 @@ SRCS+=        sys_socket.c uipc_accf.c uipc_dom
 
 # radix trie support
 SRCS+= radix.c
+SRCS+= rtbl.c
 
 # compat (nothing for now)
 SRCS+= 
Index: sys/rump/net/lib/libnet/Makefile
===================================================================
RCS file: /cvsroot/src/sys/rump/net/lib/libnet/Makefile,v
retrieving revision 1.11
diff -u -p -r1.11 Makefile
--- sys/rump/net/lib/libnet/Makefile    1 Feb 2011 01:39:21 -0000       1.11
+++ sys/rump/net/lib/libnet/Makefile    28 Mar 2011 22:08:08 -0000
@@ -6,10 +6,10 @@
 LIB=   rumpnet_net
 
 # iffy stuff
-SRCS=  if.c if_loop.c route.c rtsock.c rtsock_50.c raw_usrreq.c        \
+SRCS=  if.c if_loop.c route.c rtbl.c rtsock.c rtsock_50.c raw_usrreq.c \
        raw_cb.c if_media.c link_proto.c net_stats.c if_ethersubr.c
 SRCS+= if_43.c uipc_syscalls_50.c
 SRCS+= component.c
 
 CPPFLAGS+=     -I${.CURDIR}/opt -I${.CURDIR}/../libnetinet/opt
 CPPFLAGS+=     -DCOMPAT_OIFREQ -DCOMPAT_OIFDATA
Index: sys/rump/net/lib/libsockin/sockin.c
===================================================================
RCS file: /cvsroot/src/sys/rump/net/lib/libsockin/sockin.c,v
retrieving revision 1.25
diff -u -p -r1.25 sockin.c
--- sys/rump/net/lib/libsockin/sockin.c 5 Dec 2010 18:01:46 -0000       1.25
+++ sys/rump/net/lib/libsockin/sockin.c 28 Mar 2011 22:08:08 -0000
@@ -93,7 +93,7 @@ struct domain sockindomain = {
        .dom_dispose = NULL,
        .dom_protosw = sockinsw,
        .dom_protoswNPROTOSW = &sockinsw[__arraycount(sockinsw)],
-       .dom_rtattach = rn_inithead,
+       .dom_rtattach = rt_inithead,
        .dom_rtoffset = 32,
        .dom_maxrtkey = sizeof(struct sockaddr_in),
        .dom_ifattach = NULL,
Index: sys/sys/domain.h
===================================================================
RCS file: /cvsroot/src/sys/sys/domain.h,v
retrieving revision 1.29
diff -u -p -r1.29 domain.h
--- sys/sys/domain.h    11 Sep 2009 22:06:29 -0000      1.29
+++ sys/sys/domain.h    28 Mar 2011 22:08:08 -0000
@@ -39,6 +39,7 @@
  */
 #include <sys/mbuf.h>
 #include <sys/socket.h>
+#include <net/route.h>
 
 /*
  * Forward structure declarations for function prototypes [sic].
@@ -47,7 +48,6 @@ struct        lwp;
 struct mbuf;
 struct ifnet;
 struct ifqueue;
-struct  route;
 struct  sockaddr;
 
 LIST_HEAD(dom_rtlist, route);
@@ -63,7 +63,7 @@ struct        domain {
                        (struct mbuf *);
        const struct protosw *dom_protosw, *dom_protoswNPROTOSW;
        int     (*dom_rtattach)         /* initialize routing table */
-                       (void **, int);
+                       (rtbl_t **, int);
        int     dom_rtoffset;           /* an arg to rtattach, in bits */
        int     dom_maxrtkey;           /* for routing layer */
        void    *(*dom_ifattach)        /* attach af-dependent data on ifnet */
/*      $NetBSD: route.c,v 1.124 2011/02/01 01:39:20 matt Exp $ */

/*-
 * Copyright (c) 1998, 2008, 2011 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Kevin M. Lahey of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Copyright (c) 1980, 1986, 1991, 1993
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *      @(#)route.c     8.3 (Berkeley) 1/9/95
 */

#ifdef _KERNEL
#include "opt_route.h"
#endif /* _KERNEL */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD$");

#include <sys/param.h>
#include <sys/kmem.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/callout.h>
#include <sys/proc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
#include <sys/ioctl.h>
#include <sys/pool.h>
#include <sys/kauth.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <net/raw_cb.h>

static rtbl_t *rt_tables[AF_MAX+1];

int
rt_inithead(rtbl_t **tp, int off)
{
        rtbl_t *t;
        if (*tp != NULL)
                return 1;
        if ((t = kmem_alloc(sizeof(*t), KM_SLEEP)) == NULL)
                return 0;
        *tp = t;
        return rn_inithead0(&t->t_rnh, off);
}

struct rtentry *
rt_matchaddr(rtbl_t *t, const struct sockaddr *dst)
{
        struct radix_node_head *rnh = &t->t_rnh;
        struct radix_node *rn;

        rn = rnh->rnh_matchaddr(dst, rnh);
        if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
                return NULL;
        return (struct rtentry *)rn;
}

int
rt_addaddr(rtbl_t *t, struct rtentry *rt, const struct sockaddr *netmask)
{
        struct radix_node_head *rnh = &t->t_rnh;
        struct radix_node *rn;

        rn = rnh->rnh_addaddr(rt_getkey(rt), netmask, rnh, rt->rt_nodes);

        return (rn == NULL) ? EEXIST : 0;
}

struct rtentry *
rt_lookup(rtbl_t *t, const struct sockaddr *dst, const struct sockaddr *netmask)
{
        struct radix_node_head *rnh = &t->t_rnh;
        struct radix_node *rn;

        rn = rnh->rnh_lookup(dst, netmask, rnh);
        if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
                return NULL;
        return (struct rtentry *)rn;
}

struct rtentry *
rt_deladdr(rtbl_t *t, const struct sockaddr *dst,
    const struct sockaddr *netmask)
{
        struct radix_node_head *rnh = &t->t_rnh;
        struct radix_node *rn;

        if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == NULL)
                return NULL;
        if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
                panic("%s", __func__);
        return (struct rtentry *)rn;
}

static int
rt_walktree_visitor(struct radix_node *rn, void *v)
{
        struct rtwalk *rw = (struct rtwalk *)v;

        return (*rw->rw_f)((struct rtentry *)rn, rw->rw_v);
}

int
rt_walktree(sa_family_t family, int (*f)(struct rtentry *, void *), void *v)
{
        rtbl_t *t = rt_tables[family];
        struct rtwalk rw;

        if (t == NULL)
                return 0;

        rw.rw_f = f;
        rw.rw_v = v;

        return rn_walktree(&t->t_rnh, rt_walktree_visitor, &rw);
}

rtbl_t *
rt_gettable(sa_family_t af)
{
        if (af >= __arraycount(rt_tables))
                return NULL;
        return rt_tables[af];
}

void
rtbl_init(void)
{
        struct domain *dom;
        DOMAIN_FOREACH(dom)
                if (dom->dom_rtattach)
                        dom->dom_rtattach(&rt_tables[dom->dom_family],
                            dom->dom_rtoffset);
}

void
rt_assert_inactive(const struct rtentry *rt)
{
        if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
                panic ("rtfree 2");
}


Home | Main Index | Thread Index | Old Index