Being able to remove the requirement of an configured address for every
route entry would have multiple benefit:
. We could add route before the interface gets an address (useful in
some p2p configurations)
. The kernel wouldn't have to manage stale ifas
. The network data structures would be less coupled, making it easier
to write SMP safe code (yes I found new bugs!)
In order to achieve such goal we should preserve the "source routing"
feature. Which mean that route entry MUST still carry an address.
So the diff below adds a `rt_addr' field that will for the moment be a
copy of `rt_ifa->ifa_addr'. Once all the `rt_ifa' occurrences are
converted to `rt_addr' we can relax the logic for adding a route.
This is the first of 14 steps.
Index: net/route.c
===================================================================
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.307
diff -u -p -r1.307 route.c
--- net/route.c 8 Jun 2016 13:26:06 -0000 1.307
+++ net/route.c 8 Jun 2016 14:19:48 -0000
@@ -139,6 +139,8 @@
#include <net/if_enc.h>
#endif
+#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) :
sizeof(long))
+
/* Give some jitter to hash, to avoid synchronization between routers. */
static uint32_t rt_hashjitter;
@@ -151,6 +153,7 @@ struct pool rtentry_pool; /* pool for r
struct pool rttimer_pool; /* pool for rttimer structures */
void rt_timer_init(void);
+int rt_setaddr(struct rtentry *, struct sockaddr *);
int rtflushclone1(struct rtentry *, void *, u_int);
void rtflushclone(unsigned int, struct rtentry *);
int rt_if_remove_rtdelete(struct rtentry *, void *, u_int);
@@ -434,7 +437,6 @@ rtref(struct rtentry *rt)
void
rtfree(struct rtentry *rt)
{
- struct ifaddr *ifa;
int refcnt;
if (rt == NULL)
@@ -452,16 +454,14 @@ rtfree(struct rtentry *rt)
KERNEL_LOCK();
rt_timer_remove_all(rt);
- ifa = rt->rt_ifa;
- if (ifa)
- ifafree(ifa);
+ ifafree(rt->rt_ifa);
rtlabel_unref(rt->rt_labelid);
#ifdef MPLS
if (rt->rt_flags & RTF_MPLS)
free(rt->rt_llinfo, M_TEMP, sizeof(struct rt_mpls));
#endif
- if (rt->rt_gateway)
- free(rt->rt_gateway, M_RTABLE, 0);
+ free(rt->rt_addr, M_RTABLE, ROUNDUP(rt->rt_addr->sa_len));
+ free(rt->rt_gateway, M_RTABLE, ROUNDUP(rt->rt_gateway->sa_len));
free(rt_key(rt), M_RTABLE, rt_key(rt)->sa_len);
KERNEL_UNLOCK();
@@ -486,7 +486,7 @@ rt_sendmsg(struct rtentry *rt, int cmd,
ifp = if_get(rt->rt_ifidx);
if (ifp != NULL) {
info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
- info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ info.rti_info[RTAX_IFA] = rt->rt_addr;
}
rt_missmsg(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, 0,
@@ -767,8 +767,6 @@ ifa_ifwithroute(int flags, struct sockad
return (ifa);
}
-#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) :
sizeof(long))
-
int
rt_getifa(struct rt_addrinfo *info, u_int rtid)
{
@@ -958,7 +956,7 @@ rtrequest(int req, struct rt_addrinfo *i
* will get the new address and interface later.
*/
info->rti_ifa = NULL;
- info->rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ info->rti_info[RTAX_IFA] = rt->rt_addr;
}
info->rti_flags = rt->rt_flags | (RTF_CLONED|RTF_HOST);
@@ -1090,10 +1088,12 @@ rtrequest(int req, struct rt_addrinfo *i
* the routing table because the radix MPATH code use
* it to (re)order routes.
*/
- if ((error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]))) {
+ if ((error = rt_setaddr(rt, ifa->ifa_addr)) ||
+ (error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]))) {
ifafree(ifa);
rtfree(rt->rt_parent);
rtfree(rt->rt_gwroute);
+ free(rt->rt_addr, M_RTABLE, 0);
free(rt->rt_gateway, M_RTABLE, 0);
free(ndst, M_RTABLE, dlen);
pool_put(&rtentry_pool, rt);
@@ -1124,6 +1124,7 @@ rtrequest(int req, struct rt_addrinfo *i
ifafree(ifa);
rtfree(rt->rt_parent);
rtfree(rt->rt_gwroute);
+ free(rt->rt_addr, M_RTABLE, 0);
free(rt->rt_gateway, M_RTABLE, 0);
free(ndst, M_RTABLE, dlen);
pool_put(&rtentry_pool, rt);
@@ -1145,6 +1146,24 @@ rtrequest(int req, struct rt_addrinfo *i
rtfree(rt);
break;
}
+
+ return (0);
+}
+
+int
+rt_setaddr(struct rtentry *rt, struct sockaddr *addr)
+{
+ int alen = ROUNDUP(addr->sa_len);
+ struct sockaddr *sa;
+
+ KASSERT(rt->rt_addr == NULL);
+
+ sa = malloc(alen, M_RTABLE, M_NOWAIT);
+ if (sa == NULL)
+ return (ENOBUFS);
+
+ memmove(sa, addr, alen);
+ rt->rt_addr = sa;
return (0);
}
Index: net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.136
diff -u -p -r1.136 route.h
--- net/route.h 3 Jun 2016 02:56:59 -0000 1.136
+++ net/route.h 8 Jun 2016 14:19:48 -0000
@@ -99,6 +99,7 @@ struct rtentry {
struct sockaddr *rt_dest; /* destination */
SRPL_ENTRY(rtentry) rt_next; /* Next multipath entry to our dst. */
#endif
+ struct sockaddr *rt_addr; /* the answer: address to use */
struct sockaddr *rt_gateway; /* value */
struct ifaddr *rt_ifa; /* the answer: interface addr to use */
caddr_t rt_llinfo; /* pointer to link level info cache or
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.190
diff -u -p -r1.190 rtsock.c
--- net/rtsock.c 3 Jun 2016 02:56:59 -0000 1.190
+++ net/rtsock.c 8 Jun 2016 14:19:49 -0000
@@ -695,7 +695,7 @@ report:
ifp = if_get(rt->rt_ifidx);
if (ifp != NULL && rtm->rtm_addrs & (RTA_IFP|RTA_IFA)) {
info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
- info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ info.rti_info[RTAX_IFA] = rt->rt_addr;
if (ifp->if_flags & IFF_POINTOPOINT)
info.rti_info[RTAX_BRD] =
rt->rt_ifa->ifa_dstaddr;
@@ -1279,7 +1279,7 @@ sysctl_dumpentry(struct rtentry *rt, voi
ifp = if_get(rt->rt_ifidx);
if (ifp != NULL) {
info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
- info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
+ info.rti_info[RTAX_IFA] = rt->rt_addr;
if (ifp->if_flags & IFF_POINTOPOINT)
info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
}
Index: netinet/if_ether.c
===================================================================
RCS file: /cvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.213
diff -u -p -r1.213 if_ether.c
--- netinet/if_ether.c 6 Jun 2016 07:07:11 -0000 1.213
+++ netinet/if_ether.c 8 Jun 2016 14:19:49 -0000
@@ -388,7 +388,7 @@ arpresolve(struct ifnet *ifp, struct rte
rt->rt_expire = time_uptime;
if (la->la_asked++ < arp_maxtries)
arprequest(ifp,
-
&satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr,
+ &satosin(rt->rt_addr)->sin_addr.s_addr,
&satosin(dst)->sin_addr.s_addr,
ac->ac_enaddr);
else {
Index: netmpls/mpls_input.c
===================================================================
RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
retrieving revision 1.54
diff -u -p -r1.54 mpls_input.c
--- netmpls/mpls_input.c 4 Dec 2015 11:13:21 -0000 1.54
+++ netmpls/mpls_input.c 8 Jun 2016 14:19:49 -0000
@@ -374,7 +374,7 @@ mpls_do_error(struct mbuf *m, int type,
m_freem(m);
return (NULL);
}
- if (rt->rt_ifa->ifa_addr->sa_family == AF_INET)
+ if (rt->rt_addr->sa_family == AF_INET)
ia = ifatoia(rt->rt_ifa);
else {
/* XXX this needs fixing, if the MPLS is on an IP