aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuis Ressel <aranea@aixah.de>2018-01-13 10:53:52 +0100
committerLuis Ressel <aranea@aixah.de>2018-01-13 10:53:52 +0100
commit2b1007bf96b5744259ecfa738d04e67221b79f10 (patch)
treeeb6506284311aa1b04e6e19bf4654cd140c9b098
parentexternal-tests: add python implementation (diff)
downloadWireGuard-lr/pmtu.tar.xz
WireGuard-lr/pmtu.zip
WIP: Automatically update PMTU for tunneled destinationslr/pmtu
-rw-r--r--src/device.c27
-rw-r--r--src/messages.h4
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 {