diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2022-08-15 16:15:38 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2022-08-15 16:15:38 +0000 |
commit | 600447a725fb2bfd80a6686ee8a2184b4ee9a62d (patch) | |
tree | 537736cc7760a91fa228883d58b8f5c761978c8d /sys | |
parent | ea0b5be0419cbd303aec1104be1567f3251ad21d (diff) |
Run IPv6 hop-by-hop options processing in parallel. The ip6_hbhchcheck()
code is MP safe and moves from ip6_local() to ip6_ours(). If there
are any options, store the chain offset and next protocol in a mbuf
tag. When dequeuing without tag, it is a regular IPv6 header. As
mbuf tags degrade performance, use them only if a hop-by-hop header
is present. Such packets are rare and pf drops them by default.
OK mvs@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_input.c | 12 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 58 | ||||
-rw-r--r-- | sys/sys/mbuf.h | 3 |
3 files changed, 63 insertions, 10 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 4ff68820c80..1a4e2d8d90e 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.378 2022/08/12 14:49:15 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.379 2022/08/15 16:15:36 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -560,11 +560,13 @@ ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) int ip_local(struct mbuf **mp, int *offp, int nxt, int af) { - struct ip *ip; + if (*offp == 0) { + struct ip *ip; - ip = mtod(*mp, struct ip *); - *offp = ip->ip_hl << 2; - nxt = ip->ip_p; + ip = mtod(*mp, struct ip *); + *offp = ip->ip_hl << 2; + nxt = ip->ip_p; + } /* Check whether we are already in a IPv4/IPv6 local deliver loop. */ if (af == AF_UNSPEC) diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 045fb00206d..6e70de63143 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_input.c,v 1.252 2022/08/12 14:49:15 bluhm Exp $ */ +/* $OpenBSD: ip6_input.c,v 1.253 2022/08/15 16:15:37 bluhm Exp $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ /* @@ -167,6 +167,11 @@ ip6_init(void) #endif } +struct ip6_offnxt { + int ion_off; + int ion_nxt; +}; + /* * Enqueue packet for local delivery. Queuing is used as a boundary * between the network layer (input/forward path) running with @@ -175,10 +180,37 @@ ip6_init(void) int ip6_ours(struct mbuf **mp, int *offp, int nxt, int af) { + /* ip6_hbhchcheck() may be run before, then off and nxt are set */ + if (*offp == 0) { + nxt = ip6_hbhchcheck(mp, offp, NULL); + if (nxt == IPPROTO_DONE) + return IPPROTO_DONE; + } + /* We are already in a IPv4/IPv6 local deliver loop. */ if (af != AF_UNSPEC) return ip6_local(mp, offp, nxt, af); + /* save values for later, use after dequeue */ + if (*offp != sizeof(struct ip6_hdr)) { + struct m_tag *mtag; + struct ip6_offnxt *ion; + + /* mbuf tags are expensive, but only used for header options */ + mtag = m_tag_get(PACKET_TAG_IP6_OFFNXT, sizeof(*ion), + M_NOWAIT); + if (mtag == NULL) { + ip6stat_inc(ip6s_idropped); + m_freemp(mp); + return IPPROTO_DONE; + } + ion = (struct ip6_offnxt *)(mtag + 1); + ion->ion_off = *offp; + ion->ion_nxt = nxt; + + m_tag_prepend(*mp, mtag); + } + niq_enqueue(&ip6intrq, *mp); *mp = NULL; return IPPROTO_DONE; @@ -584,9 +616,27 @@ ip6_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) int ip6_local(struct mbuf **mp, int *offp, int nxt, int af) { - nxt = ip6_hbhchcheck(mp, offp, NULL); - if (nxt == IPPROTO_DONE) - return IPPROTO_DONE; + if (*offp == 0) { + struct m_tag *mtag; + + mtag = m_tag_find(*mp, PACKET_TAG_IP6_OFFNXT, NULL); + if (mtag != NULL) { + struct ip6_offnxt *ion; + + ion = (struct ip6_offnxt *)(mtag + 1); + *offp = ion->ion_off; + nxt = ion->ion_nxt; + + m_tag_delete(*mp, mtag); + } else { + struct ip6_hdr *ip6; + + ip6 = mtod(*mp, struct ip6_hdr *); + *offp = sizeof(struct ip6_hdr); + nxt = ip6->ip6_nxt; + + } + } /* Check whether we are already in a IPv4/IPv6 local deliver loop. */ if (af == AF_UNSPEC) diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 72655624edb..f8eae7a4e50 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mbuf.h,v 1.254 2022/02/14 04:33:18 dlg Exp $ */ +/* $OpenBSD: mbuf.h,v 1.255 2022/08/15 16:15:37 bluhm Exp $ */ /* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */ /* @@ -479,6 +479,7 @@ struct m_tag *m_tag_next(struct mbuf *, struct m_tag *); #define PACKET_TAG_SRCROUTE 0x1000 /* IPv4 source routing options */ #define PACKET_TAG_TUNNEL 0x2000 /* Tunnel endpoint address */ #define PACKET_TAG_CARP_BAL_IP 0x4000 /* carp(4) ip balanced marker */ +#define PACKET_TAG_IP6_OFFNXT 0x8000 /* IPv6 offset and next proto */ #define MTAG_BITS \ ("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_FLOWINFO" \ |