From: bluhm Date: Mon, 15 Aug 2022 16:15:36 +0000 (+0000) Subject: Run IPv6 hop-by-hop options processing in parallel. The ip6_hbhchcheck() X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=0b448d840ed3c3573bbfc2437300f0f5e6fb68c4;p=openbsd 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@ --- 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" \