Subject: ipsec.c patch to reduce kernel stack usage
To: None <itojun@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-net
Date: 06/27/2002 19:57:42
----Next_Part(Thu_Jun_27_19:57:42_2002_707)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
hi.
is attached patch ok?
(in order to reduce kernel stack usage for ipsec output path.
ipv6 part isn't tested.)
---
YAMAMOTO Takashi<yamt@mwd.biglobe.ne.jp>
----Next_Part(Thu_Jun_27_19:57:42_2002_707)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="ipsec.c.diff"
Index: ipsec.c
===================================================================
RCS file: /cvs/cvsroot/syssrc/sys/netinet6/ipsec.c,v
retrieving revision 1.61
diff -u -p -r1.61 ipsec.c
--- ipsec.c 2002/06/22 12:27:09 1.61
+++ ipsec.c 2002/06/27 10:51:00
@@ -161,6 +161,14 @@ static int ipsec6_encapsulate __P((struc
static struct mbuf *ipsec_addaux __P((struct mbuf *));
static struct mbuf *ipsec_findaux __P((struct mbuf *));
static void ipsec_optaux __P((struct mbuf *, struct mbuf *));
+#ifdef INET
+static int ipsec4_checksa __P((struct ipsecrequest *,
+ struct ipsec_output_state *));
+#endif
+#ifdef INET6
+static int ipsec6_checksa __P((struct ipsecrequest *,
+ struct ipsec_output_state *, int));
+#endif
/*
* try to validate and use cached policy on a pcb.
@@ -2489,6 +2497,39 @@ ipsec_dumpmbuf(m)
}
#ifdef INET
+static int
+ipsec4_checksa(isr, state)
+ struct ipsecrequest *isr;
+ struct ipsec_output_state *state;
+{
+ struct ip *ip;
+ struct secasindex saidx;
+ struct sockaddr_in *sin;
+
+ /* make SA index for search proper SA */
+ ip = mtod(state->m, struct ip *);
+ bcopy(&isr->saidx, &saidx, sizeof(saidx));
+ saidx.mode = isr->saidx.mode;
+ saidx.reqid = isr->saidx.reqid;
+ sin = (struct sockaddr_in *)&saidx.src;
+ if (sin->sin_len == 0) {
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_port = IPSEC_PORT_ANY;
+ bcopy(&ip->ip_src, &sin->sin_addr,
+ sizeof(sin->sin_addr));
+ }
+ sin = (struct sockaddr_in *)&saidx.dst;
+ if (sin->sin_len == 0) {
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_port = IPSEC_PORT_ANY;
+ bcopy(&ip->ip_dst, &sin->sin_addr,
+ sizeof(sin->sin_addr));
+ }
+
+ return key_checkrequest(isr, &saidx);
+}
/*
* IPsec output logic for IPv4.
*/
@@ -2500,11 +2541,9 @@ ipsec4_output(state, sp, flags)
{
struct ip *ip = NULL;
struct ipsecrequest *isr = NULL;
- struct secasindex saidx;
int s;
int error;
struct sockaddr_in *dst4;
- struct sockaddr_in *sin;
if (!state)
panic("state == NULL in ipsec4_output");
@@ -2532,30 +2571,8 @@ ipsec4_output(state, sp, flags)
&& (flags & IP_FORWARDING))
continue;
#endif
-
- /* make SA index for search proper SA */
- ip = mtod(state->m, struct ip *);
- bcopy(&isr->saidx, &saidx, sizeof(saidx));
- saidx.mode = isr->saidx.mode;
- saidx.reqid = isr->saidx.reqid;
- sin = (struct sockaddr_in *)&saidx.src;
- if (sin->sin_len == 0) {
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = IPSEC_PORT_ANY;
- bcopy(&ip->ip_src, &sin->sin_addr,
- sizeof(sin->sin_addr));
- }
- sin = (struct sockaddr_in *)&saidx.dst;
- if (sin->sin_len == 0) {
- sin->sin_len = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = IPSEC_PORT_ANY;
- bcopy(&ip->ip_dst, &sin->sin_addr,
- sizeof(sin->sin_addr));
- }
-
- if ((error = key_checkrequest(isr, &saidx)) != 0) {
+ error = ipsec4_checksa(isr, state);
+ if (error != 0) {
/*
* IPsec processing is required, but no SA found.
* I assume that key_acquire() had been called
@@ -2715,6 +2732,53 @@ bad:
#endif
#ifdef INET6
+static int
+ipsec6_checksa(isr, state, tunnel)
+ struct ipsecrequest *isr;
+ struct ipsec_output_state *state;
+ int tunnel;
+{
+ struct ip6_hdr *ip6;
+ struct secasindex saidx;
+ struct sockaddr_in6 *sin6;
+
+ if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
+ KASSERT(tunnel != 0);
+ return key_checkrequest(isr, &isr->saidx);
+ }
+
+ /* make SA index for search proper SA */
+ ip6 = mtod(state->m, struct ip6_hdr *);
+ bcopy(&isr->saidx, &saidx, sizeof(saidx));
+ sin6 = (struct sockaddr_in6 *)&saidx.src;
+ if (sin6->sin6_len == 0 || tunnel) {
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = IPSEC_PORT_ANY;
+ bcopy(&ip6->ip6_src, &sin6->sin6_addr,
+ sizeof(ip6->ip6_src));
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
+ /* fix scope id for comparing SPD */
+ sin6->sin6_addr.s6_addr16[1] = 0;
+ sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
+ }
+ }
+ sin6 = (struct sockaddr_in6 *)&saidx.dst;
+ if (sin6->sin6_len == 0 || tunnel) {
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = IPSEC_PORT_ANY;
+ bcopy(&ip6->ip6_dst, &sin6->sin6_addr,
+ sizeof(ip6->ip6_dst));
+ if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
+ /* fix scope id for comparing SPD */
+ sin6->sin6_addr.s6_addr16[1] = 0;
+ sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
+ }
+ }
+
+ return key_checkrequest(isr, &saidx);
+}
/*
* IPsec output logic for IPv6, transport mode.
*/
@@ -2729,10 +2793,8 @@ ipsec6_output_trans(state, nexthdrp, mpr
{
struct ip6_hdr *ip6;
struct ipsecrequest *isr = NULL;
- struct secasindex saidx;
int error = 0;
int plen;
- struct sockaddr_in6 *sin6;
if (!state)
panic("state == NULL in ipsec6_output_trans");
@@ -2757,40 +2819,9 @@ ipsec6_output_trans(state, nexthdrp, mpr
/* the rest will be handled by ipsec6_output_tunnel() */
break;
}
-
- /* make SA index for search proper SA */
- ip6 = mtod(state->m, struct ip6_hdr *);
- bcopy(&isr->saidx, &saidx, sizeof(saidx));
- saidx.mode = isr->saidx.mode;
- saidx.reqid = isr->saidx.reqid;
- sin6 = (struct sockaddr_in6 *)&saidx.src;
- if (sin6->sin6_len == 0) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- bcopy(&ip6->ip6_src, &sin6->sin6_addr,
- sizeof(ip6->ip6_src));
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
- /* fix scope id for comparing SPD */
- sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
- }
- }
- sin6 = (struct sockaddr_in6 *)&saidx.dst;
- if (sin6->sin6_len == 0) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- bcopy(&ip6->ip6_dst, &sin6->sin6_addr,
- sizeof(ip6->ip6_dst));
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
- /* fix scope id for comparing SPD */
- sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
- }
- }
- if (key_checkrequest(isr, &saidx) == ENOENT) {
+ error = ipsec6_checksa(isr, state, 0);
+ if (error == ENOENT) {
/*
* IPsec processing is required, but no SA found.
* I assume that key_acquire() had been called
@@ -2799,7 +2830,6 @@ ipsec6_output_trans(state, nexthdrp, mpr
* upper layer to retransmit the packet.
*/
ipsec6stat.out_nosa++;
- error = ENOENT;
/*
* Notify the fact that the packet is discarded
@@ -2904,7 +2934,6 @@ ipsec6_output_tunnel(state, sp, flags)
{
struct ip6_hdr *ip6;
struct ipsecrequest *isr = NULL;
- struct secasindex saidx;
int error = 0;
int plen;
struct sockaddr_in6* dst6;
@@ -2931,48 +2960,8 @@ ipsec6_output_tunnel(state, sp, flags)
}
for (/* already initialized */; isr; isr = isr->next) {
- if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
- /* When tunnel mode, SA peers must be specified. */
- bcopy(&isr->saidx, &saidx, sizeof(saidx));
- } else {
- /* make SA index to look for a proper SA */
- struct sockaddr_in6 *sin6;
-
- bzero(&saidx, sizeof(saidx));
- saidx.proto = isr->saidx.proto;
- saidx.mode = isr->saidx.mode;
- saidx.reqid = isr->saidx.reqid;
-
- ip6 = mtod(state->m, struct ip6_hdr *);
- sin6 = (struct sockaddr_in6 *)&saidx.src;
- if (sin6->sin6_len == 0) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- bcopy(&ip6->ip6_src, &sin6->sin6_addr,
- sizeof(ip6->ip6_src));
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
- /* fix scope id for comparing SPD */
- sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
- }
- }
- sin6 = (struct sockaddr_in6 *)&saidx.dst;
- if (sin6->sin6_len == 0) {
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = IPSEC_PORT_ANY;
- bcopy(&ip6->ip6_dst, &sin6->sin6_addr,
- sizeof(ip6->ip6_dst));
- if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
- /* fix scope id for comparing SPD */
- sin6->sin6_addr.s6_addr16[1] = 0;
- sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
- }
- }
- }
-
- if (key_checkrequest(isr, &saidx) == ENOENT) {
+ error = ipsec6_checksa(isr, state, 1);
+ if (error == ENOENT) {
/*
* IPsec processing is required, but no SA found.
* I assume that key_acquire() had been called
----Next_Part(Thu_Jun_27_19:57:42_2002_707)----