aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 00:44:55 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:53:50 -0500
commitb2aa5e9d43a38dcdfa0878ed750cf32f98460278 (patch)
treee00544bd1aa0ab6e2ccb0696e1a89cd4900130e9 /net/xfrm
parent716062fd4c2f88a33ab409f62a1e7397ad0a7e33 (diff)
[IPSEC]: Store xfrm states in security path directly
As it is xfrm_input first collects a list of xfrm states on the stack before storing them in the packet's security path just before it returns. For async crypto, this construction presents an obstacle since we may need to leave the loop after each transform. In fact, it's much easier to just skip the stack completely and always store to the security path. This is proven by the fact that this patch actually shrinks the code. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c42
1 files changed, 15 insertions, 27 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index b980095be935..587f3474ed3d 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -100,19 +100,29 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
100{ 100{
101 int err; 101 int err;
102 __be32 seq; 102 __be32 seq;
103 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
104 struct xfrm_state *x; 103 struct xfrm_state *x;
105 int xfrm_nr = 0;
106 int decaps = 0; 104 int decaps = 0;
107 unsigned int nhoff = XFRM_SPI_SKB_CB(skb)->nhoff; 105 unsigned int nhoff = XFRM_SPI_SKB_CB(skb)->nhoff;
108 unsigned int daddroff = XFRM_SPI_SKB_CB(skb)->daddroff; 106 unsigned int daddroff = XFRM_SPI_SKB_CB(skb)->daddroff;
109 107
108 /* Allocate new secpath or COW existing one. */
109 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
110 struct sec_path *sp;
111
112 sp = secpath_dup(skb->sp);
113 if (!sp)
114 goto drop;
115 if (skb->sp)
116 secpath_put(skb->sp);
117 skb->sp = sp;
118 }
119
110 seq = 0; 120 seq = 0;
111 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) 121 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
112 goto drop; 122 goto drop;
113 123
114 do { 124 do {
115 if (xfrm_nr == XFRM_MAX_DEPTH) 125 if (skb->sp->len == XFRM_MAX_DEPTH)
116 goto drop; 126 goto drop;
117 127
118 x = xfrm_state_lookup((xfrm_address_t *) 128 x = xfrm_state_lookup((xfrm_address_t *)
@@ -121,6 +131,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
121 if (x == NULL) 131 if (x == NULL)
122 goto drop; 132 goto drop;
123 133
134 skb->sp->xvec[skb->sp->len++] = x;
135
124 spin_lock(&x->lock); 136 spin_lock(&x->lock);
125 if (unlikely(x->km.state != XFRM_STATE_VALID)) 137 if (unlikely(x->km.state != XFRM_STATE_VALID))
126 goto drop_unlock; 138 goto drop_unlock;
@@ -151,8 +163,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
151 163
152 spin_unlock(&x->lock); 164 spin_unlock(&x->lock);
153 165
154 xfrm_vec[xfrm_nr++] = x;
155
156 if (x->inner_mode->input(x, skb)) 166 if (x->inner_mode->input(x, skb))
157 goto drop; 167 goto drop;
158 168
@@ -166,24 +176,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
166 goto drop; 176 goto drop;
167 } while (!err); 177 } while (!err);
168 178
169 /* Allocate new secpath or COW existing one. */
170
171 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
172 struct sec_path *sp;
173 sp = secpath_dup(skb->sp);
174 if (!sp)
175 goto drop;
176 if (skb->sp)
177 secpath_put(skb->sp);
178 skb->sp = sp;
179 }
180 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
181 goto drop;
182
183 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
184 xfrm_nr * sizeof(xfrm_vec[0]));
185 skb->sp->len += xfrm_nr;
186
187 nf_reset(skb); 179 nf_reset(skb);
188 180
189 if (decaps) { 181 if (decaps) {
@@ -197,11 +189,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
197 189
198drop_unlock: 190drop_unlock:
199 spin_unlock(&x->lock); 191 spin_unlock(&x->lock);
200 xfrm_state_put(x);
201drop: 192drop:
202 while (--xfrm_nr >= 0)
203 xfrm_state_put(xfrm_vec[xfrm_nr]);
204
205 kfree_skb(skb); 193 kfree_skb(skb);
206 return 0; 194 return 0;
207} 195}