summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2022-08-15 16:15:38 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2022-08-15 16:15:38 +0000
commit600447a725fb2bfd80a6686ee8a2184b4ee9a62d (patch)
tree537736cc7760a91fa228883d58b8f5c761978c8d /sys
parentea0b5be0419cbd303aec1104be1567f3251ad21d (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.c12
-rw-r--r--sys/netinet6/ip6_input.c58
-rw-r--r--sys/sys/mbuf.h3
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" \