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:
parent
2fda0a6f3a
commit
a287a973e3
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user