Download raw body.
use struct route in ip input
Hi,
Instaed of passing a struct rtentry from ip_input() to ip_forward()
and then embed it into a struct route for ip_output(), start with
struct route and pass it along. Then the route cache is used
consistently. Also the route cache hit and missed counters should
reflect reality with this diff.
There is a small difference in the code. in_ouraddr() checks for
NULL and not rtisvalid(). Previous discussion showed that the route
UP flag should only be considered for multipath routing. Otherwise
it does not mean anything. Especially the local and broadcast check
should not be affected by interface link status.
When doing cache lookups route must be valid, but after rtalloc_mpath()
lookup, we use any route we get.
ok?
bluhm
Index: netinet/ip_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
diff -u -p -r1.391 ip_input.c
--- netinet/ip_input.c 28 Feb 2024 10:57:20 -0000 1.391
+++ netinet/ip_input.c 9 Apr 2024 12:19:44 -0000
@@ -138,7 +138,7 @@ extern struct niqueue arpinq;
int ip_ours(struct mbuf **, int *, int, int);
int ip_dooptions(struct mbuf *, struct ifnet *);
-int in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **);
+int in_ouraddr(struct mbuf *, struct ifnet *, struct route *);
int ip_fragcheck(struct mbuf **, int *);
struct mbuf * ip_reass(struct ipqent *, struct ipq *);
@@ -387,9 +387,9 @@ bad:
int
ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
{
- struct mbuf *m;
- struct rtentry *rt = NULL;
- struct ip *ip;
+ struct route ro;
+ struct mbuf *m;
+ struct ip *ip;
int hlen;
#if NPF > 0
struct in_addr odst;
@@ -398,6 +398,7 @@ ip_input_if(struct mbuf **mp, int *offp,
KASSERT(*offp == 0);
+ ro.ro_rt = NULL;
ipstat_inc(ips_total);
m = *mp = ipv4_check(ifp, *mp);
if (m == NULL)
@@ -445,7 +446,7 @@ ip_input_if(struct mbuf **mp, int *offp,
goto out;
}
- switch(in_ouraddr(m, ifp, &rt)) {
+ switch(in_ouraddr(m, ifp, &ro)) {
case 2:
goto bad;
case 1:
@@ -547,14 +548,14 @@ ip_input_if(struct mbuf **mp, int *offp,
}
#endif /* IPSEC */
- ip_forward(m, ifp, rt, pfrdr);
+ ip_forward(m, ifp, &ro, pfrdr);
*mp = NULL;
return IPPROTO_DONE;
bad:
nxt = IPPROTO_DONE;
m_freemp(mp);
out:
- rtfree(rt);
+ rtfree(ro.ro_rt);
return nxt;
}
@@ -751,11 +752,10 @@ ip_deliver(struct mbuf **mp, int *offp,
#undef IPSTAT_INC
int
-in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt)
+in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct route *ro)
{
struct rtentry *rt;
struct ip *ip;
- struct sockaddr_in sin;
int match = 0;
#if NPF > 0
@@ -772,13 +772,8 @@ in_ouraddr(struct mbuf *m, struct ifnet
ip = mtod(m, struct ip *);
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr = ip->ip_dst;
- rt = rtalloc_mpath(sintosa(&sin), &ip->ip_src.s_addr,
- m->m_pkthdr.ph_rtableid);
- if (rtisvalid(rt)) {
+ rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid);
+ if (rt != NULL) {
if (ISSET(rt->rt_flags, RTF_LOCAL))
match = 1;
@@ -794,7 +789,6 @@ in_ouraddr(struct mbuf *m, struct ifnet
m->m_flags |= M_BCAST;
}
}
- *prt = rt;
if (!match) {
struct ifaddr *ifa;
@@ -1473,11 +1467,12 @@ const u_char inetctlerrmap[PRC_NCMDS] =
* via a source route.
*/
void
-ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt)
+ip_forward(struct mbuf *m, struct ifnet *ifp, struct route *ro, int srcrt)
{
struct mbuf mfake, *mcopy;
struct ip *ip = mtod(m, struct ip *);
- struct route ro;
+ struct route iproute;
+ struct rtentry *rt;
int error = 0, type = 0, code = 0, destmtu = 0, fake = 0, len;
u_int32_t dest;
@@ -1492,19 +1487,16 @@ ip_forward(struct mbuf *m, struct ifnet
goto done;
}
- ro.ro_rt = NULL;
- route_cache(&ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid);
- if (!rtisvalid(rt)) {
- rtfree(rt);
- rt = rtalloc_mpath(&ro.ro_dstsa, &ip->ip_src.s_addr,
- m->m_pkthdr.ph_rtableid);
- if (rt == NULL) {
- ipstat_inc(ips_noroute);
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
- return;
- }
+ if (ro == NULL) {
+ ro = &iproute;
+ ro->ro_rt = NULL;
+ }
+ rt = route_mpath(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid);
+ if (rt == NULL) {
+ ipstat_inc(ips_noroute);
+ icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
+ goto done;
}
- ro.ro_rt = rt;
/*
* Save at most 68 bytes of the packet in case
@@ -1555,10 +1547,10 @@ ip_forward(struct mbuf *m, struct ifnet
}
}
- error = ip_output(m, NULL, &ro,
+ error = ip_output(m, NULL, ro,
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
NULL, NULL, 0);
- rt = ro.ro_rt;
+ rt = ro->ro_rt;
if (error)
ipstat_inc(ips_cantforward);
else {
@@ -1626,9 +1618,10 @@ ip_forward(struct mbuf *m, struct ifnet
icmp_error(mcopy, type, code, dest, destmtu);
done:
+ if (ro == &iproute)
+ rtfree(ro->ro_rt);
if (fake)
m_tag_delete_chain(&mfake);
- rtfree(rt);
}
int
Index: netinet/ip_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
diff -u -p -r1.114 ip_var.h
--- netinet/ip_var.h 5 Mar 2024 09:45:13 -0000 1.114
+++ netinet/ip_var.h 9 Apr 2024 12:19:44 -0000
@@ -255,7 +255,7 @@ void ip_savecontrol(struct inpcb *, str
struct mbuf *);
int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *);
int ip_deliver(struct mbuf **, int *, int, int);
-void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int);
+void ip_forward(struct mbuf *, struct ifnet *, struct route *, int);
int rip_ctloutput(int, struct socket *, int, int, struct mbuf *);
void rip_init(void);
int rip_input(struct mbuf **, int *, int, int);
Index: netinet6/ip6_forward.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_forward.c,v
diff -u -p -r1.116 ip6_forward.c
--- netinet6/ip6_forward.c 28 Feb 2024 10:57:20 -0000 1.116
+++ netinet6/ip6_forward.c 9 Apr 2024 12:19:44 -0000
@@ -82,11 +82,12 @@
*/
void
-ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
+ip6_forward(struct mbuf *m, struct route *ro, int srcrt)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
+ struct route iproute;
+ struct rtentry *rt;
struct sockaddr *dst;
- struct route ro;
struct ifnet *ifp = NULL;
int error = 0, type = 0, code = 0, destmtu = 0;
struct mbuf *mcopy;
@@ -165,25 +166,22 @@ reroute:
}
#endif /* IPSEC */
- ro.ro_rt = NULL;
- route6_cache(&ro, &ip6->ip6_dst, &ip6->ip6_src,
+ if (ro == NULL) {
+ ro = &iproute;
+ ro->ro_rt = NULL;
+ }
+ rt = route6_mpath(ro, &ip6->ip6_dst, &ip6->ip6_src,
m->m_pkthdr.ph_rtableid);
- dst = &ro.ro_dstsa;
- if (!rtisvalid(rt)) {
- rtfree(rt);
- rt = rtalloc_mpath(dst, &ip6->ip6_src.s6_addr32[0],
- m->m_pkthdr.ph_rtableid);
- if (rt == NULL) {
- ip6stat_inc(ip6s_noroute);
- if (mcopy != NULL) {
- icmp6_error(mcopy, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_NOROUTE, 0);
- }
- m_freem(m);
- goto done;
+ if (rt == NULL) {
+ ip6stat_inc(ip6s_noroute);
+ if (mcopy != NULL) {
+ icmp6_error(mcopy, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_NOROUTE, 0);
}
+ m_freem(m);
+ goto done;
}
- ro.ro_rt = rt;
+ dst = &ro->ro_dstsa;
/*
* Scope check: if a packet can't be delivered to its destination
@@ -225,8 +223,8 @@ reroute:
*/
if (tdb != NULL) {
/* Callee frees mbuf */
- error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1);
- rt = ro.ro_rt;
+ error = ip6_output_ipsec_send(tdb, m, ro, 0, 1);
+ rt = ro->ro_rt;
if (error)
goto senderr;
goto freecopy;
@@ -254,7 +252,7 @@ reroute:
ip6_sendredirects &&
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
if ((ifp->if_flags & IFF_POINTOPOINT) &&
- nd6_is_addr_neighbor(&ro.ro_dstsin6, ifp)) {
+ nd6_is_addr_neighbor(&ro->ro_dstsin6, ifp)) {
/*
* If the incoming interface is equal to the outgoing
* one, the link attached to the interface is
@@ -308,8 +306,9 @@ reroute:
/* tag as generated to skip over pf_test on rerun */
m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
srcrt = 1;
- rtfree(rt);
- rt = NULL;
+ if (ro == &iproute)
+ rtfree(ro->ro_rt);
+ ro = NULL;
if_put(ifp);
ifp = NULL;
goto reroute;
@@ -388,7 +387,8 @@ senderr:
freecopy:
m_freem(mcopy);
done:
- rtfree(rt);
+ if (ro == &iproute)
+ rtfree(ro->ro_rt);
if_put(ifp);
#ifdef IPSEC
tdb_unref(tdb);
Index: netinet6/ip6_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
diff -u -p -r1.259 ip6_input.c
--- netinet6/ip6_input.c 28 Feb 2024 10:57:20 -0000 1.259
+++ netinet6/ip6_input.c 9 Apr 2024 12:19:44 -0000
@@ -357,10 +357,10 @@ bad:
int
ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp)
{
+ struct route ro;
struct mbuf *m;
struct ip6_hdr *ip6;
- struct sockaddr_in6 sin6;
- struct rtentry *rt = NULL;
+ struct rtentry *rt;
int ours = 0;
u_int16_t src_scope, dst_scope;
#if NPF > 0
@@ -370,8 +370,8 @@ ip6_input_if(struct mbuf **mp, int *offp
KASSERT(*offp == 0);
+ ro.ro_rt = NULL;
ip6stat_inc(ip6s_total);
-
m = *mp = ipv6_check(ifp, *mp);
if (m == NULL)
goto bad;
@@ -517,18 +517,14 @@ ip6_input_if(struct mbuf **mp, int *offp
/*
* Unicast check
*/
- memset(&sin6, 0, sizeof(struct sockaddr_in6));
- sin6.sin6_len = sizeof(struct sockaddr_in6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = ip6->ip6_dst;
- rt = rtalloc_mpath(sin6tosa(&sin6), &ip6->ip6_src.s6_addr32[0],
+ rt = route6_mpath(&ro, &ip6->ip6_dst, &ip6->ip6_src,
m->m_pkthdr.ph_rtableid);
/*
* Accept the packet if the route to the destination is marked
* as local.
*/
- if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL)) {
+ if (rt != NULL && ISSET(rt->rt_flags, RTF_LOCAL)) {
struct in6_ifaddr *ia6 = ifatoia6(rt->rt_ifa);
if (ip6_forwarding == 0 && rt->rt_ifidx != ifp->if_index &&
@@ -618,14 +614,14 @@ ip6_input_if(struct mbuf **mp, int *offp
}
#endif /* IPSEC */
- ip6_forward(m, rt, pfrdr);
+ ip6_forward(m, &ro, pfrdr);
*mp = NULL;
return IPPROTO_DONE;
bad:
nxt = IPPROTO_DONE;
m_freemp(mp);
out:
- rtfree(rt);
+ rtfree(ro.ro_rt);
return nxt;
}
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
diff -u -p -r1.289 ip6_output.c
--- netinet6/ip6_output.c 9 Apr 2024 11:05:05 -0000 1.289
+++ netinet6/ip6_output.c 9 Apr 2024 12:19:44 -0000
@@ -391,7 +391,7 @@ reroute:
/* initialize cached route */
if (ro == NULL) {
ro = &iproute;
- bzero((caddr_t)ro, sizeof(*ro));
+ ro->ro_rt = NULL;
}
ro_pmtu = ro;
if (opt && opt->ip6po_rthdr)
Index: netinet6/ip6_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v
diff -u -p -r1.114 ip6_var.h
--- netinet6/ip6_var.h 14 Feb 2024 13:18:21 -0000 1.114
+++ netinet6/ip6_var.h 9 Apr 2024 12:19:44 -0000
@@ -320,7 +320,7 @@ int ip6_process_hopopts(struct mbuf **,
void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **);
int ip6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
-void ip6_forward(struct mbuf *, struct rtentry *, int);
+void ip6_forward(struct mbuf *, struct route *, int);
void ip6_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in6 *);
int ip6_output(struct mbuf *, struct ip6_pktopts *, struct route *, int,
use struct route in ip input