Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163281553
D36166.id109945.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D36166.id109945.diff
View Options
diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h
--- a/sys/net/route/route_ctl.h
+++ b/sys/net/route/route_ctl.h
@@ -75,7 +75,13 @@
struct rib_cmd_info *rc);
int rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info,
struct rib_cmd_info *rc);
-int rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info);
+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,
+ void *_data);
int rib_match_gw(const struct rtentry *rt, const struct nhop_object *nh,
void *gw_sa);
diff --git a/sys/net/route/route_ifaddrs.c b/sys/net/route/route_ifaddrs.c
--- a/sys/net/route/route_ifaddrs.c
+++ b/sys/net/route/route_ifaddrs.c
@@ -64,112 +64,103 @@
SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET,
&VNET_NAME(rt_add_addr_allfibs), 0, "");
-/*
- * 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)
+static void
+report_operation(uint32_t fibnum, struct rib_cmd_info *rc)
{
- struct rib_cmd_info rc;
struct nhop_object *nh;
- int error;
- error = rib_action(fibnum, cmd, info, &rc);
- if (error == 0) {
- if (cmd == RTM_ADD)
- nh = nhop_select(rc.rc_nh_new, 0);
- else
- nh = nhop_select(rc.rc_nh_old, 0);
- rt_routemsg(cmd, rc.rc_rt, nh, fibnum);
+ if (rc->rc_cmd == RTM_DELETE)
+ nh = nhop_select(rc->rc_nh_old, 0);
+ else
+ nh = nhop_select(rc->rc_nh_new, 0);
+ rt_routemsg(rc->rc_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);
}
-/*
- * 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
-rib_handle_ifaddr_info(uint32_t fibnum, int cmd, struct rt_addrinfo *info)
+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 error = 0, last_error = 0;
- bool didwork = false;
-
- if (V_rt_add_addr_allfibs == 0) {
- error = rib_handle_ifaddr_one(fibnum, cmd, info);
- didwork = (error == 0);
- } else {
- for (fibnum = 0; fibnum < V_rt_numfibs; fibnum++) {
- error = rib_handle_ifaddr_one(fibnum, cmd, info);
- if (error == 0)
- didwork = true;
- else
- last_error = error;
- }
- }
+ struct rib_cmd_info 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;
+ NET_EPOCH_ASSERT();
+
+ int error = rib_del_route_px(fibnum, dst, plen, filter_func, filter_arg,
+ 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;
+ /* 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);
}
}
+
return (error);
}
static int
-ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
- struct sockaddr *ia)
+add_loopback_route_flags(struct ifaddr *ifa, struct sockaddr *ia, int op_flags)
{
struct rib_cmd_info rc;
- struct epoch_tracker et;
int error;
- struct rt_addrinfo info;
- struct sockaddr_dl null_sdl;
- struct ifnet *ifp;
-
- ifp = ifa->ifa_ifp;
- NET_EPOCH_ENTER(et);
- bzero(&info, sizeof(info));
- if (cmd != RTM_DELETE)
- info.rti_ifp = V_loif;
- 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);
+ NET_EPOCH_ASSERT();
- error = rib_action(ifp->if_fib, cmd, &info, &rc);
- NET_EPOCH_EXIT(et);
+ struct ifnet *ifp = ifa->ifa_ifp;
+ struct nhop_object *nh = nhop_alloc(ifp->if_fib, ia->sa_family);
+ struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
+ if (nh == NULL)
+ return (ENOMEM);
- if (error == 0 ||
- (cmd == RTM_ADD && error == EEXIST) ||
- (cmd == RTM_DELETE && (error == ENOENT || error == ESRCH)))
+ nhop_set_direct_gw(nh, ifp);
+ nhop_set_transmit_ifp(nh, V_loif);
+ nhop_set_src(nh, ifaof_ifpforaddr(ifa->ifa_addr, ifp));
+ nhop_set_pinned(nh, true);
+ nhop_set_rtflags(nh, RTF_STATIC);
+ nhop_set_pxtype_flag(nh, NHF_HOST);
+ rnd.rnd_nhop = nhop_get_nhop(nh, &error);
+ if (error != 0)
return (error);
+ error = rib_add_route_px(ifp->if_fib, ia, -1, &rnd, op_flags, &rc);
- log(LOG_DEBUG, "%s: %s failed for interface %s: %u\n",
- __func__, otype, if_name(ifp), error);
+ if (error != 0)
+ log(LOG_DEBUG, "%s: failed to update interface %s route: %u\n",
+ __func__, if_name(ifp), error);
return (error);
}
@@ -177,22 +168,49 @@
int
ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
{
+ struct epoch_tracker et;
- return (ifa_maintain_loopback_route(RTM_ADD, "insertion", ifa, ia));
+ NET_EPOCH_ENTER(et);
+ int error = add_loopback_route_flags(ifa, ia, RTM_F_CREATE | RTM_F_FORCE);
+ NET_EPOCH_EXIT(et);
+
+ return (error);
}
int
-ifa_del_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
+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 (ifa_maintain_loopback_route(RTM_DELETE, "deletion", ifa, ia));
+ return (error);
}
int
-ifa_switch_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;
- return (ifa_maintain_loopback_route(RTM_CHANGE, "switch", ifa, ia));
+ NET_EPOCH_ENTER(et);
+
+ link_init_sdl(ifp, gw, ifp->if_type);
+ error = rib_del_route_px_gw(ifp->if_fib, ia, -1, gw, RTM_F_FORCE, &rc);
+
+ NET_EPOCH_EXIT(et);
+
+ if (error != 0)
+ log(LOG_DEBUG, "%s: failed to delete interface %s route: %u\n",
+ __func__, if_name(ifp), error);
+
+ return (error);
}
static bool
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -821,36 +821,34 @@
}
static int
-in_handle_prefix_route(uint32_t fibnum, int cmd,
- struct sockaddr_in *dst, struct sockaddr_in *netmask, struct ifaddr *ifa,
- struct ifnet *ifp)
+in_handle_prefix_route(uint32_t fibnum, int cmd, struct sockaddr *dst,
+ int plen, struct ifaddr *ifa, struct ifnet *ifp)
{
+ int error = 0;
NET_EPOCH_ASSERT();
- /* 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 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,
- },
- /* Ensure we delete the prefix IFF prefix ifa matches */
- .rti_filter = in_match_ifaddr,
- .rti_filterdata = ifa,
- };
-
- return (rib_handle_ifaddr_info(fibnum, cmd, &info));
+ if (cmd == RTM_DELETE) {
+ error = rib_del_kernel_px(fibnum, dst, plen, in_match_ifaddr, ifa,
+ RTM_F_FORCE);
+ } else {
+ struct nhop_object *nh = nhop_alloc(fibnum, dst->sa_family);
+ struct route_nhop_data rnd = { .rnd_weight = RT_DEFAULT_WEIGHT };
+
+ if (nh == NULL)
+ return (ENOMEM);
+ nhop_set_direct_gw(nh, ifa->ifa_ifp);
+ nhop_set_transmit_ifp(nh, ifp);
+ nhop_set_src(nh, ifa);
+ nhop_set_pinned(nh, true);
+ nhop_set_pxtype_flag(nh, plen == 32 ? NHF_HOST : 0);
+ rnd.rnd_nhop = nhop_get_nhop(nh, &error);
+ if (error != 0)
+ return (error);
+ 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);
}
/*
@@ -959,19 +957,12 @@
{
struct ifaddr *ifa = &ia->ia_ifa;
struct in_addr daddr, maddr;
- struct sockaddr_in *pmask;
struct epoch_tracker et;
int error;
ia_getrtprefix(ia, &daddr, &maddr);
- 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;
+ int plen = bitcount32(maddr.s_addr);
struct sockaddr_in dst = {
.sin_family = AF_INET,
@@ -989,7 +980,8 @@
uint32_t fibnum = ifa->ifa_ifp->if_fib;
NET_EPOCH_ENTER(et);
- error = in_handle_prefix_route(fibnum, cmd, &dst, pmask, ifa, ifp);
+ error = in_handle_prefix_route(fibnum, cmd, (struct sockaddr *)&dst,
+ plen, ifa, ifp);
NET_EPOCH_EXIT(et);
return (error);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1267,6 +1267,29 @@
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.
* Returns 0 on success or errno.
@@ -1276,35 +1299,26 @@
{
struct epoch_tracker et;
struct ifaddr *ifa = &ia->ia_ifa;
+ uint32_t fibnum = ifa->ifa_ifp->if_fib;
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 = {
.sin6_family = AF_INET6,
.sin6_len = sizeof(struct sockaddr_in6),
.sin6_addr = ia->ia_dstaddr.sin6_addr,
};
- struct rt_addrinfo info = {
- .rti_ifa = ifa,
- .rti_ifp = ifa->ifa_ifp,
- .rti_flags = RTF_PINNED | RTF_HOST,
- .rti_info = {
- [RTAX_DST] = (struct sockaddr *)&dst,
- [RTAX_GATEWAY] = (struct sockaddr *)&sdl,
- },
- };
- /* Don't set additional per-gw filters on removal */
-
NET_EPOCH_ENTER(et);
- error = rib_handle_ifaddr_info(ifa->ifa_ifp->if_fib, cmd, &info);
+ if (cmd == RTM_DELETE) {
+ struct sockaddr_dl link_sdl;
+ struct sockaddr *gw = (struct sockaddr *)&link_sdl;
+ struct ifnet *ifp = ifa->ifa_ifp;
+
+ link_init_sdl(ifp, gw, ifp->if_type);
+ error = rib_del_kernel_px(fibnum, (struct sockaddr *)&dst, 128,
+ rib_match_gw, gw, RTM_F_FORCE);
+ } else
+ error = in6_handle_dstaddr_rtadd(fibnum, (struct sockaddr *)&dst, ifa);
NET_EPOCH_EXIT(et);
return (error);
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -2014,41 +2014,55 @@
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.
* ifa can be NULL.
* Returns 0 on success
*/
static int
-nd6_prefix_rtrequest(uint32_t fibnum, int cmd, struct sockaddr_in6 *dst,
- struct sockaddr_in6 *netmask, struct ifnet *ifp, struct ifaddr *ifa)
+nd6_prefix_rtrequest(uint32_t fibnum, int cmd, struct sockaddr *dst,
+ int plen, struct ifnet *ifp, struct ifaddr *ifa)
{
struct epoch_tracker et;
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,
- };
+ NET_EPOCH_ENTER(et);
+ if (cmd == RTM_DELETE) {
+ struct sockaddr_dl link_sdl;
+ struct sockaddr *gw = (struct sockaddr *)&link_sdl;
- 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 */
+ 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_ENTER(et);
- error = rib_handle_ifaddr_info(fibnum, cmd, &info);
NET_EPOCH_EXIT(et);
+
return (error);
}
@@ -2057,15 +2071,8 @@
{
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,
- &pr->ndpr_prefix, pmask6, pr->ndpr_ifp, ifa);
+ (struct sockaddr *)&pr->ndpr_prefix, pr->ndpr_plen, pr->ndpr_ifp, ifa);
if (error == 0)
pr->ndpr_stateflags |= NDPRF_ONLINK;
@@ -2176,10 +2183,9 @@
.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(ifp->if_fib, RTM_DELETE,
- &pr->ndpr_prefix, pmask6, ifp, NULL);
+ (struct sockaddr *)&pr->ndpr_prefix, pr->ndpr_plen, ifp, NULL);
a_failure = 1;
if (error == 0) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jul 22, 5:15 PM (14 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35373489
Default Alt Text
D36166.id109945.diff (15 KB)
Attached To
Mode
D36166: routing: install prefix and loopback routes using new nhop-based KPI.
Attached
Detach File
Event Timeline
Log In to Comment