diff options
author | Patrick McHardy <kaber@trash.net> | 2007-04-09 14:47:18 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:28:38 -0400 |
commit | c5c2523893747f88a83376abad310c8ad13f7197 (patch) | |
tree | 58f1ab25ac9f7ca7460abbd24e9bab9c8683f6fd /net/ipv4/esp4.c | |
parent | 557922584d9c5b6b990bcfb2fec3134f0e73a05d (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/esp4.c')
-rw-r--r-- | net/ipv4/esp4.c | 30 |
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 | ||
275 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | 275 | static 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 | ||
303 | static void esp4_err(struct sk_buff *skb, u32 info) | 305 | static 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 | ||
427 | error: | 433 | error: |
@@ -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 | }; |