Revert "routing: install prefix and loopback routes using new nhop-based KPI."
Temporarily revert the commit to unblock testing.
This reverts commit a1b59379db
.
This commit is contained in:
parent
5d91386826
commit
7b3440fc30
@ -75,13 +75,9 @@ int rib_change_route(uint32_t fibnum, struct rt_addrinfo *info,
|
|||||||
struct rib_cmd_info *rc);
|
struct rib_cmd_info *rc);
|
||||||
int rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info,
|
int rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info,
|
||||||
struct rib_cmd_info *rc);
|
struct rib_cmd_info *rc);
|
||||||
int rib_add_kernel_px(uint32_t fibnum, struct sockaddr *dst, int plen,
|
|
||||||
struct route_nhop_data *rnd, int op_flags);
|
|
||||||
int rib_del_kernel_px(uint32_t fibnum, struct sockaddr *dst, int plen,
|
|
||||||
rib_filter_f_t *filter_func, void *filter_arg, int op_flags);
|
|
||||||
|
|
||||||
int rib_match_gw(const struct rtentry *rt, const struct nhop_object *nh,
|
int rib_match_gw(const struct rtentry *rt, const struct nhop_object *nh,
|
||||||
void *_data);
|
void *_data);
|
||||||
|
int rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info);
|
||||||
|
|
||||||
int rib_add_default_route(uint32_t fibnum, int family, struct ifnet *ifp,
|
int rib_add_default_route(uint32_t fibnum, int family, struct ifnet *ifp,
|
||||||
struct sockaddr *gw, struct rib_cmd_info *rc);
|
struct sockaddr *gw, struct rib_cmd_info *rc);
|
||||||
|
@ -64,103 +64,112 @@ VNET_DEFINE(u_int, rt_add_addr_allfibs) = 0;
|
|||||||
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, "");
|
||||||
|
|
||||||
static void
|
/*
|
||||||
report_operation(uint32_t fibnum, struct rib_cmd_info *rc)
|
* Executes routing tables change specified by @cmd and @info for the fib
|
||||||
|
* @fibnum. Generates routing message on success.
|
||||||
|
* Note: it assumes there is only single route (interface route) for the
|
||||||
|
* provided prefix.
|
||||||
|
* Returns 0 on success or errno.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rib_handle_ifaddr_one(uint32_t fibnum, int cmd, struct rt_addrinfo *info)
|
||||||
{
|
{
|
||||||
|
struct rib_cmd_info rc;
|
||||||
struct nhop_object *nh;
|
struct nhop_object *nh;
|
||||||
|
int error;
|
||||||
|
|
||||||
if (rc->rc_cmd == RTM_DELETE)
|
error = rib_action(fibnum, cmd, info, &rc);
|
||||||
nh = nhop_select(rc->rc_nh_old, 0);
|
if (error == 0) {
|
||||||
else
|
if (cmd == RTM_ADD)
|
||||||
nh = nhop_select(rc->rc_nh_new, 0);
|
nh = nhop_select(rc.rc_nh_new, 0);
|
||||||
rt_routemsg(rc->rc_cmd, rc->rc_rt, nh, fibnum);
|
else
|
||||||
}
|
nh = nhop_select(rc.rc_nh_old, 0);
|
||||||
|
rt_routemsg(cmd, rc.rc_rt, nh, fibnum);
|
||||||
int
|
|
||||||
rib_add_kernel_px(uint32_t fibnum, struct sockaddr *dst, int plen,
|
|
||||||
struct route_nhop_data *rnd, int op_flags)
|
|
||||||
{
|
|
||||||
struct rib_cmd_info rc = {};
|
|
||||||
|
|
||||||
NET_EPOCH_ASSERT();
|
|
||||||
|
|
||||||
int error = rib_add_route_px(fibnum, dst, plen, rnd, op_flags, &rc);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
report_operation(fibnum, &rc);
|
|
||||||
|
|
||||||
if (V_rt_add_addr_allfibs != 0) {
|
|
||||||
for (int i = 0; i < V_rt_numfibs; i++) {
|
|
||||||
if (i == fibnum)
|
|
||||||
continue;
|
|
||||||
struct rib_head *rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
|
|
||||||
/* Don't care much about the errors in non-primary fib */
|
|
||||||
if (rnh != NULL) {
|
|
||||||
if (rib_copy_route(rc.rc_rt, rnd, rnh, &rc) == 0)
|
|
||||||
report_operation(i, &rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds/deletes interface prefix specified by @info to the routing table.
|
||||||
|
* If V_rt_add_addr_allfibs is set, iterates over all existing routing
|
||||||
|
* tables, otherwise uses fib in @fibnum. Generates routing message for
|
||||||
|
* each table.
|
||||||
|
* Returns 0 on success or errno.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
rib_del_kernel_px(uint32_t fibnum, struct sockaddr *dst, int plen,
|
rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info)
|
||||||
rib_filter_f_t *filter_func, void *filter_arg, int op_flags)
|
|
||||||
{
|
{
|
||||||
struct rib_cmd_info rc = {};
|
int error = 0, last_error = 0;
|
||||||
|
bool didwork = false;
|
||||||
|
|
||||||
NET_EPOCH_ASSERT();
|
if (V_rt_add_addr_allfibs == 0) {
|
||||||
|
error = rib_handle_ifaddr_one(fibnum, cmd, info);
|
||||||
int error = rib_del_route_px(fibnum, dst, plen, filter_func, filter_arg,
|
didwork = (error == 0);
|
||||||
op_flags, &rc);
|
} else {
|
||||||
if (error != 0)
|
for (fibnum = 0; fibnum < V_rt_numfibs; fibnum++) {
|
||||||
return (error);
|
error = rib_handle_ifaddr_one(fibnum, cmd, info);
|
||||||
report_operation(fibnum, &rc);
|
if (error == 0)
|
||||||
|
didwork = true;
|
||||||
if (V_rt_add_addr_allfibs != 0) {
|
else
|
||||||
for (int i = 0; i < V_rt_numfibs; i++) {
|
last_error = error;
|
||||||
if (i == fibnum)
|
|
||||||
continue;
|
|
||||||
/* Don't care much about the errors in non-primary fib */
|
|
||||||
if (rib_del_route_px(fibnum, dst, plen, filter_func, filter_arg,
|
|
||||||
op_flags, &rc) == 0)
|
|
||||||
report_operation(i, &rc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd == RTM_DELETE) {
|
||||||
|
if (didwork) {
|
||||||
|
error = 0;
|
||||||
|
} else {
|
||||||
|
/* we only give an error if it wasn't in any table */
|
||||||
|
error = ((info->rti_flags & RTF_HOST) ?
|
||||||
|
EHOSTUNREACH : ENETUNREACH);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (last_error != 0) {
|
||||||
|
/* return an error if any of them failed */
|
||||||
|
error = last_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_loopback_route_flags(struct ifaddr *ifa, struct sockaddr *ia, int op_flags)
|
ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
|
||||||
|
struct sockaddr *ia)
|
||||||
{
|
{
|
||||||
struct rib_cmd_info rc;
|
struct rib_cmd_info rc;
|
||||||
|
struct epoch_tracker et;
|
||||||
int error;
|
int error;
|
||||||
|
struct rt_addrinfo info;
|
||||||
|
struct sockaddr_dl null_sdl;
|
||||||
|
struct ifnet *ifp;
|
||||||
|
|
||||||
NET_EPOCH_ASSERT();
|
ifp = ifa->ifa_ifp;
|
||||||
|
|
||||||
struct ifnet *ifp = ifa->ifa_ifp;
|
NET_EPOCH_ENTER(et);
|
||||||
struct nhop_object *nh = nhop_alloc(ifp->if_fib, ia->sa_family);
|
bzero(&info, sizeof(info));
|
||||||
struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
|
if (cmd != RTM_DELETE)
|
||||||
if (nh == NULL)
|
info.rti_ifp = V_loif;
|
||||||
return (ENOMEM);
|
if (cmd == RTM_ADD) {
|
||||||
|
/* explicitly specify (loopback) ifa */
|
||||||
|
if (info.rti_ifp != NULL)
|
||||||
|
info.rti_ifa = ifaof_ifpforaddr(ifa->ifa_addr, info.rti_ifp);
|
||||||
|
}
|
||||||
|
info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC | RTF_PINNED;
|
||||||
|
info.rti_info[RTAX_DST] = ia;
|
||||||
|
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl;
|
||||||
|
link_init_sdl(ifp, (struct sockaddr *)&null_sdl, ifp->if_type);
|
||||||
|
|
||||||
nhop_set_direct_gw(nh, ifp);
|
error = rib_action(ifp->if_fib, cmd, &info, &rc);
|
||||||
nhop_set_transmit_ifp(nh, V_loif);
|
NET_EPOCH_EXIT(et);
|
||||||
nhop_set_src(nh, ifaof_ifpforaddr(ifa->ifa_addr, ifp));
|
|
||||||
nhop_set_pinned(nh, true);
|
if (error == 0 ||
|
||||||
nhop_set_rtflags(nh, RTF_STATIC);
|
(cmd == RTM_ADD && error == EEXIST) ||
|
||||||
nhop_set_pxtype_flag(nh, NHF_HOST);
|
(cmd == RTM_DELETE && (error == ENOENT || error == ESRCH)))
|
||||||
rnd.rnd_nhop = nhop_get_nhop(nh, &error);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
return (error);
|
||||||
error = rib_add_route_px(ifp->if_fib, ia, -1, &rnd, op_flags, &rc);
|
|
||||||
|
|
||||||
if (error != 0)
|
log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n",
|
||||||
log(LOG_DEBUG, "%s: failed to update interface %s route: %u\n",
|
__func__, otype, if_name(ifp), error);
|
||||||
__func__, if_name(ifp), error);
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -168,49 +177,22 @@ add_loopback_route_flags(struct ifaddr *ifa, struct sockaddr *ia, int op_flags)
|
|||||||
int
|
int
|
||||||
ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
||||||
{
|
{
|
||||||
struct epoch_tracker et;
|
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
return (ifa_maintain_loopback_route(RTM_ADD, "insertion", ifa, ia));
|
||||||
int error = add_loopback_route_flags(ifa, ia, RTM_F_CREATE | RTM_F_FORCE);
|
|
||||||
NET_EPOCH_EXIT(et);
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
|
||||||
{
|
|
||||||
struct epoch_tracker et;
|
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
|
||||||
int error = add_loopback_route_flags(ifa, ia, RTM_F_REPLACE | RTM_F_FORCE);
|
|
||||||
NET_EPOCH_EXIT(et);
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
||||||
{
|
{
|
||||||
struct ifnet *ifp = ifa->ifa_ifp;
|
|
||||||
struct sockaddr_dl link_sdl;
|
|
||||||
struct sockaddr *gw = (struct sockaddr *)&link_sdl;
|
|
||||||
struct rib_cmd_info rc;
|
|
||||||
struct epoch_tracker et;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
return (ifa_maintain_loopback_route(RTM_DELETE, "deletion", ifa, ia));
|
||||||
|
}
|
||||||
|
|
||||||
link_init_sdl(ifp, gw, ifp->if_type);
|
int
|
||||||
error = rib_del_route_px_gw(ifp->if_fib, ia, -1, gw, RTM_F_FORCE, &rc);
|
ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
|
||||||
|
{
|
||||||
|
|
||||||
NET_EPOCH_EXIT(et);
|
return (ifa_maintain_loopback_route(RTM_CHANGE, "switch", ifa, ia));
|
||||||
|
|
||||||
if (error != 0)
|
|
||||||
log(LOG_DEBUG, "%s: failed to delete interface %s route: %u\n",
|
|
||||||
__func__, if_name(ifp), error);
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -821,34 +821,36 @@ in_match_ifaddr(const struct rtentry *rt, const struct nhop_object *nh, void *ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
in_handle_prefix_route(uint32_t fibnum, int cmd, struct sockaddr *dst,
|
in_handle_prefix_route(uint32_t fibnum, int cmd,
|
||||||
int plen, struct ifaddr *ifa, struct ifnet *ifp)
|
struct sockaddr_in *dst, struct sockaddr_in *netmask, struct ifaddr *ifa,
|
||||||
|
struct ifnet *ifp)
|
||||||
{
|
{
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
NET_EPOCH_ASSERT();
|
NET_EPOCH_ASSERT();
|
||||||
|
|
||||||
if (cmd == RTM_DELETE) {
|
/* Prepare gateway */
|
||||||
error = rib_del_kernel_px(fibnum, dst, plen, in_match_ifaddr, ifa,
|
struct sockaddr_dl_short sdl = {
|
||||||
RTM_F_FORCE);
|
.sdl_family = AF_LINK,
|
||||||
} else {
|
.sdl_len = sizeof(struct sockaddr_dl_short),
|
||||||
struct nhop_object *nh = nhop_alloc(fibnum, dst->sa_family);
|
.sdl_type = ifa->ifa_ifp->if_type,
|
||||||
struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
|
.sdl_index = ifa->ifa_ifp->if_index,
|
||||||
|
};
|
||||||
|
|
||||||
if (nh == NULL)
|
struct rt_addrinfo info = {
|
||||||
return (ENOMEM);
|
.rti_ifa = ifa,
|
||||||
nhop_set_direct_gw(nh, ifa->ifa_ifp);
|
.rti_ifp = ifp,
|
||||||
nhop_set_transmit_ifp(nh, ifp);
|
.rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST),
|
||||||
nhop_set_src(nh, ifa);
|
.rti_info = {
|
||||||
nhop_set_pinned(nh, true);
|
[RTAX_DST] = (struct sockaddr *)dst,
|
||||||
nhop_set_pxtype_flag(nh, plen == 32 ? NHF_HOST : 0);
|
[RTAX_NETMASK] = (struct sockaddr *)netmask,
|
||||||
rnd.rnd_nhop = nhop_get_nhop(nh, &error);
|
[RTAX_GATEWAY] = (struct sockaddr *)&sdl,
|
||||||
if (error != 0)
|
},
|
||||||
return (error);
|
/* Ensure we delete the prefix IFF prefix ifa matches */
|
||||||
int op_flags = RTM_F_CREATE | RTM_F_REPLACE | RTM_F_FORCE;
|
.rti_filter = in_match_ifaddr,
|
||||||
error = rib_add_kernel_px(fibnum, dst, plen, &rnd, op_flags);
|
.rti_filterdata = ifa,
|
||||||
}
|
};
|
||||||
return (error);
|
|
||||||
|
return (rib_handle_ifaddr_info(fibnum, cmd, &info));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -957,12 +959,19 @@ in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia)
|
|||||||
{
|
{
|
||||||
struct ifaddr *ifa = &ia->ia_ifa;
|
struct ifaddr *ifa = &ia->ia_ifa;
|
||||||
struct in_addr daddr, maddr;
|
struct in_addr daddr, maddr;
|
||||||
|
struct sockaddr_in *pmask;
|
||||||
struct epoch_tracker et;
|
struct epoch_tracker et;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
ia_getrtprefix(ia, &daddr, &maddr);
|
ia_getrtprefix(ia, &daddr, &maddr);
|
||||||
|
|
||||||
int plen = bitcount32(maddr.s_addr);
|
struct sockaddr_in mask = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_len = sizeof(struct sockaddr_in),
|
||||||
|
.sin_addr = maddr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pmask = (maddr.s_addr != INADDR_BROADCAST) ? &mask : NULL;
|
||||||
|
|
||||||
struct sockaddr_in dst = {
|
struct sockaddr_in dst = {
|
||||||
.sin_family = AF_INET,
|
.sin_family = AF_INET,
|
||||||
@ -980,8 +989,7 @@ in_handle_ifaddr_route(int cmd, struct in_ifaddr *ia)
|
|||||||
|
|
||||||
uint32_t fibnum = ifa->ifa_ifp->if_fib;
|
uint32_t fibnum = ifa->ifa_ifp->if_fib;
|
||||||
NET_EPOCH_ENTER(et);
|
NET_EPOCH_ENTER(et);
|
||||||
error = in_handle_prefix_route(fibnum, cmd, (struct sockaddr *)&dst,
|
error = in_handle_prefix_route(fibnum, cmd, &dst, pmask, ifa, ifp);
|
||||||
plen, ifa, ifp);
|
|
||||||
NET_EPOCH_EXIT(et);
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -1267,29 +1267,6 @@ in6_broadcast_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
in6_handle_dstaddr_rtadd(uint32_t fibnum, struct sockaddr *dst, struct ifaddr *ifa)
|
|
||||||
{
|
|
||||||
struct nhop_object *nh = nhop_alloc(fibnum, dst->sa_family);
|
|
||||||
struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (nh == NULL)
|
|
||||||
return (ENOMEM);
|
|
||||||
nhop_set_direct_gw(nh, ifa->ifa_ifp);
|
|
||||||
nhop_set_transmit_ifp(nh, ifa->ifa_ifp);
|
|
||||||
nhop_set_src(nh, ifa);
|
|
||||||
nhop_set_pinned(nh, true);
|
|
||||||
nhop_set_pxtype_flag(nh, NHF_HOST);
|
|
||||||
rnd.rnd_nhop = nhop_get_nhop(nh, &error);
|
|
||||||
if (error == 0) {
|
|
||||||
int op_flags = RTM_F_CREATE | RTM_F_REPLACE | RTM_F_FORCE;
|
|
||||||
error = rib_add_kernel_px(fibnum, dst, -1, &rnd, op_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds or deletes interface route for p2p ifa.
|
* Adds or deletes interface route for p2p ifa.
|
||||||
* Returns 0 on success or errno.
|
* Returns 0 on success or errno.
|
||||||
@ -1299,26 +1276,35 @@ in6_handle_dstaddr_rtrequest(int cmd, struct in6_ifaddr *ia)
|
|||||||
{
|
{
|
||||||
struct epoch_tracker et;
|
struct epoch_tracker et;
|
||||||
struct ifaddr *ifa = &ia->ia_ifa;
|
struct ifaddr *ifa = &ia->ia_ifa;
|
||||||
uint32_t fibnum = ifa->ifa_ifp->if_fib;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
/* Prepare gateway */
|
||||||
|
struct sockaddr_dl_short sdl = {
|
||||||
|
.sdl_family = AF_LINK,
|
||||||
|
.sdl_len = sizeof(struct sockaddr_dl_short),
|
||||||
|
.sdl_type = ifa->ifa_ifp->if_type,
|
||||||
|
.sdl_index = ifa->ifa_ifp->if_index,
|
||||||
|
};
|
||||||
|
|
||||||
struct sockaddr_in6 dst = {
|
struct sockaddr_in6 dst = {
|
||||||
.sin6_family = AF_INET6,
|
.sin6_family = AF_INET6,
|
||||||
.sin6_len = sizeof(struct sockaddr_in6),
|
.sin6_len = sizeof(struct sockaddr_in6),
|
||||||
.sin6_addr = ia->ia_dstaddr.sin6_addr,
|
.sin6_addr = ia->ia_dstaddr.sin6_addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
struct rt_addrinfo info = {
|
||||||
if (cmd == RTM_DELETE) {
|
.rti_ifa = ifa,
|
||||||
struct sockaddr_dl link_sdl;
|
.rti_ifp = ifa->ifa_ifp,
|
||||||
struct sockaddr *gw = (struct sockaddr *)&link_sdl;
|
.rti_flags = RTF_PINNED | RTF_HOST,
|
||||||
struct ifnet *ifp = ifa->ifa_ifp;
|
.rti_info = {
|
||||||
|
[RTAX_DST] = (struct sockaddr *)&dst,
|
||||||
|
[RTAX_GATEWAY] = (struct sockaddr *)&sdl,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* Don't set additional per-gw filters on removal */
|
||||||
|
|
||||||
link_init_sdl(ifp, gw, ifp->if_type);
|
NET_EPOCH_ENTER(et);
|
||||||
error = rib_del_kernel_px(fibnum, (struct sockaddr *)&dst, 128,
|
error = rib_handle_ifaddr_info(ifa->ifa_ifp->if_fib, cmd, &info);
|
||||||
rib_match_gw, gw, RTM_F_FORCE);
|
|
||||||
} else
|
|
||||||
error = in6_handle_dstaddr_rtadd(fibnum, (struct sockaddr *)&dst, ifa);
|
|
||||||
NET_EPOCH_EXIT(et);
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -1999,55 +1999,41 @@ pfxlist_onlink_check(void)
|
|||||||
ND6_ONLINK_UNLOCK();
|
ND6_ONLINK_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
nd6_prefix_rtadd(uint32_t fibnum, struct sockaddr *dst, int plen,
|
|
||||||
struct ifnet *ifp, struct ifaddr *ifa)
|
|
||||||
{
|
|
||||||
struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
struct nhop_object *nh = nhop_alloc(fibnum, dst->sa_family);
|
|
||||||
if (nh == NULL)
|
|
||||||
return (ENOMEM);
|
|
||||||
nhop_set_direct_gw(nh, ifp);
|
|
||||||
nhop_set_transmit_ifp(nh, ifp);
|
|
||||||
nhop_set_src(nh, ifa);
|
|
||||||
nhop_set_pinned(nh, true);
|
|
||||||
nhop_set_pxtype_flag(nh, plen == 128 ? NHF_HOST : 0);
|
|
||||||
rnd.rnd_nhop = nhop_get_nhop(nh, &error);
|
|
||||||
if (error == 0) {
|
|
||||||
int op_flags = RTM_F_CREATE | RTM_F_REPLACE | RTM_F_FORCE;
|
|
||||||
error = rib_add_kernel_px(fibnum, dst, plen, &rnd, op_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add or remove interface route specified by @dst, @netmask and @ifp.
|
* Add or remove interface route specified by @dst, @netmask and @ifp.
|
||||||
* ifa can be NULL.
|
* ifa can be NULL.
|
||||||
* Returns 0 on success
|
* Returns 0 on success
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nd6_prefix_rtrequest(uint32_t fibnum, int cmd, struct sockaddr *dst,
|
nd6_prefix_rtrequest(uint32_t fibnum, int cmd, struct sockaddr_in6 *dst,
|
||||||
int plen, struct ifnet *ifp, struct ifaddr *ifa)
|
struct sockaddr_in6 *netmask, struct ifnet *ifp, struct ifaddr *ifa)
|
||||||
{
|
{
|
||||||
struct epoch_tracker et;
|
struct epoch_tracker et;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
/* Prepare gateway */
|
||||||
|
struct sockaddr_dl_short sdl = {
|
||||||
|
.sdl_family = AF_LINK,
|
||||||
|
.sdl_len = sizeof(struct sockaddr_dl_short),
|
||||||
|
.sdl_type = ifp->if_type,
|
||||||
|
.sdl_index = ifp->if_index,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt_addrinfo info = {
|
||||||
|
.rti_ifa = ifa,
|
||||||
|
.rti_ifp = ifp,
|
||||||
|
.rti_flags = RTF_PINNED | ((netmask != NULL) ? 0 : RTF_HOST),
|
||||||
|
.rti_info = {
|
||||||
|
[RTAX_DST] = (struct sockaddr *)dst,
|
||||||
|
[RTAX_NETMASK] = (struct sockaddr *)netmask,
|
||||||
|
[RTAX_GATEWAY] = (struct sockaddr *)&sdl,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/* Don't set additional per-gw filters on removal */
|
||||||
|
|
||||||
NET_EPOCH_ENTER(et);
|
NET_EPOCH_ENTER(et);
|
||||||
if (cmd == RTM_DELETE) {
|
error = rib_handle_ifaddr_info(fibnum, cmd, &info);
|
||||||
struct sockaddr_dl link_sdl;
|
|
||||||
struct sockaddr *gw = (struct sockaddr *)&link_sdl;
|
|
||||||
|
|
||||||
link_init_sdl(ifp, gw, ifp->if_type);
|
|
||||||
error = rib_del_kernel_px(fibnum, dst, plen,
|
|
||||||
rib_match_gw, gw, RTM_F_FORCE);
|
|
||||||
} else
|
|
||||||
error = nd6_prefix_rtadd(fibnum, dst, plen, ifp, ifa);
|
|
||||||
|
|
||||||
NET_EPOCH_EXIT(et);
|
NET_EPOCH_EXIT(et);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2056,8 +2042,15 @@ nd6_prefix_onlink_rtrequest(struct nd_prefix *pr, struct ifaddr *ifa)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
struct sockaddr_in6 mask6 = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
.sin6_len = sizeof(struct sockaddr_in6),
|
||||||
|
.sin6_addr = pr->ndpr_mask,
|
||||||
|
};
|
||||||
|
struct sockaddr_in6 *pmask6 = (pr->ndpr_plen != 128) ? &mask6 : NULL;
|
||||||
|
|
||||||
error = nd6_prefix_rtrequest(pr->ndpr_ifp->if_fib, RTM_ADD,
|
error = nd6_prefix_rtrequest(pr->ndpr_ifp->if_fib, RTM_ADD,
|
||||||
(struct sockaddr *)&pr->ndpr_prefix, pr->ndpr_plen, pr->ndpr_ifp, ifa);
|
&pr->ndpr_prefix, pmask6, pr->ndpr_ifp, ifa);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
pr->ndpr_stateflags |= NDPRF_ONLINK;
|
pr->ndpr_stateflags |= NDPRF_ONLINK;
|
||||||
|
|
||||||
@ -2168,9 +2161,10 @@ nd6_prefix_offlink(struct nd_prefix *pr)
|
|||||||
.sin6_len = sizeof(struct sockaddr_in6),
|
.sin6_len = sizeof(struct sockaddr_in6),
|
||||||
.sin6_addr = pr->ndpr_mask,
|
.sin6_addr = pr->ndpr_mask,
|
||||||
};
|
};
|
||||||
|
struct sockaddr_in6 *pmask6 = (pr->ndpr_plen != 128) ? &mask6 : NULL;
|
||||||
|
|
||||||
error = nd6_prefix_rtrequest(ifp->if_fib, RTM_DELETE,
|
error = nd6_prefix_rtrequest(ifp->if_fib, RTM_DELETE,
|
||||||
(struct sockaddr *)&pr->ndpr_prefix, pr->ndpr_plen, ifp, NULL);
|
&pr->ndpr_prefix, pmask6, ifp, NULL);
|
||||||
|
|
||||||
a_failure = 1;
|
a_failure = 1;
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user