diff mbox

[2/3] xfrm: Traffic Flow Confidentiality for IPv4 ESP

Message ID 1291717744-30111-3-git-send-email-martin@strongswan.org
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Martin Willi Dec. 7, 2010, 10:29 a.m. UTC
Add TFC padding to all packets smaller than the boundary configured
on the xfrm state. If the boundary is larger than the PMTU, limit
padding to the PMTU.

Signed-off-by: Martin Willi <martin@strongswan.org>
---
 net/ipv4/esp4.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

Comments

Herbert Xu Dec. 8, 2010, 8:49 a.m. UTC | #1
On Tue, Dec 07, 2010 at 11:29:03AM +0100, Martin Willi wrote:
> Add TFC padding to all packets smaller than the boundary configured
> on the xfrm state. If the boundary is larger than the PMTU, limit
> padding to the PMTU.

Thanks for the update Martin.

However, I still think it's more complicated than it needs be.
In particular, why would we need a boundary at all? Setting it to
anything other than the PMTU would seem to defeat the purpose of
TFC for packets between the boundary and the PMTU.

If we can get rid of tfc.pad, we can simplify the user-interface
change to just adding an xfrm_state flag.

Cheers,
Martin Willi Dec. 8, 2010, 9:20 a.m. UTC | #2
> In particular, why would we need a boundary at all? Setting it to
> anything other than the PMTU would seem to defeat the purpose of
> TFC for packets between the boundary and the PMTU.

I don't agree, this highly depends on the traffic on the SA. For a
general purpose tunnel with TCP flows, PMTU padding is fine. But if
there are only small packets (maybe SIP+RTP), padding to the PMTU is
very expensive.

The administrator setting up the SAs probably knows (or even controls
directly) what traffic it is used for, and might lower the boundary
accordingly.

Regards
Martin

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Herbert Xu Dec. 8, 2010, 9:24 a.m. UTC | #3
On Wed, Dec 08, 2010 at 10:20:41AM +0100, Martin Willi wrote:
> 
> > In particular, why would we need a boundary at all? Setting it to
> > anything other than the PMTU would seem to defeat the purpose of
> > TFC for packets between the boundary and the PMTU.
> 
> I don't agree, this highly depends on the traffic on the SA. For a
> general purpose tunnel with TCP flows, PMTU padding is fine. But if
> there are only small packets (maybe SIP+RTP), padding to the PMTU is
> very expensive.
> 
> The administrator setting up the SAs probably knows (or even controls
> directly) what traffic it is used for, and might lower the boundary
> accordingly.

OK, that's a good reason.

But you should probably get rid of that unused flag field in
the user-interface and just provide a pad length.

Thanks,
diff mbox

Patch

diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 14ca1f1..e7784e8 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -23,6 +23,8 @@  struct esp_skb_cb {
 
 #define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
 
+static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
+
 /*
  * Allocate an AEAD request structure with extra space for SG and IV.
  *
@@ -117,25 +119,36 @@  static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 	int blksize;
 	int clen;
 	int alen;
+	int plen;
+	int tfclen;
 	int nfrags;
 
 	/* skb is pure payload to encrypt */
 
 	err = -ENOMEM;
 
-	/* Round to block size */
-	clen = skb->len;
-
 	esp = x->data;
 	aead = esp->aead;
 	alen = crypto_aead_authsize(aead);
 
+	tfclen = 0;
+	if (x->tfc.pad && x->props.mode == XFRM_MODE_TUNNEL) {
+		struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
+		u32 mtu, padto;
+
+		mtu = esp4_get_mtu(x, dst->child_mtu_cached);
+		padto = min_t(u32, x->tfc.pad, mtu);
+		if (skb->len < padto)
+			tfclen = padto - skb->len;
+	}
 	blksize = ALIGN(crypto_aead_blocksize(aead), 4);
-	clen = ALIGN(clen + 2, blksize);
+	clen = ALIGN(skb->len + 2 + tfclen, blksize);
 	if (esp->padlen)
 		clen = ALIGN(clen, esp->padlen);
+	plen = clen - skb->len - tfclen;
 
-	if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0)
+	err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
+	if (err < 0)
 		goto error;
 	nfrags = err;
 
@@ -150,13 +163,17 @@  static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 
 	/* Fill padding... */
 	tail = skb_tail_pointer(trailer);
+	if (tfclen) {
+		memset(tail, 0, tfclen);
+		tail += tfclen;
+	}
 	do {
 		int i;
-		for (i=0; i<clen-skb->len - 2; i++)
+		for (i = 0; i < plen - 2; i++)
 			tail[i] = i + 1;
 	} while (0);
-	tail[clen - skb->len - 2] = (clen - skb->len) - 2;
-	tail[clen - skb->len - 1] = *skb_mac_header(skb);
+	tail[plen - 2] = plen - 2;
+	tail[plen - 1] = *skb_mac_header(skb);
 	pskb_put(skb, trailer, clen - skb->len + alen);
 
 	skb_push(skb, -skb_network_offset(skb));