Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/route/route_ctl.c
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | static int del_route(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
struct rib_cmd_info *rc); | struct rib_cmd_info *rc); | ||||
static int change_route(struct rib_head *, struct rt_addrinfo *, | static int change_route(struct rib_head *, struct rt_addrinfo *, | ||||
struct rib_cmd_info *rc); | struct rib_cmd_info *rc); | ||||
static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type, | static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type, | ||||
struct rib_cmd_info *rc); | struct rib_cmd_info *rc); | ||||
static void destroy_subscription_epoch(epoch_context_t ctx); | static void destroy_subscription_epoch(epoch_context_t ctx); | ||||
/* Routing table UMA zone */ | |||||
VNET_DEFINE_STATIC(uma_zone_t, rtzone); | |||||
#define V_rtzone VNET(rtzone) | |||||
void | |||||
vnet_rtzone_init() | |||||
{ | |||||
V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), | |||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); | |||||
} | |||||
#ifdef VIMAGE | |||||
void | |||||
vnet_rtzone_destroy() | |||||
{ | |||||
uma_zdestroy(V_rtzone); | |||||
} | |||||
#endif | |||||
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); | |||||
} | |||||
/* | |||||
* Schedule rtentry deletion | |||||
*/ | |||||
static 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 struct rib_head * | static struct rib_head * | ||||
get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) | get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) | ||||
{ | { | ||||
struct rib_head *rnh; | struct rib_head *rnh; | ||||
struct sockaddr *dst; | struct sockaddr *dst; | ||||
KASSERT((fibnum < rt_numfibs), ("rib_add_route: bad fibnum")); | KASSERT((fibnum < rt_numfibs), ("rib_add_route: bad fibnum")); | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | add_route(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
} | } | ||||
error = nhop_create_from_info(rnh, info, &nh); | error = nhop_create_from_info(rnh, info, &nh); | ||||
if (error != 0) { | if (error != 0) { | ||||
ifa_free(info->rti_ifa); | ifa_free(info->rti_ifa); | ||||
return (error); | return (error); | ||||
} | } | ||||
rt = uma_zalloc(V_rtzone, M_NOWAIT); | rt = uma_zalloc(V_rtzone, M_NOWAIT | M_ZERO); | ||||
if (rt == NULL) { | if (rt == NULL) { | ||||
ifa_free(info->rti_ifa); | ifa_free(info->rti_ifa); | ||||
nhop_free(nh); | nhop_free(nh); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
RT_LOCK_INIT(rt); | |||||
rt->rt_flags = RTF_UP | flags; | rt->rt_flags = RTF_UP | flags; | ||||
rt->rt_nhop = nh; | rt->rt_nhop = nh; | ||||
/* Fill in dst */ | /* Fill in dst */ | ||||
memcpy(&rt->rt_dst, dst, dst->sa_len); | memcpy(&rt->rt_dst, dst, dst->sa_len); | ||||
rt_key(rt) = &rt->rt_dst; | rt_key(rt) = &rt->rt_dst; | ||||
/* | /* | ||||
Show All 24 Lines | add_route(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
RT_LOCK(rt); | RT_LOCK(rt); | ||||
#ifdef RADIX_MPATH | #ifdef RADIX_MPATH | ||||
/* do not permit exactly the same dst/mask/gw pair */ | /* do not permit exactly the same dst/mask/gw pair */ | ||||
if (rt_mpath_capable(rnh) && | if (rt_mpath_capable(rnh) && | ||||
rt_mpath_conflict(rnh, rt, netmask)) { | rt_mpath_conflict(rnh, rt, netmask)) { | ||||
RIB_WUNLOCK(rnh); | RIB_WUNLOCK(rnh); | ||||
nhop_free(nh); | nhop_free(nh); | ||||
RT_LOCK_DESTROY(rt); | |||||
uma_zfree(V_rtzone, rt); | uma_zfree(V_rtzone, rt); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
#endif | #endif | ||||
rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, rt->rt_nodes); | rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, rt->rt_nodes); | ||||
if (rn != NULL) { | if (rn != NULL) { | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | if (rt_old != NULL) | ||||
rtfree(rt_old); | rtfree(rt_old); | ||||
/* | /* | ||||
* If it still failed to go into the tree, | * If it still failed to go into the tree, | ||||
* then un-make it (this should be a function) | * then un-make it (this should be a function) | ||||
*/ | */ | ||||
if (rn == NULL) { | if (rn == NULL) { | ||||
nhop_free(nh); | nhop_free(nh); | ||||
RT_LOCK_DESTROY(rt); | |||||
uma_zfree(V_rtzone, rt); | uma_zfree(V_rtzone, rt); | ||||
return (EEXIST); | return (EEXIST); | ||||
} | } | ||||
RT_UNLOCK(rt); | RT_UNLOCK(rt); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 550 Lines • Show Last 20 Lines |