From 2b1007bf96b5744259ecfa738d04e67221b79f10 Mon Sep 17 00:00:00 2001 From: Luis Ressel Date: Sat, 13 Jan 2018 10:53:52 +0100 Subject: WIP: Automatically update PMTU for tunneled destinations --- src/device.c | 27 ++++++++++++++++++++++++++- src/messages.h | 4 +++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/device.c b/src/device.c index f47c126..11fc8fe 100644 --- a/src/device.c +++ b/src/device.c @@ -119,8 +119,12 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev) struct wireguard_peer *peer; struct sk_buff *next; struct sk_buff_head packets; + struct dst_entry *dst_peer; + struct dst_entry *dst_skb; sa_family_t family; int ret; + u32 mtu; + u32 dbgf = 0; if (unlikely(skb_examine_untrusted_ip_hdr(skb) != skb->protocol)) { ret = -EPROTONOSUPPORT; @@ -142,6 +146,27 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev) goto err_peer; } + dst_peer = dst_cache_get(&peer->endpoint_cache); /* TODO: Laaaaaaazy */ + if (dst_peer) { + dbgf |= 1; + mtu = dst_mtu(dst_peer); + + if(unlikely(mtu < WG_L5_HDR_LEN)) { + ret = -EMSGSIZE; + net_dbg_ratelimited("%s: Path MTU for peer %llu is too small: %u\n", dev->name, peer->internal_id, mtu); + goto err_peer; + } + mtu -= WG_L5_HDR_LEN; + + if (mtu != dev->mtu) { + dbgf |= 2; + mtu &= ~(MESSAGE_PADDING_MULTIPLE - 1); /* w/o this, skb_encrypt() would happily pad the msg past the peer PMTU. */ + dst_skb = skb_dst(skb); + dst_skb->ops->update_pmtu(dst_skb, NULL, skb, mtu); /* TODO: Should we pass in skb->sk instead of NULL? */ + } + } + printk("wg xmit: %u\n", dbgf); + __skb_queue_head_init(&packets); if (!skb_is_gso(skb)) skb->next = NULL; @@ -256,7 +281,7 @@ static void setup(struct net_device *dev) dev->features |= WG_NETDEV_FEATURES; dev->hw_features |= WG_NETDEV_FEATURES; dev->hw_enc_features |= WG_NETDEV_FEATURES; - dev->mtu = ETH_DATA_LEN - MESSAGE_MINIMUM_LENGTH - sizeof(struct udphdr) - max(sizeof(struct ipv6hdr), sizeof(struct iphdr)); + dev->mtu = ETH_DATA_LEN - WG_L5_HDR_LEN; /* We need to keep the dst around in case of icmp replies. */ netif_keep_dst(dev); diff --git a/src/messages.h b/src/messages.h index e221b51..5fa4acd 100644 --- a/src/messages.h +++ b/src/messages.h @@ -119,7 +119,9 @@ enum message_alignments { MESSAGE_MINIMUM_LENGTH = message_data_len(0) }; -#define SKB_HEADER_LEN (max(sizeof(struct iphdr), sizeof(struct ipv6hdr)) + sizeof(struct udphdr) + NET_SKB_PAD) +#define WG_L4_HDR_LEN (max(sizeof(struct iphdr), sizeof(struct ipv6hdr)) + sizeof(struct udphdr)) +#define WG_L5_HDR_LEN (WG_L4_HDR_LEN + MESSAGE_MINIMUM_LENGTH) +#define SKB_HEADER_LEN (WG_L4_HDR_LEN + NET_SKB_PAD) #define DATA_PACKET_HEAD_ROOM ALIGN(sizeof(struct message_data) + SKB_HEADER_LEN, 4) enum { -- cgit v1.2.3-59-g8ed1b