Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/route.c
Show First 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | |||||
#ifdef VIMAGE | #ifdef VIMAGE | ||||
VNET_PCPUSTAT_SYSUNINIT(rtstat); | VNET_PCPUSTAT_SYSUNINIT(rtstat); | ||||
#endif | #endif | ||||
VNET_DEFINE(struct rib_head *, rt_tables); | VNET_DEFINE(struct rib_head *, rt_tables); | ||||
#define V_rt_tables VNET(rt_tables) | #define V_rt_tables VNET(rt_tables) | ||||
VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ | |||||
#define V_rtzone VNET(rtzone) | |||||
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 void destroy_rtentry_epoch(epoch_context_t ctx); | |||||
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 | * handler for net.my_fibnum | ||||
*/ | */ | ||||
static int | static int | ||||
sysctl_my_fibnum(SYSCTL_HANDLER_ARGS) | sysctl_my_fibnum(SYSCTL_HANDLER_ARGS) | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | route_init(void) | ||||
if (rt_numfibs > RT_MAXFIBS) | if (rt_numfibs > RT_MAXFIBS) | ||||
rt_numfibs = RT_MAXFIBS; | rt_numfibs = RT_MAXFIBS; | ||||
if (rt_numfibs == 0) | if (rt_numfibs == 0) | ||||
rt_numfibs = 1; | 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 int | |||||
rtentry_zinit(void *mem, int size, int how) | |||||
{ | |||||
struct rtentry *rt = mem; | |||||
RT_LOCK_INIT(rt); | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
rtentry_zfini(void *mem, int size) | |||||
{ | |||||
struct rtentry *rt = mem; | |||||
RT_LOCK_DESTROY(rt); | |||||
} | |||||
static int | |||||
rtentry_ctor(void *mem, int size, void *arg, int how) | |||||
{ | |||||
struct rtentry *rt = mem; | |||||
bzero(rt, offsetof(struct rtentry, rt_endzero)); | |||||
rt->rt_chain = NULL; | |||||
return (0); | |||||
} | |||||
static void | |||||
rtentry_dtor(void *mem, int size, void *arg) | |||||
{ | |||||
struct rtentry *rt = mem; | |||||
RT_UNLOCK_COND(rt); | |||||
} | |||||
static void | |||||
vnet_route_init(const void *unused __unused) | vnet_route_init(const void *unused __unused) | ||||
{ | { | ||||
struct domain *dom; | struct domain *dom; | ||||
struct rib_head **rnh; | struct rib_head **rnh; | ||||
int table; | int table; | ||||
int fam; | int fam; | ||||
V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) * | V_rt_tables = malloc(rt_numfibs * (AF_MAX+1) * | ||||
sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO); | sizeof(struct rib_head *), M_RTABLE, M_WAITOK|M_ZERO); | ||||
V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), | vnet_rtzone_init(); | ||||
rtentry_ctor, rtentry_dtor, | |||||
rtentry_zinit, rtentry_zfini, UMA_ALIGN_PTR, 0); | |||||
for (dom = domains; dom; dom = dom->dom_next) { | for (dom = domains; dom; dom = dom->dom_next) { | ||||
if (dom->dom_rtattach == NULL) | if (dom->dom_rtattach == NULL) | ||||
continue; | continue; | ||||
for (table = 0; table < rt_numfibs; table++) { | for (table = 0; table < rt_numfibs; table++) { | ||||
fam = dom->dom_family; | fam = dom->dom_family; | ||||
if (table != 0 && fam != AF_INET6 && fam != AF_INET) | if (table != 0 && fam != AF_INET6 && fam != AF_INET) | ||||
break; | break; | ||||
Show All 40 Lines | vnet_route_uninit(const void *unused __unused) | ||||
* structures. Wait for the destruction callbacks to fire. | * structures. Wait for the destruction callbacks to fire. | ||||
* Note that this should result in freeing all rtentries, but | * Note that this should result in freeing all rtentries, but | ||||
* nexthops deletions will be scheduled for the next epoch run | * nexthops deletions will be scheduled for the next epoch run | ||||
* and will be completed after vnet teardown. | * and will be completed after vnet teardown. | ||||
*/ | */ | ||||
epoch_drain_callbacks(net_epoch_preempt); | epoch_drain_callbacks(net_epoch_preempt); | ||||
free(V_rt_tables, M_RTABLE); | free(V_rt_tables, M_RTABLE); | ||||
uma_zdestroy(V_rtzone); | vnet_rtzone_destroy(); | ||||
} | } | ||||
VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, | VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, | ||||
vnet_route_uninit, 0); | vnet_route_uninit, 0); | ||||
#endif | #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) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
int | int | ||||
sys_setfib(struct thread *td, struct setfib_args *uap) | sys_setfib(struct thread *td, struct setfib_args *uap) | ||||
{ | { | ||||
if (uap->fibnum < 0 || uap->fibnum >= rt_numfibs) | if (uap->fibnum < 0 || uap->fibnum >= rt_numfibs) | ||||
return EINVAL; | return EINVAL; | ||||
td->td_proc->p_fibnum = uap->fibnum; | td->td_proc->p_fibnum = uap->fibnum; | ||||
return (0); | return (0); | ||||
} | |||||
/* | |||||
* Remove a reference count from an rtentry. | |||||
* If the count gets low enough, take it out of the routing table | |||||
*/ | |||||
void | |||||
rtfree(struct rtentry *rt) | |||||
{ | |||||
KASSERT(rt != NULL,("%s: NULL rt", __func__)); | |||||
RT_LOCK_ASSERT(rt); | |||||
RT_UNLOCK(rt); | |||||
epoch_call(net_epoch_preempt, destroy_rtentry_epoch, | |||||
&rt->rt_epoch_ctx); | |||||
} | |||||
static void | |||||
destroy_rtentry(struct rtentry *rt) | |||||
{ | |||||
/* | |||||
* At this moment rnh, nh_control may be already freed. | |||||
* nhop interface may have been migrated to a different vnet. | |||||
* Use vnet stored in the nexthop to delete the entry. | |||||
*/ | |||||
CURVNET_SET(nhop_get_vnet(rt->rt_nhop)); | |||||
/* Unreference nexthop */ | |||||
nhop_free(rt->rt_nhop); | |||||
uma_zfree(V_rtzone, rt); | |||||
CURVNET_RESTORE(); | |||||
} | |||||
/* | |||||
* Epoch callback indicating rtentry is safe to destroy | |||||
*/ | |||||
static void | |||||
destroy_rtentry_epoch(epoch_context_t ctx) | |||||
{ | |||||
struct rtentry *rt; | |||||
rt = __containerof(ctx, struct rtentry, rt_epoch_ctx); | |||||
destroy_rtentry(rt); | |||||
} | } | ||||
/* | /* | ||||
* 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 |