Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Nov 2014 15:02:46 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r275243 - projects/routing/sys/net
Message-ID:  <201411291502.sATF2kRA036067@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sat Nov 29 15:02:45 2014
New Revision: 275243
URL: https://svnweb.freebsd.org/changeset/base/275243

Log:
  * Make ifa_add_loopback_route() prepare gw before insertion.
  * Temporarily move ifa_switch_loopback_route() implementation to route.c

Modified:
  projects/routing/sys/net/if.c
  projects/routing/sys/net/route.c
  projects/routing/sys/net/route.h

Modified: projects/routing/sys/net/if.c
==============================================================================
--- projects/routing/sys/net/if.c	Sat Nov 29 14:30:39 2014	(r275242)
+++ projects/routing/sys/net/if.c	Sat Nov 29 15:02:45 2014	(r275243)
@@ -1528,27 +1528,28 @@ ifa_free(struct ifaddr *ifa)
 int
 ifa_add_loopback_route(struct ifaddr *ifa, struct sockaddr *ia)
 {
-	int error = 0;
-	struct rtentry *rt = NULL;
+	int error;
 	struct rt_addrinfo info;
-	static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+	struct sockaddr_dl null_sdl;
+	struct ifnet *ifp;
+
+	ifp = ifa->ifa_ifp;
 
 	bzero(&info, sizeof(info));
 	info.rti_ifp = V_loif;
 	info.rti_flags = ifa->ifa_flags | RTF_HOST | RTF_STATIC;
 	info.rti_info[RTAX_DST] = ia;
 	info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&null_sdl;
-	error = rtrequest1_fib(RTM_ADD, &info, &rt, ifa->ifa_ifp->if_fib);
 
-	if (error == 0 && rt != NULL) {
-		RT_LOCK(rt);
-		((struct sockaddr_dl *)rt->rt_gateway)->sdl_type  =
-			ifa->ifa_ifp->if_type;
-		((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
-			ifa->ifa_ifp->if_index;
-		RT_REMREF(rt);
-		RT_UNLOCK(rt);
-	} else if (error != 0)
+	bzero(&null_sdl, sizeof(null_sdl));
+	null_sdl.sdl_len = sizeof(null_sdl);
+	null_sdl.sdl_family = AF_LINK;
+	null_sdl.sdl_type = ifp->if_type;
+	null_sdl.sdl_index = ifp->if_index;
+
+	error = rtrequest1_fib(RTM_ADD, &info, NULL, ifp->if_fib);
+
+	if (error != 0)
 		log(LOG_DEBUG, "%s: insertion failed: %u\n", __func__, error);
 
 	return (error);
@@ -1581,20 +1582,8 @@ ifa_del_loopback_route(struct ifaddr *if
 int
 ifa_switch_loopback_route(struct ifaddr *ifa, struct sockaddr *sa, int fib)
 {
-	struct rtentry *rt;
-
-	rt = rtalloc1_fib(sa, 0, 0, fib);
-	if (rt == NULL) {
-		log(LOG_DEBUG, "%s: fail", __func__);
-		return (EHOSTUNREACH);
-	}
-	((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
-	    ifa->ifa_ifp->if_type;
-	((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
-	    ifa->ifa_ifp->if_index;
-	RTFREE_LOCKED(rt);
 
-	return (0);
+	return (rt_switch_loopback_route(fib, sa, ifa->ifa_ifp));
 }
 
 /*

Modified: projects/routing/sys/net/route.c
==============================================================================
--- projects/routing/sys/net/route.c	Sat Nov 29 14:30:39 2014	(r275242)
+++ projects/routing/sys/net/route.c	Sat Nov 29 15:02:45 2014	(r275243)
@@ -2027,6 +2027,52 @@ rtinit(struct ifaddr *ifa, int cmd, int 
 }
 
 /*
+ * Switches 'real' interface index inside rt_gateway
+ * for address in @dst to interface @ifp.
+ *
+ * Returns 0 on success/
+ */
+int
+rt_switch_loopback_route(uint32_t fibnum, struct sockaddr *dst,
+    struct ifnet *ifp)
+{
+	struct rib_head *rh;
+	struct radix_node *rn;
+	struct rtentry *rt;
+	struct sockaddr_dl *sdl;
+
+	KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
+	rh = rt_tables_get_rnh(fibnum, dst->sa_family);
+	if (rh == NULL)
+		return (EHOSTUNREACH);
+
+	RIB_CFG_WLOCK(rh);
+	rn = rh->rnh_matchaddr(dst, &rh->head);
+	if (rn == NULL && ((rn->rn_flags & RNF_ROOT) != 0)) {
+		RIB_CFG_WUNLOCK(rh);
+		return (EHOSTUNREACH);
+	}
+	rt = RNTORT(rn);
+
+	/* Ensure we have found host route */
+	if (rt_mask(rt) == NULL) {
+		sdl = (struct sockaddr_dl *)rt->rt_gateway;
+		RIB_WLOCK(rh);
+		sdl->sdl_type = ifp->if_type;
+		sdl->sdl_index = ifp->if_index;
+		RIB_WUNLOCK(rh);
+	} else
+		rt = NULL;
+
+	RIB_CFG_WUNLOCK(rh);
+
+	if (rt == NULL)
+		return (EHOSTUNREACH);
+
+	return (0);
+}
+
+/*
  * Announce interface address arrival/withdraw
  * Returns 0 on success.
  */

Modified: projects/routing/sys/net/route.h
==============================================================================
--- projects/routing/sys/net/route.h	Sat Nov 29 14:30:39 2014	(r275242)
+++ projects/routing/sys/net/route.h	Sat Nov 29 15:02:45 2014	(r275243)
@@ -338,6 +338,7 @@ typedef int rt_walktree_f_t(struct rtent
 typedef void rt_setwarg_t(struct rib_head *, uint32_t, int, void *);
 void	rt_foreach_fib(int af, rt_setwarg_t *, rt_walktree_f_t *, void *);
 void	rt_flushifroutes(struct ifnet *ifp);
+int	rt_switch_loopback_route(uint32_t, struct sockaddr *, struct ifnet *);
 
 /* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */
 /* Thes are used by old code not yet converted to use multiple FIBS */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411291502.sATF2kRA036067>