Switch rtsock code to using newly-create rib_action() KPI call.

This simplifies the code and allows to further split rtentry and nexthop,
 removing one of the blockers for multipath code introduction, described in
 D24141.

Reviewed by:	ae
Differential Revision:	https://reviews.freebsd.org/D25192
This commit is contained in:
Alexander V. Chernikov 2020-06-10 07:46:22 +00:00
parent 2fda0a6f3a
commit a287a973e3
3 changed files with 62 additions and 43 deletions

View File

@ -610,6 +610,37 @@ change_route(struct rib_head *rnh, struct rt_addrinfo *info,
return (error); return (error);
} }
/*
* Performs modification of routing table specificed by @action.
* Table is specified by @fibnum and sa_family in @info->rti_info[RTAX_DST].
* Needs to be run in network epoch.
*
* Returns 0 on success and fills in @rc with action result.
*/
int
rib_action(uint32_t fibnum, int action, struct rt_addrinfo *info,
struct rib_cmd_info *rc)
{
int error;
switch (action) {
case RTM_ADD:
error = rib_add_route(fibnum, info, rc);
break;
case RTM_DELETE:
error = rib_del_route(fibnum, info, rc);
break;
case RTM_CHANGE:
error = rib_change_route(fibnum, info, rc);
break;
default:
error = ENOTSUP;
}
return (error);
}
static void static void
rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info) rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info)
{ {

View File

@ -51,6 +51,8 @@ int rib_del_route(uint32_t fibnum, struct rt_addrinfo *info,
struct rib_cmd_info *rc); struct rib_cmd_info *rc);
int rib_change_route(uint32_t fibnum, struct rt_addrinfo *info, 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,
struct rib_cmd_info *rc);
int rib_add_redirect(u_int fibnum, struct sockaddr *dst, int rib_add_redirect(u_int fibnum, struct sockaddr *dst,
struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp, struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp,

View File

@ -62,6 +62,7 @@
#include <net/netisr.h> #include <net/netisr.h>
#include <net/raw_cb.h> #include <net/raw_cb.h>
#include <net/route.h> #include <net/route.h>
#include <net/route/route_ctl.h>
#include <net/route/route_var.h> #include <net/route/route_var.h>
#ifdef RADIX_MPATH #ifdef RADIX_MPATH
#include <net/radix_mpath.h> #include <net/radix_mpath.h>
@ -181,10 +182,10 @@ static int route_output(struct mbuf *m, struct socket *so, ...);
static void rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out); static void rt_getmetrics(const struct rtentry *rt, struct rt_metrics *out);
static void rt_dispatch(struct mbuf *, sa_family_t); static void rt_dispatch(struct mbuf *, sa_family_t);
static int handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, static int handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
struct rt_msghdr *rtm, struct rtentry **ret_nrt); struct rt_msghdr *rtm, struct rib_cmd_info *rc);
static int update_rtm_from_rte(struct rt_addrinfo *info, static int update_rtm_from_rte(struct rt_addrinfo *info,
struct rt_msghdr **prtm, int alloc_len, struct rt_msghdr **prtm, int alloc_len,
struct rtentry *rt); struct rtentry *rt, struct nhop_object *nh);
static void send_rtm_reply(struct socket *so, struct rt_msghdr *rtm, static void send_rtm_reply(struct socket *so, struct rt_msghdr *rtm,
struct mbuf *m, sa_family_t saf, u_int fibnum, struct mbuf *m, sa_family_t saf, u_int fibnum,
int rtm_errno); int rtm_errno);
@ -656,10 +657,9 @@ fill_addrinfo(struct rt_msghdr *rtm, int len, u_int fibnum, struct rt_addrinfo *
*/ */
static int static int
handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
struct rt_msghdr *rtm, struct rtentry **ret_nrt) struct rt_msghdr *rtm, struct rib_cmd_info *rc)
{ {
RIB_RLOCK_TRACKER; RIB_RLOCK_TRACKER;
struct rtentry *rt;
struct rib_head *rnh; struct rib_head *rnh;
sa_family_t saf; sa_family_t saf;
@ -677,14 +677,14 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
* address lookup (no mask). * address lookup (no mask).
* 'route -n get addr' * 'route -n get addr'
*/ */
rt = (struct rtentry *) rnh->rnh_matchaddr( rc->rc_rt = (struct rtentry *) rnh->rnh_matchaddr(
info->rti_info[RTAX_DST], &rnh->head); info->rti_info[RTAX_DST], &rnh->head);
} else } else
rt = (struct rtentry *) rnh->rnh_lookup( rc->rc_rt = (struct rtentry *) rnh->rnh_lookup(
info->rti_info[RTAX_DST], info->rti_info[RTAX_DST],
info->rti_info[RTAX_NETMASK], &rnh->head); info->rti_info[RTAX_NETMASK], &rnh->head);
if (rt == NULL) { if (rc->rc_rt == NULL) {
RIB_RUNLOCK(rnh); RIB_RUNLOCK(rnh);
return (ESRCH); return (ESRCH);
} }
@ -695,8 +695,9 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
* (no need to call rt_mpath_matchgate if gate == NULL) * (no need to call rt_mpath_matchgate if gate == NULL)
*/ */
if (rt_mpath_capable(rnh) && info->rti_info[RTAX_GATEWAY]) { if (rt_mpath_capable(rnh) && info->rti_info[RTAX_GATEWAY]) {
rt = rt_mpath_matchgate(rt, info->rti_info[RTAX_GATEWAY]); rc->rc_rt = rt_mpath_matchgate(rc->rc_rt,
if (!rt) { info->rti_info[RTAX_GATEWAY]);
if (rc->rc_rt == NULL) {
RIB_RUNLOCK(rnh); RIB_RUNLOCK(rnh);
return (ESRCH); return (ESRCH);
} }
@ -713,16 +714,13 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
struct sockaddr laddr; struct sockaddr laddr;
struct nhop_object *nh; struct nhop_object *nh;
nh = rt->rt_nhop; nh = rc->rc_rt->rt_nhop;
if (nh->nh_ifp != NULL && if (nh->nh_ifp != NULL &&
nh->nh_ifp->if_type == IFT_PROPVIRTUAL) { nh->nh_ifp->if_type == IFT_PROPVIRTUAL) {
struct epoch_tracker et;
struct ifaddr *ifa; struct ifaddr *ifa;
NET_EPOCH_ENTER(et);
ifa = ifa_ifwithnet(info->rti_info[RTAX_DST], 1, ifa = ifa_ifwithnet(info->rti_info[RTAX_DST], 1,
RT_ALL_FIBS); RT_ALL_FIBS);
NET_EPOCH_EXIT(et);
if (ifa != NULL) if (ifa != NULL)
rt_maskedcopy(ifa->ifa_addr, rt_maskedcopy(ifa->ifa_addr,
&laddr, &laddr,
@ -734,24 +732,21 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
/* /*
* refactor rt and no lock operation necessary * refactor rt and no lock operation necessary
*/ */
rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, rc->rc_rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr,
&rnh->head); &rnh->head);
if (rt == NULL) { if (rc->rc_rt == NULL) {
RIB_RUNLOCK(rnh); RIB_RUNLOCK(rnh);
return (ESRCH); return (ESRCH);
} }
} }
RT_LOCK(rt); rc->rc_nh_new = rc->rc_rt->rt_nhop;
RIB_RUNLOCK(rnh); RIB_RUNLOCK(rnh);
*ret_nrt = rt;
return (0); return (0);
} }
/* /*
* Update sockaddrs, flags, etc in @prtm based on @rt data. * Update sockaddrs, flags, etc in @prtm based on @rt data.
* Assumes @rt is locked.
* rtm can be reallocated. * rtm can be reallocated.
* *
* Returns 0 on success, along with pointer to (potentially reallocated) * Returns 0 on success, along with pointer to (potentially reallocated)
@ -760,21 +755,17 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum,
*/ */
static int static int
update_rtm_from_rte(struct rt_addrinfo *info, struct rt_msghdr **prtm, update_rtm_from_rte(struct rt_addrinfo *info, struct rt_msghdr **prtm,
int alloc_len, struct rtentry *rt) int alloc_len, struct rtentry *rt, struct nhop_object *nh)
{ {
struct sockaddr_storage netmask_ss; struct sockaddr_storage netmask_ss;
struct walkarg w; struct walkarg w;
union sockaddr_union saun; union sockaddr_union saun;
struct rt_msghdr *rtm, *orig_rtm = NULL; struct rt_msghdr *rtm, *orig_rtm = NULL;
struct nhop_object *nh;
struct ifnet *ifp; struct ifnet *ifp;
int error, len; int error, len;
RT_LOCK_ASSERT(rt);
rtm = *prtm; rtm = *prtm;
nh = rt->rt_nhop;
info->rti_info[RTAX_DST] = rt_key(rt); info->rti_info[RTAX_DST] = rt_key(rt);
info->rti_info[RTAX_GATEWAY] = &nh->gw_sa; info->rti_info[RTAX_GATEWAY] = &nh->gw_sa;
info->rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt), info->rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
@ -854,6 +845,8 @@ route_output(struct mbuf *m, struct socket *so, ...)
int alloc_len = 0, len, error = 0, fibnum; int alloc_len = 0, len, error = 0, fibnum;
sa_family_t saf = AF_UNSPEC; sa_family_t saf = AF_UNSPEC;
struct walkarg w; struct walkarg w;
struct rib_cmd_info rc;
struct nhop_object *nh;
fibnum = so->so_fibnum; fibnum = so->so_fibnum;
@ -881,6 +874,7 @@ route_output(struct mbuf *m, struct socket *so, ...)
m_copydata(m, 0, len, (caddr_t)rtm); m_copydata(m, 0, len, (caddr_t)rtm);
bzero(&info, sizeof(info)); bzero(&info, sizeof(info));
bzero(&w, sizeof(w)); bzero(&w, sizeof(w));
nh = NULL;
if (rtm->rtm_version != RTM_VERSION) { if (rtm->rtm_version != RTM_VERSION) {
/* Do not touch message since format is unknown */ /* Do not touch message since format is unknown */
@ -912,33 +906,26 @@ route_output(struct mbuf *m, struct socket *so, ...)
} }
switch (rtm->rtm_type) { switch (rtm->rtm_type) {
struct rtentry *saved_nrt;
case RTM_ADD: case RTM_ADD:
case RTM_CHANGE: case RTM_CHANGE:
if (rtm->rtm_type == RTM_ADD) { if (rtm->rtm_type == RTM_ADD) {
if (info.rti_info[RTAX_GATEWAY] == NULL) if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL); senderr(EINVAL);
} }
saved_nrt = NULL; error = rib_action(fibnum, rtm->rtm_type, &info, &rc);
error = rtrequest1_fib(rtm->rtm_type, &info, &saved_nrt, if (error == 0) {
fibnum);
if (error == 0 && saved_nrt != NULL) {
#ifdef INET6 #ifdef INET6
rti_need_deembed = (V_deembed_scopeid) ? 1 : 0; rti_need_deembed = (V_deembed_scopeid) ? 1 : 0;
#endif #endif
RT_LOCK(saved_nrt); rtm->rtm_index = rc.rc_nh_new->nh_ifp->if_index;
rtm->rtm_index = saved_nrt->rt_nhop->nh_ifp->if_index; nh = rc.rc_nh_new;
RT_UNLOCK(saved_nrt);
} }
break; break;
case RTM_DELETE: case RTM_DELETE:
saved_nrt = NULL; error = rib_action(fibnum, RTM_DELETE, &info, &rc);
error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt, fibnum);
if (error == 0) { if (error == 0) {
RT_LOCK(saved_nrt); nh = rc.rc_nh_old;
rt = saved_nrt;
goto report; goto report;
} }
#ifdef INET6 #ifdef INET6
@ -948,17 +935,17 @@ route_output(struct mbuf *m, struct socket *so, ...)
break; break;
case RTM_GET: case RTM_GET:
error = handle_rtm_get(&info, fibnum, rtm, &rt); error = handle_rtm_get(&info, fibnum, rtm, &rc);
if (error != 0) if (error != 0)
senderr(error); senderr(error);
nh = rc.rc_nh_new;
report: report:
RT_LOCK_ASSERT(rt); if (!can_export_rte(curthread->td_ucred, rc.rc_rt)) {
if (!can_export_rte(curthread->td_ucred, rt)) {
RT_UNLOCK(rt);
senderr(ESRCH); senderr(ESRCH);
} }
error = update_rtm_from_rte(&info, &rtm, alloc_len, rt);
error = update_rtm_from_rte(&info, &rtm, alloc_len, rc.rc_rt, nh);
/* /*
* Note that some sockaddr pointers may have changed to * Note that some sockaddr pointers may have changed to
* point to memory outsize @rtm. Some may be pointing * point to memory outsize @rtm. Some may be pointing
@ -974,7 +961,6 @@ route_output(struct mbuf *m, struct socket *so, ...)
#ifdef INET6 #ifdef INET6
rti_need_deembed = 0; rti_need_deembed = 0;
#endif #endif
RT_UNLOCK(rt);
if (error != 0) if (error != 0)
senderr(error); senderr(error);
break; break;