Changeset View
Changeset View
Standalone View
Standalone View
sys/net/route.c
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
#ifdef RADIX_MPATH | #ifdef RADIX_MPATH | ||||
#include <net/radix_mpath.h> | #include <net/radix_mpath.h> | ||||
#endif | #endif | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/ip_mroute.h> | #include <netinet/ip_mroute.h> | ||||
#include <vm/uma.h> | |||||
#define RT_MAXFIBS UINT16_MAX | |||||
/* Kernel config default option. */ | |||||
#ifdef ROUTETABLES | |||||
#if ROUTETABLES <= 0 | |||||
#error "ROUTETABLES defined too low" | |||||
#endif | |||||
#if ROUTETABLES > RT_MAXFIBS | |||||
#error "ROUTETABLES defined too big" | |||||
#endif | |||||
#define RT_NUMFIBS ROUTETABLES | |||||
#endif /* ROUTETABLES */ | |||||
/* Initialize to default if not otherwise set. */ | |||||
#ifndef RT_NUMFIBS | |||||
#define RT_NUMFIBS 1 | |||||
#endif | |||||
/* This is read-only.. */ | |||||
u_int rt_numfibs = RT_NUMFIBS; | |||||
SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RDTUN, &rt_numfibs, 0, ""); | |||||
/* | /* | ||||
* By default add routes to all fibs for new interfaces. | * By default add routes to all fibs for new interfaces. | ||||
* Once this is set to 0 then only allocate routes on interface | * Once this is set to 0 then only allocate routes on interface | ||||
* changes for the FIB of the caller when adding a new set of addresses | * changes for the FIB of the caller when adding a new set of addresses | ||||
* to an interface. XXX this is a shotgun aproach to a problem that needs | * to an interface. XXX this is a shotgun aproach to a problem that needs | ||||
* a more fine grained solution.. that will come. | * a more fine grained solution.. that will come. | ||||
* XXX also has the problems getting the FIB from curthread which will not | * XXX also has the problems getting the FIB from curthread which will not | ||||
* always work given the fib can be overridden and prefixes can be added | * always work given the fib can be overridden and prefixes can be added | ||||
* from the network stack context. | * from the network stack context. | ||||
*/ | */ | ||||
VNET_DEFINE(u_int, rt_add_addr_allfibs) = 1; | VNET_DEFINE(u_int, rt_add_addr_allfibs) = 1; | ||||
SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET, | SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET, | ||||
&VNET_NAME(rt_add_addr_allfibs), 0, ""); | &VNET_NAME(rt_add_addr_allfibs), 0, ""); | ||||
VNET_PCPUSTAT_DEFINE(struct rtstat, rtstat); | VNET_PCPUSTAT_DEFINE(struct rtstat, rtstat); | ||||
VNET_PCPUSTAT_SYSINIT(rtstat); | VNET_PCPUSTAT_SYSINIT(rtstat); | ||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
VNET_PCPUSTAT_SYSUNINIT(rtstat); | VNET_PCPUSTAT_SYSUNINIT(rtstat); | ||||
#endif | #endif | ||||
VNET_DEFINE(struct rib_head *, rt_tables); | |||||
#define V_rt_tables VNET(rt_tables) | |||||
EVENTHANDLER_LIST_DEFINE(rt_addrmsg); | EVENTHANDLER_LIST_DEFINE(rt_addrmsg); | ||||
static int rt_ifdelroute(const struct rtentry *rt, const struct nhop_object *, | static int rt_ifdelroute(const struct rtentry *rt, const struct nhop_object *, | ||||
void *arg); | void *arg); | ||||
static int rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, | static int rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *info, | ||||
int flags); | int flags); | ||||
/* | /* | ||||
* handler for net.my_fibnum | |||||
*/ | |||||
static int | |||||
sysctl_my_fibnum(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
int fibnum; | |||||
int error; | |||||
fibnum = curthread->td_proc->p_fibnum; | |||||
error = sysctl_handle_int(oidp, &fibnum, 0, req); | |||||
return (error); | |||||
} | |||||
SYSCTL_PROC(_net, OID_AUTO, my_fibnum, | |||||
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, | |||||
&sysctl_my_fibnum, "I", | |||||
"default FIB of caller"); | |||||
static __inline struct rib_head ** | |||||
rt_tables_get_rnh_ptr(int table, int fam) | |||||
{ | |||||
struct rib_head **rnh; | |||||
KASSERT(table >= 0 && table < rt_numfibs, | |||||
("%s: table out of bounds (0 <= %d < %d)", __func__, table, | |||||
rt_numfibs)); | |||||
KASSERT(fam >= 0 && fam < (AF_MAX + 1), | |||||
("%s: fam out of bounds (0 <= %d < %d)", __func__, fam, AF_MAX+1)); | |||||
/* rnh is [fib=0][af=0]. */ | |||||
rnh = (struct rib_head **)V_rt_tables; | |||||
/* Get the offset to the requested table and fam. */ | |||||
rnh += table * (AF_MAX+1) + fam; | |||||
return (rnh); | |||||
} | |||||
struct rib_head * | |||||
rt_tables_get_rnh(int table, int fam) | |||||
{ | |||||
return (*rt_tables_get_rnh_ptr(table, fam)); | |||||
} | |||||
u_int | |||||
rt_tables_get_gen(int table, int fam) | |||||
{ | |||||
struct rib_head *rnh; | |||||
rnh = *rt_tables_get_rnh_ptr(table, fam); | |||||
KASSERT(rnh != NULL, ("%s: NULL rib_head pointer table %d fam %d", | |||||
__func__, table, fam)); | |||||
return (rnh->rnh_gen); | |||||
} | |||||
/* | |||||
* route initialization must occur before ip6_init2(), which happenas at | * route initialization must occur before ip6_init2(), which happenas at | ||||
* SI_ORDER_MIDDLE. | * SI_ORDER_MIDDLE. | ||||
*/ | */ | ||||
static void | static void | ||||
route_init(void) | route_init(void) | ||||
{ | { | ||||
/* whack the tunable ints into line. */ | |||||
if (rt_numfibs > RT_MAXFIBS) | |||||
rt_numfibs = RT_MAXFIBS; | |||||
if (rt_numfibs == 0) | |||||
rt_numfibs = 1; | |||||
nhops_init(); | nhops_init(); | ||||
} | } | ||||
SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, NULL); | SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, NULL); | ||||
static void | |||||
vnet_route_init(const void *unused __unused) | |||||
{ | |||||
struct domain *dom; | |||||
struct rib_head **rnh; | |||||
int table; | |||||
int fam; | |||||
V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) * | |||||
sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO); | |||||
vnet_rtzone_init(); | |||||
for (dom = domains; dom; dom = dom->dom_next) { | |||||
if (dom->dom_rtattach == NULL) | |||||
continue; | |||||
for (table = 0; table < rt_numfibs; table++) { | |||||
fam = dom->dom_family; | |||||
if (table != 0 && fam != AF_INET6 && fam != AF_INET) | |||||
break; | |||||
rnh = rt_tables_get_rnh_ptr(table, fam); | |||||
if (rnh == NULL) | |||||
panic("%s: rnh NULL", __func__); | |||||
*rnh = dom->dom_rtattach(table); | |||||
} | |||||
} | |||||
} | |||||
VNET_SYSINIT(vnet_route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, | |||||
vnet_route_init, 0); | |||||
#ifdef VIMAGE | |||||
static void | |||||
vnet_route_uninit(const void *unused __unused) | |||||
{ | |||||
int table; | |||||
int fam; | |||||
struct domain *dom; | |||||
struct rib_head **rnh; | |||||
for (dom = domains; dom; dom = dom->dom_next) { | |||||
if (dom->dom_rtdetach == NULL) | |||||
continue; | |||||
for (table = 0; table < rt_numfibs; table++) { | |||||
fam = dom->dom_family; | |||||
if (table != 0 && fam != AF_INET6 && fam != AF_INET) | |||||
break; | |||||
rnh = rt_tables_get_rnh_ptr(table, fam); | |||||
if (rnh == NULL) | |||||
panic("%s: rnh NULL", __func__); | |||||
dom->dom_rtdetach(*rnh); | |||||
} | |||||
} | |||||
/* | |||||
* dom_rtdetach calls rt_table_destroy(), which | |||||
* schedules deletion for all rtentries, nexthops and control | |||||
* structures. Wait for the destruction callbacks to fire. | |||||
* Note that this should result in freeing all rtentries, but | |||||
* nexthops deletions will be scheduled for the next epoch run | |||||
* and will be completed after vnet teardown. | |||||
*/ | |||||
epoch_drain_callbacks(net_epoch_preempt); | |||||
free(V_rt_tables, M_RTABLE); | |||||
vnet_rtzone_destroy(); | |||||
} | |||||
VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, | |||||
vnet_route_uninit, 0); | |||||
#endif | |||||
struct rib_head * | struct rib_head * | ||||
rt_table_init(int offset, int family, u_int fibnum) | rt_table_init(int offset, int family, u_int fibnum) | ||||
{ | { | ||||
struct rib_head *rh; | struct rib_head *rh; | ||||
rh = malloc(sizeof(struct rib_head), M_RTABLE, M_WAITOK | M_ZERO); | rh = malloc(sizeof(struct rib_head), M_RTABLE, M_WAITOK | M_ZERO); | ||||
/* TODO: These details should be hidded inside radix.c */ | /* TODO: These details should be hidded inside radix.c */ | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | rt_table_destroy(struct rib_head *rh) | ||||
nhops_destroy_rib(rh); | nhops_destroy_rib(rh); | ||||
rib_destroy_subscriptions(rh); | rib_destroy_subscriptions(rh); | ||||
/* Assume table is already empty */ | /* Assume table is already empty */ | ||||
RIB_LOCK_DESTROY(rh); | RIB_LOCK_DESTROY(rh); | ||||
free(rh, M_RTABLE); | free(rh, M_RTABLE); | ||||
} | |||||
#ifndef _SYS_SYSPROTO_H_ | |||||
struct setfib_args { | |||||
int fibnum; | |||||
}; | |||||
#endif | |||||
int | |||||
sys_setfib(struct thread *td, struct setfib_args *uap) | |||||
{ | |||||
if (uap->fibnum < 0 || uap->fibnum >= rt_numfibs) | |||||
return EINVAL; | |||||
td->td_proc->p_fibnum = uap->fibnum; | |||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* Adds a temporal redirect entry to the routing table. | * Adds a temporal redirect entry to the routing table. | ||||
* @fibnum: fib number | * @fibnum: fib number | ||||
* @dst: destination to install redirect to | * @dst: destination to install redirect to | ||||
* @gateway: gateway to go via | * @gateway: gateway to go via | ||||
* @author: sockaddr of originating router, can be NULL | * @author: sockaddr of originating router, can be NULL | ||||
▲ Show 20 Lines • Show All 987 Lines • Show Last 20 Lines |