: Optimize MTU calculation
Subsystems (3)
Optimize IPsec MTU calculation. Now also tested with beet mode.
[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.
---
commit 02ce45c1de8a2de2f02cc6f3d88583706575142b
tree e97b27090af4a3767df52c16ea23ea9851a97c58
parent c543abe080ba68e9040ca819bab2a6ff2ad90c15
author Patrick McHardy <[email protected]> Thu, 05 Apr 2007 14:02:07 +0200 committer Patrick McHardy <[email protected]> Thu, 05 Apr 2007 14:02:07 +0200
include/net/xfrm.h | 2 +- net/ipv4/esp4.c | 30 ++++++++++++++++++------------ net/ipv6/esp6.c | 22 ++++++++++++---------- net/xfrm/xfrm_state.c | 36 ++++++++---------------------------- 4 files changed, 39 insertions(+), 51 deletions(-)
include/net/xfrm.h +1 -1
@@ -279,7 +279,7 @@ struct xfrm_typexfrm_address_t *(*local_addr)(struct xfrm_state *,xfrm_address_t *);xfrm_address_t *(*remote_addr)(struct xfrm_state *,xfrm_address_t *);/* Estimate maximal size of result of transformation of a dgram */ -u32 (*get_max_size)(struct xfrm_state *,int size); +u32 (*get_mtu)(struct xfrm_state *,int size); };extern int xfrm_register_type (struct xfrm_type *type,unsigned short family);
net/ipv4/esp4.c +18 -12
@@ -272,32 +272,34 @@ out:return -EINVAL ; } -static u32 esp4_get_max_size (struct xfrm_state *x,int mtu) +static u32 esp4_get_mtu (struct xfrm_state *x,int mtu) {struct esp_data *esp = x->data;u32 blksize =ALIGN (crypto_blkcipher_blocksize (esp->conf.tfm),4 ); -int enclen =0 ; +u32 align =max_t (u32, blksize, esp->conf.padlen); +u32 rem; + + mtu -= x->props.header_len + esp->auth.icv_trunc_len; + rem = mtu & (align -1 ); + mtu &= ~(align -1 );switch (x->props.mode) {case XFRM_MODE_TUNNEL : - mtu =ALIGN (mtu +2 , blksize);break ;default :case XFRM_MODE_TRANSPORT :/* The worst case */ - mtu =ALIGN (mtu +2 ,4 ) + blksize -4 ; + mtu -= blksize -4 ; + mtu +=min_t (u32, blksize -4 , rem);break ;case XFRM_MODE_BEET :/* The worst case. */ - enclen =IPV4_BEET_PHMAXLEN ; - mtu =ALIGN (mtu + enclen +2 , blksize); + mtu -=IPV4_BEET_PHMAXLEN ; + mtu +=min_t (u32,IPV4_BEET_PHMAXLEN , rem);break ; } -if (esp->conf.padlen) - mtu =ALIGN (mtu, esp->conf.padlen); - -return mtu + x->props.header_len + esp->auth.icv_trunc_len - enclen; +return mtu -2 ; }static void esp4_err (struct sk_buff *skb,u32 info)
@@ -340,6 +342,7 @@ static int esp_init_state(struct xfrm_state *x) {struct esp_data *esp =NULL ;struct crypto_blkcipher *tfm; +u32 align;/* null auth and encryption can have zero length keys */ if (x->aalg) {
@@ -421,7 +424,10 @@ static int esp_init_state(struct xfrm_state *x) } } x->data = esp; - x->props.trailer_len =esp4_get_max_size (x,0 ) - x->props.header_len; + align =ALIGN (crypto_blkcipher_blocksize (esp->conf.tfm),4 ); +if (esp->conf.padlen) + align =max_t (u32, align, esp->conf.padlen); + x->props.trailer_len = align +1 + esp->auth.icv_trunc_len;return 0 ; error:
@@ -438,7 +444,7 @@ static struct xfrm_type esp_type = .proto = IPPROTO_ESP, .init_state = esp_init_state, .destructor = esp_destroy, - .get_max_size = esp4_get_max_size, + .get_mtu = esp4_get_mtu, .input = esp_input, .output = esp_output };
net/ipv6/esp6.c +12 -10
@@ -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,
net/xfrm/xfrm_state.c +8 -28
@@ -1666,37 +1666,17 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) }EXPORT_SYMBOL (xfrm_state_delete_tunnel); -/* -* This function is NOT optimal. For example, with ESP it will give an -* MTU that's usually two bytes short of being optimal. However, it will -* usually give an answer that's a multiple of 4 provided the input is -* also a multiple of 4. -*/ int xfrm_state_mtu (struct xfrm_state *x,int mtu) { -int res = mtu; - - res -= x->props.header_len; - -for (;;) { -int m = res; - -if (m <68 ) -return 68 ; - -spin_lock_bh (&x->lock); -if (x->km.state ==XFRM_STATE_VALID && - x->type && x->type->get_max_size) - m = x->type->get_max_size (x, m); -else - m += x->props.header_len; -spin_unlock_bh (&x->lock); - -if (m <= mtu) -break ; - res -= (m - mtu); - } +int res; +spin_lock_bh (&x->lock); +if (x->km.state ==XFRM_STATE_VALID && + x->type && x->type->get_mtu) + res = x->type->get_mtu (x, mtu); +else + res = mtu; +spin_unlock_bh (&x->lock);return res; }
From: Patrick McHardy <[email protected]>
Date: Fri, 06 Apr 2007 21:48:49 +0200
Quoted 1 line
Optimize IPsec MTU calculation. Now also tested with beet mode.
Applied, thanks Patrick.