diff options
author | Patrick McHardy <kaber@trash.net> | 2007-04-09 11:47:18 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-25 22:28:38 -0700 |
commit | c5c2523893747f88a83376abad310c8ad13f7197 (patch) | |
tree | 58f1ab25ac9f7ca7460abbd24e9bab9c8683f6fd /net/ipv6 | |
parent | 557922584d9c5b6b990bcfb2fec3134f0e73a05d (diff) | |
download | kernel-crypto-c5c2523893747f88a83376abad310c8ad13f7197.tar.gz kernel-crypto-c5c2523893747f88a83376abad310c8ad13f7197.tar.xz kernel-crypto-c5c2523893747f88a83376abad310c8ad13f7197.zip |
[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/ipv6')
-rw-r--r-- | net/ipv6/esp6.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6b76c4c3113..7107bb7e2e6 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -235,22 +235,24 @@ out: return ret; } -static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) +static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); + u32 align = max_t(u32, blksize, esp->conf.padlen); + u32 rem; - if (x->props.mode == XFRM_MODE_TUNNEL) { - mtu = ALIGN(mtu + 2, blksize); - } else { - /* The worst case. */ + mtu -= x->props.header_len + esp->auth.icv_trunc_len; + rem = mtu & (align - 1); + mtu &= ~(align - 1); + + if (x->props.mode != XFRM_MODE_TUNNEL) { u32 padsize = ((blksize - 1) & 7) + 1; - mtu = ALIGN(mtu + 2, padsize) + blksize - padsize; + mtu -= blksize - padsize; + mtu += min_t(u32, blksize - padsize, rem); } - if (esp->conf.padlen) - mtu = ALIGN(mtu, esp->conf.padlen); - return mtu + x->props.header_len + esp->auth.icv_trunc_len; + return mtu - 2; } static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -380,7 +382,7 @@ static struct xfrm_type esp6_type = .proto = IPPROTO_ESP, .init_state = esp6_init_state, .destructor = esp6_destroy, - .get_max_size = esp6_get_max_size, + .get_mtu = esp6_get_mtu, .input = esp6_input, .output = esp6_output, .hdr_offset = xfrm6_find_1stfragopt, |