Any reason you are not adding the free(9) sizes in rtrequest(), too?
OK florian@
On Wed, Jun 08, 2016 at 04:23:33PM +0200, Martin Pieuchot wrote:
> 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
>
--
I'm not entirely sure you are real.