aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-04-09 14:47:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:38 -0400
commitc5c2523893747f88a83376abad310c8ad13f7197 (patch)
tree58f1ab25ac9f7ca7460abbd24e9bab9c8683f6fd /net/ipv4
parent557922584d9c5b6b990bcfb2fec3134f0e73a05d (diff)
[XFRM]: Optimize MTU calculation
Replace the probing based MTU estimation, which usually takes 2-3 iterations to find a fitting value and may underestimate the MTU, by an exact calculation. Also fix underestimation of the XFRM trailer_len, which causes unnecessary reallocations. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/esp4.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index bdc65d8af181..a315d5d22764 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -272,32 +272,34 @@ out:
272 return -EINVAL; 272 return -EINVAL;
273} 273}
274 274
275static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) 275static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
276{ 276{
277 struct esp_data *esp = x->data; 277 struct esp_data *esp = x->data;
278 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); 278 u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
279 int enclen = 0; 279 u32 align = max_t(u32, blksize, esp->conf.padlen);
280 u32 rem;
281
282 mtu -= x->props.header_len + esp->auth.icv_trunc_len;
283 rem = mtu & (align - 1);
284 mtu &= ~(align - 1);
280 285
281 switch (x->props.mode) { 286 switch (x->props.mode) {
282 case XFRM_MODE_TUNNEL: 287 case XFRM_MODE_TUNNEL:
283 mtu = ALIGN(mtu +2, blksize);
284 break; 288 break;
285 default: 289 default:
286 case XFRM_MODE_TRANSPORT: 290 case XFRM_MODE_TRANSPORT:
287 /* The worst case */ 291 /* The worst case */
288 mtu = ALIGN(mtu + 2, 4) + blksize - 4; 292 mtu -= blksize - 4;
293 mtu += min_t(u32, blksize - 4, rem);
289 break; 294 break;
290 case XFRM_MODE_BEET: 295 case XFRM_MODE_BEET:
291 /* The worst case. */ 296 /* The worst case. */
292 enclen = IPV4_BEET_PHMAXLEN; 297 mtu -= IPV4_BEET_PHMAXLEN;
293 mtu = ALIGN(mtu + enclen + 2, blksize); 298 mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem);
294 break; 299 break;
295 } 300 }
296 301
297 if (esp->conf.padlen) 302 return mtu - 2;
298 mtu = ALIGN(mtu, esp->conf.padlen);
299
300 return mtu + x->props.header_len + esp->auth.icv_trunc_len - enclen;
301} 303}
302 304
303static void esp4_err(struct sk_buff *skb, u32 info) 305static void esp4_err(struct sk_buff *skb, u32 info)
@@ -340,6 +342,7 @@ static int esp_init_state(struct xfrm_state *x)
340{ 342{
341 struct esp_data *esp = NULL; 343 struct esp_data *esp = NULL;
342 struct crypto_blkcipher *tfm; 344 struct crypto_blkcipher *tfm;
345 u32 align;
343 346
344 /* null auth and encryption can have zero length keys */ 347 /* null auth and encryption can have zero length keys */
345 if (x->aalg) { 348 if (x->aalg) {
@@ -421,7 +424,10 @@ static int esp_init_state(struct xfrm_state *x)
421 } 424 }
422 } 425 }
423 x->data = esp; 426 x->data = esp;
424 x->props.trailer_len = esp4_get_max_size(x, 0) - x->props.header_len; 427 align = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
428 if (esp->conf.padlen)
429 align = max_t(u32, align, esp->conf.padlen);
430 x->props.trailer_len = align + 1 + esp->auth.icv_trunc_len;
425 return 0; 431 return 0;
426 432
427error: 433error:
@@ -438,7 +444,7 @@ static struct xfrm_type esp_type =
438 .proto = IPPROTO_ESP, 444 .proto = IPPROTO_ESP,
439 .init_state = esp_init_state, 445 .init_state = esp_init_state,
440 .destructor = esp_destroy, 446 .destructor = esp_destroy,
441 .get_max_size = esp4_get_max_size, 447 .get_mtu = esp4_get_mtu,
442 .input = esp_input, 448 .input = esp_input,
443 .output = esp_output 449 .output = esp_output
444}; 450};