Index | Thread | Search

From:
Claudio Jeker <claudio@openbsd.org>
Subject:
Re: route generation number for IPv6
To:
Alexander Bluhm <alexander.bluhm@gmx.net>
Cc:
tech@openbsd.org
Date:
Wed, 7 Feb 2024 11:19:20 +0100

Download raw body.

Thread
On Mon, Feb 05, 2024 at 08:21:38PM +0100, Alexander Bluhm wrote:
> On Sun, Feb 04, 2024 at 07:21:46PM +0100, Alexander Bluhm wrote:
> > Let's use the route generation number also for IPv6 and in_pcbrtentry().
> 
> New diff after fixing m88k build.  Prototype route6_cache() is now
> in netinet6/in6.h.
> 
> ok?

Lets get this in. OK claudio@
 
> bluhm
> 
> Index: net/route.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.c,v
> diff -u -p -r1.427 route.c
> --- net/route.c	31 Jan 2024 14:56:42 -0000	1.427
> +++ net/route.c	5 Feb 2024 19:12:07 -0000
> @@ -228,6 +228,34 @@ route_cache(struct route *ro, struct in_
>  	satosin(&ro->ro_dst)->sin_addr = addr;
>  }
>  
> +void
> +route6_cache(struct route_in6 *ro, const struct in6_addr *addr,
> +    u_int rtableid)
> +{
> +	u_long gen;
> +
> +	gen = atomic_load_long(&rtgeneration);
> +	membar_consumer();
> +
> +	if (rtisvalid(ro->ro_rt) &&
> +	    ro->ro_generation == gen &&
> +	    ro->ro_tableid == rtableid &&
> +	    ro->ro_dst.sin6_family == AF_INET6 &&
> +	    IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, addr)) {
> +		    return;
> +	}
> +
> +	rtfree(ro->ro_rt);
> +	ro->ro_rt = NULL;
> +	ro->ro_generation = gen;
> +	ro->ro_tableid = rtableid;
> +
> +	memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
> +	ro->ro_dst.sin6_family = AF_INET6;
> +	ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
> +	ro->ro_dst.sin6_addr = *addr;
> +}
> +
>  /*
>   * Returns 1 if the (cached) ``rt'' entry is still valid, 0 otherwise.
>   */
> Index: netinet/in_pcb.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v
> diff -u -p -r1.289 in_pcb.c
> --- netinet/in_pcb.c	2 Feb 2024 15:39:23 -0000	1.289
> +++ netinet/in_pcb.c	5 Feb 2024 19:12:07 -0000
> @@ -916,24 +916,10 @@ in_pcbrtentry(struct inpcb *inp)
>  
>  	ro = &inp->inp_route;
>  
> -	/* check if route is still valid */
> -	if (!rtisvalid(ro->ro_rt)) {
> -		rtfree(ro->ro_rt);
> -		ro->ro_rt = NULL;
> -	}
> -
> -	/*
> -	 * No route yet, so try to acquire one.
> -	 */
> +	if (inp->inp_faddr.s_addr == INADDR_ANY)
> +		return (NULL);
> +	route_cache(ro, inp->inp_faddr, inp->inp_rtableid);
>  	if (ro->ro_rt == NULL) {
> -		memset(ro, 0, sizeof(struct route));
> -
> -		if (inp->inp_faddr.s_addr == INADDR_ANY)
> -			return (NULL);
> -		ro->ro_dst.sa_family = AF_INET;
> -		ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
> -		satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
> -		ro->ro_tableid = inp->inp_rtableid;
>  		ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
>  		    &inp->inp_laddr.s_addr, ro->ro_tableid);
>  	}
> Index: netinet6/in6.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6.h,v
> diff -u -p -r1.113 in6.h
> --- netinet6/in6.h	31 Jan 2024 14:56:43 -0000	1.113
> +++ netinet6/in6.h	5 Feb 2024 19:12:07 -0000
> @@ -428,6 +428,8 @@ int	in6_mask2len(struct in6_addr *, u_ch
>  int	in6_nam2sin6(const struct mbuf *, struct sockaddr_in6 **);
>  int	in6_sa2sin6(struct sockaddr *, struct sockaddr_in6 **);
>  
> +void	route6_cache(struct route_in6 *, const struct in6_addr *, u_int);
> +
>  struct ip6_pktopts;
>  struct ip6_moptions;
>  
> Index: netinet6/in6_pcb.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_pcb.c,v
> diff -u -p -r1.134 in6_pcb.c
> --- netinet6/in6_pcb.c	31 Jan 2024 12:27:57 -0000	1.134
> +++ netinet6/in6_pcb.c	5 Feb 2024 19:12:07 -0000
> @@ -566,24 +566,10 @@ in6_pcbrtentry(struct inpcb *inp)
>  {
>  	struct route_in6 *ro = &inp->inp_route6;
>  
> -	/* check if route is still valid */
> -	if (!rtisvalid(ro->ro_rt)) {
> -		rtfree(ro->ro_rt);
> -		ro->ro_rt = NULL;
> -	}
> -
> -	/*
> -	 * No route yet, so try to acquire one.
> -	 */
> +	if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
> +		return (NULL);
> +	route6_cache(ro, &inp->inp_faddr6, inp->inp_rtableid);
>  	if (ro->ro_rt == NULL) {
> -		memset(ro, 0, sizeof(struct route_in6));
> -
> -		if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
> -			return (NULL);
> -		ro->ro_dst.sin6_family = AF_INET6;
> -		ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
> -		ro->ro_dst.sin6_addr = inp->inp_faddr6;
> -		ro->ro_tableid = inp->inp_rtableid;
>  		ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
>  		    &inp->inp_laddr6.s6_addr32[0], ro->ro_tableid);
>  	}
> Index: netinet6/in6_src.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_src.c,v
> diff -u -p -r1.91 in6_src.c
> --- netinet6/in6_src.c	9 Jan 2024 19:57:01 -0000	1.91
> +++ netinet6/in6_src.c	5 Feb 2024 19:12:07 -0000
> @@ -82,7 +82,7 @@
>  #include <netinet6/ip6_var.h>
>  #include <netinet6/nd6.h>
>  
> -int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
> +int in6_selectif(const struct in6_addr *, struct ip6_pktopts *,
>      struct ip6_moptions *, struct route_in6 *, struct ifnet **, u_int);
>  
>  /*
> @@ -118,7 +118,7 @@ in6_pcbselsrc(const struct in6_addr **in
>  		struct sockaddr_in6 sa6;
>  
>  		/* get the outgoing interface */
> -		error = in6_selectif(dstsock, opts, mopts, ro, &ifp, rtableid);
> +		error = in6_selectif(dst, opts, mopts, ro, &ifp, rtableid);
>  		if (error)
>  			return (error);
>  
> @@ -179,22 +179,8 @@ in6_pcbselsrc(const struct in6_addr **in
>  	 * If route is known or can be allocated now,
>  	 * our src addr is taken from the i/f, else punt.
>  	 */
> -	if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) ||
> -	    !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
> -		rtfree(ro->ro_rt);
> -		ro->ro_rt = NULL;
> -	}
> +	route6_cache(ro, dst, rtableid);
>  	if (ro->ro_rt == NULL) {
> -		struct sockaddr_in6 *sa6;
> -
> -		/* No route yet, so try to acquire one */
> -		bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
> -		ro->ro_tableid = rtableid;
> -		sa6 = &ro->ro_dst;
> -		sa6->sin6_family = AF_INET6;
> -		sa6->sin6_len = sizeof(struct sockaddr_in6);
> -		sa6->sin6_addr = *dst;
> -		sa6->sin6_scope_id = dstsock->sin6_scope_id;
>  		ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst),
>  		    RT_RESOLVE, ro->ro_tableid);
>  	}
> @@ -312,35 +298,17 @@ in6_selectsrc(const struct in6_addr **in
>  }
>  
>  struct rtentry *
> -in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
> +in6_selectroute(const struct in6_addr *dst, struct ip6_pktopts *opts,
>      struct route_in6 *ro, unsigned int rtableid)
>  {
> -	struct in6_addr *dst;
> -
> -	dst = &dstsock->sin6_addr;
> -
>  	/*
>  	 * Use a cached route if it exists and is valid, else try to allocate
>  	 * a new one.
>  	 */
>  	if (ro) {
> -		if (rtisvalid(ro->ro_rt))
> -			KASSERT(sin6tosa(&ro->ro_dst)->sa_family == AF_INET6);
> -		if (!rtisvalid(ro->ro_rt) ||
> -		    !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
> -			rtfree(ro->ro_rt);
> -			ro->ro_rt = NULL;
> -		}
> +		route6_cache(ro, dst, rtableid);
>  		if (ro->ro_rt == NULL) {
> -			struct sockaddr_in6 *sa6;
> -
>  			/* No route yet, so try to acquire one */
> -			bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
> -			ro->ro_tableid = rtableid;
> -			sa6 = &ro->ro_dst;
> -			*sa6 = *dstsock;
> -			sa6->sin6_scope_id = 0;
> -			ro->ro_tableid = rtableid;
>  			ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
>  			    NULL, ro->ro_tableid);
>  		}
> @@ -369,7 +337,7 @@ in6_selectroute(struct sockaddr_in6 *dst
>  }
>  
>  int
> -in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
> +in6_selectif(const struct in6_addr *dst, struct ip6_pktopts *opts,
>      struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
>      u_int rtableid)
>  {
> @@ -387,11 +355,11 @@ in6_selectif(struct sockaddr_in6 *dstsoc
>  	 * If the destination address is a multicast address and the outgoing
>  	 * interface for the address is specified by the caller, use it.
>  	 */
> -	if (IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) &&
> +	if (IN6_IS_ADDR_MULTICAST(dst) &&
>  	    mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL)
>  	    	return (0);
>  
> -	rt = in6_selectroute(dstsock, opts, ro, rtableid);
> +	rt = in6_selectroute(dst, opts, ro, rtableid);
>  	if (rt == NULL)
>  		return (EHOSTUNREACH);
>  
> Index: netinet6/ip6_forward.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v
> diff -u -p -r1.112 ip6_forward.c
> --- netinet6/ip6_forward.c	7 Jul 2023 08:05:02 -0000	1.112
> +++ netinet6/ip6_forward.c	5 Feb 2024 19:12:07 -0000
> @@ -85,7 +85,7 @@ void
>  ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
>  {
>  	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
> -	struct sockaddr_in6 *sin6;
> +	struct sockaddr *dst;
>  	struct route_in6 ro;
>  	struct ifnet *ifp = NULL;
>  	int error = 0, type = 0, code = 0, destmtu = 0;
> @@ -165,15 +165,12 @@ reroute:
>  	}
>  #endif /* IPSEC */
>  
> -	memset(&ro, 0, sizeof(ro));
> -	sin6 = &ro.ro_dst;
> -	sin6->sin6_family = AF_INET6;
> -	sin6->sin6_len = sizeof(*sin6);
> -	sin6->sin6_addr = ip6->ip6_dst;
> -
> +	ro.ro_rt = NULL;
> +	route6_cache(&ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
> +	dst = sin6tosa(&ro.ro_dst);
>  	if (!rtisvalid(rt)) {
>  		rtfree(rt);
> -		rt = rtalloc_mpath(sin6tosa(sin6), &ip6->ip6_src.s6_addr32[0],
> +		rt = rtalloc_mpath(dst, &ip6->ip6_src.s6_addr32[0],
>  		    m->m_pkthdr.ph_rtableid);
>  		if (rt == NULL) {
>  			ip6stat_inc(ip6s_noroute);
> @@ -185,6 +182,7 @@ reroute:
>  			goto out;
>  		}
>  	}
> +	ro.ro_rt = rt;
>  
>  	/*
>  	 * Scope check: if a packet can't be delivered to its destination
> @@ -226,8 +224,6 @@ reroute:
>  	 */
>  	if (tdb != NULL) {
>  		/* Callee frees mbuf */
> -		ro.ro_rt = rt;
> -		ro.ro_tableid = m->m_pkthdr.ph_rtableid;
>  		error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1);
>  		rt = ro.ro_rt;
>  		if (error)
> @@ -237,7 +233,7 @@ reroute:
>  #endif /* IPSEC */
>  
>  	if (rt->rt_flags & RTF_GATEWAY)
> -		sin6 = satosin6(rt->rt_gateway);
> +		dst = rt->rt_gateway;
>  
>  	/*
>  	 * If we are to forward the packet using the same interface
> @@ -319,7 +315,7 @@ reroute:
>  	}
>  #endif
>  
> -	error = if_output_tso(ifp, &m, sin6tosa(sin6), rt, ifp->if_mtu);
> +	error = if_output_tso(ifp, &m, dst, rt, ifp->if_mtu);
>  	if (error)
>  		ip6stat_inc(ip6s_cantforward);
>  	else if (m == NULL)
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
> diff -u -p -r1.284 ip6_output.c
> --- netinet6/ip6_output.c	31 Jan 2024 12:27:57 -0000	1.284
> +++ netinet6/ip6_output.c	5 Feb 2024 19:12:07 -0000
> @@ -169,7 +169,7 @@ ip6_output(struct mbuf *m, struct ip6_pk
>  	int hlen, tlen;
>  	struct route_in6 ip6route;
>  	struct rtentry *rt = NULL;
> -	struct sockaddr_in6 *dst, dstsock;
> +	struct sockaddr_in6 *dst;
>  	int error = 0;
>  	u_long mtu;
>  	int dontfrag;
> @@ -442,13 +442,7 @@ reroute:
>  	}
>  #endif /* IPSEC */
>  
> -	bzero(&dstsock, sizeof(dstsock));
> -	dstsock.sin6_family = AF_INET6;
> -	dstsock.sin6_addr = ip6->ip6_dst;
> -	dstsock.sin6_len = sizeof(dstsock);
> -	ro->ro_tableid = m->m_pkthdr.ph_rtableid;
> -
> -	if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
> +	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
>  		struct in6_pktinfo *pi = NULL;
>  
>  		/*
> @@ -463,7 +457,8 @@ reroute:
>  	}
>  
>  	if (ifp == NULL) {
> -		rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
> +		rt = in6_selectroute(&ip6->ip6_dst, opt, ro,
> +		    m->m_pkthdr.ph_rtableid);
>  		if (rt == NULL) {
>  			ip6stat_inc(ip6s_noroute);
>  			error = EHOSTUNREACH;
> @@ -485,7 +480,7 @@ reroute:
>  			goto bad;
>  		}
>  	} else {
> -		*dst = dstsock;
> +		route6_cache(ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
>  	}
>  
>  	if (rt && (rt->rt_flags & RTF_GATEWAY) &&
> Index: netinet6/ip6_var.h
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v
> diff -u -p -r1.110 ip6_var.h
> --- netinet6/ip6_var.h	3 Feb 2024 22:50:09 -0000	1.110
> +++ netinet6/ip6_var.h	5 Feb 2024 19:12:07 -0000
> @@ -369,7 +369,7 @@ int	in6_pcbselsrc(const struct in6_addr 
>  	    struct inpcb *, struct ip6_pktopts *);
>  int	in6_selectsrc(const struct in6_addr **, struct sockaddr_in6 *,
>  	    struct ip6_moptions *, unsigned int);
> -struct rtentry *in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
> +struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *,
>  	    struct route_in6 *, unsigned int rtableid);
>  
>  u_int32_t ip6_randomflowlabel(void);

-- 
:wq Claudio