aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2019-05-19 21:49:56 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2019-05-19 21:49:56 +0000
commit2ad7ed6e4a84448234e9aaef3c9fa884848f7387 (patch)
treea5a2b93e48beb4e23f13cee68010e5247cc550b9 /sys/net/if.c
parent980bde58344a6b226ed1618e3dcc22271e10cfa3 (diff)
downloadsrc-2ad7ed6e4a84448234e9aaef3c9fa884848f7387.tar.gz
src-2ad7ed6e4a84448234e9aaef3c9fa884848f7387.zip
Fix rt_ifa selection during loopback route insertion process.
Currently such routes are added with a link-level IFA, which is plain wrong. Only after the insertion they get fixed by the special link_rtrequest() ifa handler. This behaviour complicates routing code and makes ifa selection more complex. Streamline this process by explicitly moving link_rtrequest() logic to the pre-insertion rt_getifa_fib() ifa selector. Avoid calling all this logic in the loopback route case by explicitly specifying proper rt_ifa inside the ifa_maintain_loopback_route().ยง MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D20076
Notes
Notes: svn path=/head/; revision=347982
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c46
1 files changed, 11 insertions, 35 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 9ee22041090b..2a1edfe4d2c5 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -264,7 +264,6 @@ static void if_route(struct ifnet *, int flag, int fam);
static int if_setflag(struct ifnet *, int, int, int *, int);
static int if_transmit(struct ifnet *ifp, struct mbuf *m);
static void if_unroute(struct ifnet *, int flag, int fam);
-static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
static void do_link_state_change(void *, int);
static int if_getgroup(struct ifgroupreq *, struct ifnet *);
@@ -862,7 +861,6 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
sdl->sdl_type = ifp->if_type;
ifp->if_addr = ifa;
ifa->ifa_ifp = ifp;
- ifa->ifa_rtrequest = link_rtrequest;
ifa->ifa_addr = (struct sockaddr *)sdl;
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
ifa->ifa_netmask = (struct sockaddr *)sdl;
@@ -1892,6 +1890,7 @@ static int
ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
struct sockaddr *ia)
{
+ struct epoch_tracker et;
int error;
struct rt_addrinfo info;
struct sockaddr_dl null_sdl;
@@ -1902,6 +1901,16 @@ ifa_maintain_loopback_route(int cmd, const char *otype, struct ifaddr *ifa,
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) {
+ NET_EPOCH_ENTER(et);
+ info.rti_ifa = ifaof_ifpforaddr(ifa->ifa_addr, info.rti_ifp);
+ if (info.rti_ifa != NULL)
+ ifa_ref(info.rti_ifa);
+ NET_EPOCH_EXIT(et);
+ }
+ }
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;
@@ -2210,39 +2219,6 @@ ifa_preferred(struct ifaddr *cur, struct ifaddr *next)
((*carp_master_p)(next) && !(*carp_master_p)(cur))));
}
-#include <net/if_llatbl.h>
-
-/*
- * Default action when installing a route with a Link Level gateway.
- * Lookup an appropriate real ifa to point to.
- * This should be moved to /sys/net/link.c eventually.
- */
-static void
-link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
-{
- struct epoch_tracker et;
- struct ifaddr *ifa, *oifa;
- struct sockaddr *dst;
- struct ifnet *ifp;
-
- if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == NULL) ||
- ((ifp = ifa->ifa_ifp) == NULL) || ((dst = rt_key(rt)) == NULL))
- return;
- NET_EPOCH_ENTER(et);
- ifa = ifaof_ifpforaddr(dst, ifp);
- if (ifa) {
- oifa = rt->rt_ifa;
- if (oifa != ifa) {
- ifa_free(oifa);
- ifa_ref(ifa);
- }
- rt->rt_ifa = ifa;
- if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
- ifa->ifa_rtrequest(cmd, rt, info);
- }
- NET_EPOCH_EXIT(et);
-}
-
struct sockaddr_dl *
link_alloc_sdl(size_t size, int flags)
{