Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/route/route_ctl.c
Show First 20 Lines • Show All 143 Lines • ▼ Show 20 Lines | |||||
* Schedule rtentry deletion | * Schedule rtentry deletion | ||||
*/ | */ | ||||
static void | static void | ||||
rtfree(struct rtentry *rt) | rtfree(struct rtentry *rt) | ||||
{ | { | ||||
KASSERT(rt != NULL, ("%s: NULL rt", __func__)); | KASSERT(rt != NULL, ("%s: NULL rt", __func__)); | ||||
RT_LOCK_ASSERT(rt); | |||||
RT_UNLOCK(rt); | |||||
epoch_call(net_epoch_preempt, destroy_rtentry_epoch, | epoch_call(net_epoch_preempt, destroy_rtentry_epoch, | ||||
&rt->rt_epoch_ctx); | &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) | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | add_route(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
} | } | ||||
rt = uma_zalloc(V_rtzone, M_NOWAIT | M_ZERO); | 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->rte_flags = RTF_UP | flags; | rt->rte_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 16 Lines | add_route(struct rib_head *rnh, struct rt_addrinfo *info, | ||||
*/ | */ | ||||
ifa = info->rti_ifa; | ifa = info->rti_ifa; | ||||
rt->rt_weight = 1; | rt->rt_weight = 1; | ||||
rt_setmetrics(info, rt); | rt_setmetrics(info, rt); | ||||
rt_old = NULL; | rt_old = NULL; | ||||
RIB_WLOCK(rnh); | RIB_WLOCK(rnh); | ||||
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) { | ||||
/* Most common usecase */ | /* Most common usecase */ | ||||
if (rt->rt_expire > 0) | if (rt->rt_expire > 0) | ||||
tmproutes_update(rnh, rt); | tmproutes_update(rnh, rt); | ||||
/* Finalize notification */ | /* Finalize notification */ | ||||
rnh->rnh_gen++; | rnh->rnh_gen++; | ||||
rc->rc_rt = RNTORT(rn); | rc->rc_rt = rt; | ||||
rc->rc_nh_new = nh; | rc->rc_nh_new = nh; | ||||
rc->rc_nh_weight = rt->rt_weight; | |||||
rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | ||||
} else if ((info->rti_flags & RTF_PINNED) != 0) { | } else if ((info->rti_flags & RTF_PINNED) != 0) { | ||||
/* | /* | ||||
* Force removal and re-try addition | * Force removal and re-try addition | ||||
* TODO: better multipath&pinned support | * TODO: better multipath&pinned support | ||||
*/ | */ | ||||
struct sockaddr *info_dst = info->rti_info[RTAX_DST]; | struct sockaddr *info_dst = info->rti_info[RTAX_DST]; | ||||
info->rti_info[RTAX_DST] = ndst; | info->rti_info[RTAX_DST] = ndst; | ||||
/* Do not delete existing PINNED(interface) routes */ | /* Do not delete existing PINNED(interface) routes */ | ||||
info->rti_flags &= ~RTF_PINNED; | info->rti_flags &= ~RTF_PINNED; | ||||
rt_old = rt_unlinkrte(rnh, info, &error); | rt_old = rt_unlinkrte(rnh, info, &error); | ||||
info->rti_flags |= RTF_PINNED; | info->rti_flags |= RTF_PINNED; | ||||
info->rti_info[RTAX_DST] = info_dst; | info->rti_info[RTAX_DST] = info_dst; | ||||
if (rt_old != NULL) { | if (rt_old != NULL) { | ||||
rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, | rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, | ||||
rt->rt_nodes); | rt->rt_nodes); | ||||
/* Finalize notification */ | /* Finalize notification */ | ||||
rnh->rnh_gen++; | rnh->rnh_gen++; | ||||
if (rn != NULL) { | if (rn != NULL) { | ||||
rc->rc_cmd = RTM_CHANGE; | rc->rc_cmd = RTM_CHANGE; | ||||
rc->rc_rt = RNTORT(rn); | rc->rc_rt = rt; | ||||
rc->rc_nh_old = rt_old->rt_nhop; | rc->rc_nh_old = rt_old->rt_nhop; | ||||
rc->rc_nh_new = nh; | rc->rc_nh_new = nh; | ||||
rc->rc_nh_weight = rt->rt_weight; | |||||
} else { | } else { | ||||
rc->rc_cmd = RTM_DELETE; | rc->rc_cmd = RTM_DELETE; | ||||
rc->rc_rt = RNTORT(rn); | rc->rc_rt = rt_old; | ||||
rc->rc_nh_old = rt_old->rt_nhop; | rc->rc_nh_old = rt_old->rt_nhop; | ||||
rc->rc_nh_new = nh; | rc->rc_nh_weight = rt_old->rt_weight; | ||||
} | } | ||||
rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | ||||
} | } | ||||
} | } | ||||
RIB_WUNLOCK(rnh); | RIB_WUNLOCK(rnh); | ||||
if ((rn != NULL) || (rt_old != NULL)) | if ((rn != NULL) || (rt_old != NULL)) | ||||
rib_notify(rnh, RIB_NOTIFY_DELAYED, rc); | rib_notify(rnh, RIB_NOTIFY_DELAYED, rc); | ||||
if (rt_old != NULL) | 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); | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Removes route defined by @info from the kernel table specified by @fibnum and | * Removes route defined by @info from the kernel table specified by @fibnum and | ||||
* sa_family in @info->rti_info[RTAX_DST]. | * sa_family in @info->rti_info[RTAX_DST]. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | #endif | ||||
rn = rnh->rnh_deladdr(dst, netmask, &rnh->head); | rn = rnh->rnh_deladdr(dst, netmask, &rnh->head); | ||||
if (rn == NULL) | if (rn == NULL) | ||||
return (NULL); | return (NULL); | ||||
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) | if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT)) | ||||
panic ("rtrequest delete"); | panic ("rtrequest delete"); | ||||
rt = RNTORT(rn); | rt = RNTORT(rn); | ||||
RT_LOCK(rt); | |||||
rt->rte_flags &= ~RTF_UP; | rt->rte_flags &= ~RTF_UP; | ||||
*perror = 0; | *perror = 0; | ||||
return (rt); | return (rt); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | #endif | ||||
if (rt->rt_nhop != nh_orig) { | if (rt->rt_nhop != nh_orig) { | ||||
RIB_WUNLOCK(rnh); | RIB_WUNLOCK(rnh); | ||||
nhop_free(nh); | nhop_free(nh); | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} | } | ||||
/* Proceed with the update */ | /* Proceed with the update */ | ||||
RT_LOCK(rt); | |||||
/* Provide notification to the protocols.*/ | /* Provide notification to the protocols.*/ | ||||
rt->rt_nhop = nh; | rt->rt_nhop = nh; | ||||
rt_setmetrics(info, rt); | rt_setmetrics(info, rt); | ||||
/* Finalize notification */ | /* Finalize notification */ | ||||
rnh->rnh_gen++; | |||||
rc->rc_rt = rt; | rc->rc_rt = rt; | ||||
rc->rc_nh_old = nh_orig; | rc->rc_nh_old = nh_orig; | ||||
rc->rc_nh_new = rt->rt_nhop; | rc->rc_nh_new = rt->rt_nhop; | ||||
rc->rc_nh_weight = rt->rt_weight; | |||||
RT_UNLOCK(rt); | |||||
/* Update generation id to reflect rtable change */ | |||||
rnh->rnh_gen++; | |||||
rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); | ||||
RIB_WUNLOCK(rnh); | RIB_WUNLOCK(rnh); | ||||
rib_notify(rnh, RIB_NOTIFY_DELAYED, rc); | rib_notify(rnh, RIB_NOTIFY_DELAYED, rc); | ||||
nhop_free(nh_orig); | nhop_free(nh_orig); | ||||
▲ Show 20 Lines • Show All 310 Lines • Show Last 20 Lines |