> On 1. Jun 2020, at 22:49, Alexander V. Chernikov <melif...@freebsd.org> wrote: > > Author: melifaro > Date: Mon Jun 1 20:49:42 2020 > New Revision: 361706 > URL: https://svnweb.freebsd.org/changeset/base/361706 > > Log: > * Add rib_<add|del|change>_route() functions to manipulate the routing table. > > The main driver for the change is the need to improve notification mechanism. > Currently callers guess the operation data based on the rtentry structure > returned in case of successful operation result. There are two problems with > this appoach. First is that it doesn't provide enough information for the > upcoming multipath changes, where rtentry refers to a new nexthop group, > and there is no way of guessing which paths were added during the change. > Second is that some rtentry fields can change during notification and > protecting from it by requiring customers to unlock rtentry is not desired. > > Additionally, as the consumers such as rtsock do know which operation they > request in advance, making explicit add/change/del versions of the functions > makes sense, especially given the functions don't share a lot of code. > > With that in mind, introduce rib_cmd_info notification structure and > rib_<add|del|change>_route() functions, with mandatory rib_cmd_info pointer. > It will be used in upcoming generalized notifications. > > * Move definitions of the new functions and some other functions/structures > used for the routing table manipulation to a separate header file, > net/route/route_ctl.h. net/route.h is a frequently used file included in > ~140 places in kernel, and 90% of the users don't need these definitions. > > Reviewed by: ae > Differential Revision: https://reviews.freebsd.org/D25067 > > Modified: > head/sys/net/if_llatbl.c > head/sys/net/route.c > head/sys/net/route.h > head/sys/net/route/nhop_ctl.c > head/sys/net/route/route_ctl.c > head/sys/net/route/route_ddb.c > head/sys/net/route/route_helpers.c > head/sys/net/route/route_temporal.c > head/sys/net/route/route_var.h > head/sys/netinet/in_rmx.c > head/sys/netinet/ip_icmp.c > head/sys/netinet6/icmp6.c > head/sys/netinet6/in6_rmx.c > head/sys/netinet6/nd6_rtr.c > > Modified: head/sys/net/if_llatbl.c > ============================================================================== > --- head/sys/net/if_llatbl.c Mon Jun 1 20:40:40 2020 (r361705) > +++ head/sys/net/if_llatbl.c Mon Jun 1 20:49:42 2020 (r361706) > @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_dl.h> > #include <net/if_var.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> Where is this file coming from?
Best regards Michael > #include <net/vnet.h> > #include <netinet/if_ether.h> > #include <netinet6/in6_var.h> > > Modified: head/sys/net/route.c > ============================================================================== > --- head/sys/net/route.c Mon Jun 1 20:40:40 2020 (r361705) > +++ head/sys/net/route.c Mon Jun 1 20:49:42 2020 (r361706) > @@ -61,6 +61,7 @@ > #include <net/if_var.h> > #include <net/if_dl.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop.h> > #include <net/route/shared.h> > @@ -346,6 +347,9 @@ rt_table_init(int offset, int family, u_int fibnum) > > nhops_init_rib(rh); > > + /* Init subscription system */ > + CK_STAILQ_INIT(&rh->rnh_subscribers); > + > /* Finally, set base callbacks */ > rh->rnh_addaddr = rn_addroute; > rh->rnh_deladdr = rn_delete; > @@ -1148,6 +1152,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru > { > const struct sockaddr *dst; > struct rib_head *rnh; > + struct rib_cmd_info rc; > int error; > > KASSERT((fibnum < rt_numfibs), ("rtrequest1_fib: bad fibnum")); > @@ -1180,10 +1185,11 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru > if (info->rti_flags & RTF_HOST) > info->rti_info[RTAX_NETMASK] = NULL; > > + bzero(&rc, sizeof(struct rib_cmd_info)); > error = 0; > switch (req) { > case RTM_DELETE: > - error = del_route(rnh, info, ret_nrt); > + error = del_route(rnh, info, &rc); > break; > case RTM_RESOLVE: > /* > @@ -1192,14 +1198,17 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru > */ > break; > case RTM_ADD: > - error = add_route(rnh, info, ret_nrt); > + error = add_route(rnh, info, &rc); > break; > case RTM_CHANGE: > - error = change_route(rnh, info, ret_nrt); > + error = change_route(rnh, info, &rc); > break; > default: > error = EOPNOTSUPP; > } > + > + if (ret_nrt != NULL) > + *ret_nrt = rc.rc_rt; > > return (error); > } > > Modified: head/sys/net/route.h > ============================================================================== > --- head/sys/net/route.h Mon Jun 1 20:40:40 2020 (r361705) > +++ head/sys/net/route.h Mon Jun 1 20:49:42 2020 (r361706) > @@ -399,12 +399,6 @@ void rtfree(struct rtentry *); > void rtfree_func(struct rtentry *); > void rt_updatemtu(struct ifnet *); > > -typedef int rt_walktree_f_t(struct rtentry *, void *); > -typedef void rt_setwarg_t(struct rib_head *, uint32_t, int, void *); > -void rib_walk_del(u_int fibnum, int family, rt_filter_f_t *filter_f, > - void *arg, bool report); > -void rt_foreach_fib_walk(int af, rt_setwarg_t *, rt_walktree_f_t *, void *); > -void rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg); > void rt_flushifroutes_af(struct ifnet *, int); > void rt_flushifroutes(struct ifnet *ifp); > > @@ -423,12 +417,8 @@ int rtrequest1_fib(int, struct rt_addrinfo *, > struct > int rib_lookup_info(uint32_t, const struct sockaddr *, uint32_t, uint32_t, > struct rt_addrinfo *); > void rib_free_info(struct rt_addrinfo *info); > -int rib_add_redirect(u_int fibnum, struct sockaddr *dst, > - struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp, > - int flags, int expire_sec); > > /* New API */ > -void rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg); > struct nhop_object *rib_lookup(uint32_t fibnum, const struct sockaddr *dst, > uint32_t flags, uint32_t flowid); > #endif > > Modified: head/sys/net/route/nhop_ctl.c > ============================================================================== > --- head/sys/net/route/nhop_ctl.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/nhop_ctl.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_var.h> > #include <net/if_dl.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop_utils.h> > #include <net/route/nhop.h> > > Modified: head/sys/net/route/route_ctl.c > ============================================================================== > --- head/sys/net/route/route_ctl.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/route_ctl.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_dl.h> > #include <net/vnet.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop_utils.h> > #include <net/route/nhop.h> > @@ -67,11 +68,61 @@ __FBSDID("$FreeBSD$"); > * All functions assumes they are called in net epoch. > */ > > +static void rib_notify(struct rib_head *rnh, enum rib_subscription_type type, > + struct rib_cmd_info *rc); > + > static void rt_notifydelete(struct rtentry *rt, struct rt_addrinfo *info); > > +static struct rib_head * > +get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) > +{ > + struct rib_head *rnh; > + struct sockaddr *dst; > + > + KASSERT((fibnum < rt_numfibs), ("rib_add_route: bad fibnum")); > + > + dst = info->rti_info[RTAX_DST]; > + rnh = rt_tables_get_rnh(fibnum, dst->sa_family); > + > + return (rnh); > +} > + > +/* > + * Adds route defined by @info into the kernel table specified by @fibnum and > + * sa_family in @info->rti_info[RTAX_DST]. > + * > + * Returns 0 on success and fills in operation metadata into @rc. > + */ > int > +rib_add_route(uint32_t fibnum, struct rt_addrinfo *info, > + struct rib_cmd_info *rc) > +{ > + struct rib_head *rnh; > + > + NET_EPOCH_ASSERT(); > + > + rnh = get_rnh(fibnum, info); > + if (rnh == NULL) > + return (EAFNOSUPPORT); > + > + /* > + * Check consistency between RTF_HOST flag and netmask > + * existence. > + */ > + if (info->rti_flags & RTF_HOST) > + info->rti_info[RTAX_NETMASK] = NULL; > + else if (info->rti_info[RTAX_NETMASK] == NULL) > + return (EINVAL); > + > + bzero(rc, sizeof(struct rib_cmd_info)); > + rc->rc_cmd = RTM_ADD; > + > + return (add_route(rnh, info, rc)); > +} > + > +int > add_route(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt) > + struct rib_cmd_info *rc) > { > struct sockaddr *dst, *ndst, *gateway, *netmask; > struct rtentry *rt, *rt_old; > @@ -146,6 +197,7 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *in > rt->rt_weight = 1; > > rt_setmetrics(info, rt); > + rt_old = NULL; > > RIB_WLOCK(rnh); > RT_LOCK(rt); > @@ -163,12 +215,20 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *in > > rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, rt->rt_nodes); > > - if (rn != NULL && rt->rt_expire > 0) > - tmproutes_update(rnh, rt); > + if (rn != NULL) { > + /* Most common usecase */ > + if (rt->rt_expire > 0) > + tmproutes_update(rnh, rt); > > - rt_old = NULL; > - if (rn == NULL && (info->rti_flags & RTF_PINNED) != 0) { > + /* Finalize notification */ > + rnh->rnh_gen++; > > + rc->rc_rt = RNTORT(rn); > + rc->rc_nh_new = nh; > + > + rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); > + } else if ((info->rti_flags & RTF_PINNED) != 0) { > + > /* > * Force removal and re-try addition > * TODO: better multipath&pinned support > @@ -180,9 +240,26 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *in > rt_old = rt_unlinkrte(rnh, info, &error); > info->rti_flags |= RTF_PINNED; > info->rti_info[RTAX_DST] = info_dst; > - if (rt_old != NULL) > + if (rt_old != NULL) { > rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, > rt->rt_nodes); > + > + /* Finalize notification */ > + rnh->rnh_gen++; > + > + if (rn != NULL) { > + rc->rc_cmd = RTM_CHANGE; > + rc->rc_rt = RNTORT(rn); > + rc->rc_nh_old = rt_old->rt_nhop; > + rc->rc_nh_new = nh; > + } else { > + rc->rc_cmd = RTM_DELETE; > + rc->rc_rt = RNTORT(rn); > + rc->rc_nh_old = rt_old->rt_nhop; > + rc->rc_nh_new = nh; > + } > + rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); > + } > } > RIB_WUNLOCK(rnh); > > @@ -208,12 +285,6 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *in > if (ifa->ifa_rtrequest) > ifa->ifa_rtrequest(RTM_ADD, rt, rt->rt_nhop, info); > > - /* > - * actually return a resultant rtentry > - */ > - if (ret_nrt) > - *ret_nrt = rt; > - rnh->rnh_gen++; /* Routing table updated */ > RT_UNLOCK(rt); > > return (0); > @@ -221,6 +292,29 @@ add_route(struct rib_head *rnh, struct rt_addrinfo *in > > > /* > + * Removes route defined by @info from the kernel table specified by @fibnum > and > + * sa_family in @info->rti_info[RTAX_DST]. > + * > + * Returns 0 on success and fills in operation metadata into @rc. > + */ > +int > +rib_del_route(uint32_t fibnum, struct rt_addrinfo *info, struct rib_cmd_info > *rc) > +{ > + struct rib_head *rnh; > + > + NET_EPOCH_ASSERT(); > + > + rnh = get_rnh(fibnum, info); > + if (rnh == NULL) > + return (EAFNOSUPPORT); > + > + bzero(rc, sizeof(struct rib_cmd_info)); > + rc->rc_cmd = RTM_DELETE; > + > + return (del_route(rnh, info, rc)); > +} > + > +/* > * Conditionally unlinks rtentry matching data inside @info from @rnh. > * Returns unlinked, locked and referenced @rtentry on success, > * Returns NULL and sets @perror to: > @@ -295,7 +389,7 @@ rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo > > int > del_route(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt) > + struct rib_cmd_info *rc) > { > struct sockaddr *dst, *netmask; > struct sockaddr_storage mdst; > @@ -314,6 +408,13 @@ del_route(struct rib_head *rnh, struct rt_addrinfo *in > > RIB_WLOCK(rnh); > rt = rt_unlinkrte(rnh, info, &error); > + if (rt != NULL) { > + /* Finalize notification */ > + rnh->rnh_gen++; > + rc->rc_rt = rt; > + rc->rc_nh_old = rt->rt_nhop; > + rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); > + } > RIB_WUNLOCK(rnh); > if (error != 0) > return (error); > @@ -324,17 +425,32 @@ del_route(struct rib_head *rnh, struct rt_addrinfo *in > * If the caller wants it, then it can have it, > * the entry will be deleted after the end of the current epoch. > */ > - if (ret_nrt) > - *ret_nrt = rt; > - > rtfree(rt); > > return (0); > } > > +int > +rib_change_route(uint32_t fibnum, struct rt_addrinfo *info, > + struct rib_cmd_info *rc) > +{ > + struct rib_head *rnh; > + > + NET_EPOCH_ASSERT(); > + > + rnh = get_rnh(fibnum, info); > + if (rnh == NULL) > + return (EAFNOSUPPORT); > + > + bzero(rc, sizeof(struct rib_cmd_info)); > + rc->rc_cmd = RTM_CHANGE; > + > + return (change_route(rnh, info, rc)); > +} > + > static int > change_route_one(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt) > + struct rib_cmd_info *rc) > { > RIB_RLOCK_TRACKER; > struct rtentry *rt = NULL; > @@ -434,14 +550,18 @@ change_route_one(struct rib_head *rnh, struct rt_addri > if ((nh_orig->nh_ifa != nh->nh_ifa) && nh_orig->nh_ifa->ifa_rtrequest) > nh_orig->nh_ifa->ifa_rtrequest(RTM_DELETE, rt, nh_orig, info); > > - if (ret_nrt != NULL) > - *ret_nrt = rt; > + /* Finalize notification */ > + rc->rc_rt = rt; > + rc->rc_nh_old = nh_orig; > + rc->rc_nh_new = rt->rt_nhop; > > RT_UNLOCK(rt); > > /* Update generation id to reflect rtable change */ > rnh->rnh_gen++; > > + rib_notify(rnh, RIB_NOTIFY_IMMEDIATE, rc); > + > RIB_WUNLOCK(rnh); > > nhop_free(nh_orig); > @@ -451,7 +571,7 @@ change_route_one(struct rib_head *rnh, struct rt_addri > > int > change_route(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt) > + struct rib_cmd_info *rc) > { > int error; > > @@ -468,7 +588,7 @@ change_route(struct rib_head *rnh, struct rt_addrinfo > * multiple times before failing. > */ > for (int i = 0; i < RIB_MAX_RETRIES; i++) { > - error = change_route_one(rnh, info, ret_nrt); > + error = change_route_one(rnh, info, rc); > if (error != EAGAIN) > break; > } > @@ -581,4 +701,62 @@ rib_walk_del(u_int fibnum, int family, rt_filter_f_t * > } > } > > +static void > +rib_notify(struct rib_head *rnh, enum rib_subscription_type type, > + struct rib_cmd_info *rc) > +{ > + struct rib_subscription *rs; > + > + CK_STAILQ_FOREACH(rs, &rnh->rnh_subscribers, next) { > + if (rs->type == type) > + rs->func(rnh, rc, rs->arg); > + } > +} > + > +struct rib_subscription * > +rib_subscribe(uint32_t fibnum, int family, rib_subscription_cb_t *f, void > *arg, > + enum rib_subscription_type type, int waitok) > +{ > + struct rib_head *rnh; > + struct rib_subscription *rs; > + int flags = M_ZERO | (waitok ? M_WAITOK : 0); > + > + NET_EPOCH_ASSERT(); > + KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__)); > + rnh = rt_tables_get_rnh(fibnum, family); > + > + rs = malloc(sizeof(struct rib_subscription), M_RTABLE, flags); > + if (rs == NULL) > + return (NULL); > + > + rs->func = f; > + rs->arg = arg; > + rs->type = type; > + > + RIB_WLOCK(rnh); > + CK_STAILQ_INSERT_TAIL(&rnh->rnh_subscribers, rs, next); > + RIB_WUNLOCK(rnh); > + > + return (rs); > +} > + > +int > +rib_unsibscribe(uint32_t fibnum, int family, struct rib_subscription *rs) > +{ > + struct rib_head *rnh; > + > + NET_EPOCH_ASSERT(); > + KASSERT((fibnum < rt_numfibs), ("%s: bad fibnum", __func__)); > + rnh = rt_tables_get_rnh(fibnum, family); > + > + if (rnh == NULL) > + return (ENOENT); > + > + RIB_WLOCK(rnh); > + CK_STAILQ_REMOVE(&rnh->rnh_subscribers, rs, rib_subscription, next); > + RIB_WUNLOCK(rnh); > + > + free(rs, M_RTABLE); > + return (0); > +} > > > Modified: head/sys/net/route/route_ddb.c > ============================================================================== > --- head/sys/net/route/route_ddb.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/route_ddb.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_dl.h> > #include <net/route.h> > #include <net/route/nhop.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > > /* > > Modified: head/sys/net/route/route_helpers.c > ============================================================================== > --- head/sys/net/route/route_helpers.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/route_helpers.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_var.h> > #include <net/if_dl.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop_utils.h> > #include <net/route/nhop.h> > > Modified: head/sys/net/route/route_temporal.c > ============================================================================== > --- head/sys/net/route/route_temporal.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/route_temporal.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -38,11 +38,13 @@ __FBSDID("$FreeBSD$"); > #include <sys/socket.h> > #include <sys/kernel.h> > #include <sys/lock.h> > +#include <sys/ck.h> > #include <sys/rmlock.h> > #include <sys/callout.h> > > #include <net/if.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/vnet.h> > > > Modified: head/sys/net/route/route_var.h > ============================================================================== > --- head/sys/net/route/route_var.h Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/net/route/route_var.h Mon Jun 1 20:49:42 2020 > (r361706) > @@ -35,6 +35,7 @@ > #ifndef RNF_NORMAL > #include <net/radix.h> > #endif > +#include <sys/ck.h> > #include <sys/epoch.h> > #include <netinet/in.h> /* struct sockaddr_in */ > #include <sys/counter.h> > @@ -63,6 +64,7 @@ struct rib_head { > struct callout expire_callout; /* Callout for expiring dynamic > routes */ > time_t next_expire; /* Next expire run ts */ > struct nh_control *nh_control; /* nexthop subsystem data */ > + CK_STAILQ_HEAD(, rib_subscription) rnh_subscribers;/* notification > subscribers */ > }; > > #define RIB_RLOCK_TRACKER struct rm_priotracker _rib_tracker > @@ -110,12 +112,13 @@ void rt_setmetrics(const struct rt_addrinfo *info, str > struct radix_node *rt_mpath_unlink(struct rib_head *rnh, > struct rt_addrinfo *info, struct rtentry *rto, int *perror); > #endif > +struct rib_cmd_info; > int add_route(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt); > + struct rib_cmd_info *rc); > int del_route(struct rib_head *rnh, struct rt_addrinfo *info, > - struct rtentry **ret_nrt); > + struct rib_cmd_info *rc); > int change_route(struct rib_head *, struct rt_addrinfo *, > - struct rtentry **); > + struct rib_cmd_info *rc); > > VNET_PCPUSTAT_DECLARE(struct rtstat, rtstat); > #define RTSTAT_ADD(name, val) \ > > Modified: head/sys/netinet/in_rmx.c > ============================================================================== > --- head/sys/netinet/in_rmx.c Mon Jun 1 20:40:40 2020 (r361705) > +++ head/sys/netinet/in_rmx.c Mon Jun 1 20:49:42 2020 (r361706) > @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if.h> > #include <net/if_var.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop.h> > #include <net/route/shared.h> > > Modified: head/sys/netinet/ip_icmp.c > ============================================================================== > --- head/sys/netinet/ip_icmp.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/netinet/ip_icmp.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_var.h> > #include <net/if_types.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/nhop.h> > #include <net/vnet.h> > > > Modified: head/sys/netinet6/icmp6.c > ============================================================================== > --- head/sys/netinet6/icmp6.c Mon Jun 1 20:40:40 2020 (r361705) > +++ head/sys/netinet6/icmp6.c Mon Jun 1 20:49:42 2020 (r361706) > @@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_llatbl.h> > #include <net/if_types.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/nhop.h> > #include <net/vnet.h> > > > Modified: head/sys/netinet6/in6_rmx.c > ============================================================================== > --- head/sys/netinet6/in6_rmx.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/netinet6/in6_rmx.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if.h> > #include <net/if_var.h> > #include <net/route.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/route/nhop.h> > #include <net/route/shared.h> > > Modified: head/sys/netinet6/nd6_rtr.c > ============================================================================== > --- head/sys/netinet6/nd6_rtr.c Mon Jun 1 20:40:40 2020 > (r361705) > +++ head/sys/netinet6/nd6_rtr.c Mon Jun 1 20:49:42 2020 > (r361706) > @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); > #include <net/if_dl.h> > #include <net/route.h> > #include <net/route/nhop.h> > +#include <net/route/route_ctl.h> > #include <net/route/route_var.h> > #include <net/radix.h> > #include <net/vnet.h>
smime.p7s
Description: S/MIME cryptographic signature