diff --git a/tun_linux.go b/tun_linux.go index cf66a8c..6a9cb09 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -216,6 +216,7 @@ func (c Tun) Activate() error { LinkIndex: link.Attrs().Index, Dst: dr, MTU: c.DefaultMTU, + AdvMSS: c.advMSS(route{}), Scope: unix.RT_SCOPE_LINK, Src: c.Cidr.IP, Protocol: unix.RTPROT_KERNEL, @@ -233,6 +234,7 @@ func (c Tun) Activate() error { LinkIndex: link.Attrs().Index, Dst: r.route, MTU: r.mtu, + AdvMSS: c.advMSS(r), Scope: unix.RT_SCOPE_LINK, } @@ -248,6 +250,7 @@ func (c Tun) Activate() error { LinkIndex: link.Attrs().Index, Dst: r.route, MTU: r.mtu, + AdvMSS: c.advMSS(r), Scope: unix.RT_SCOPE_LINK, } @@ -265,3 +268,16 @@ func (c Tun) Activate() error { return nil } + +func (c Tun) advMSS(r route) int { + mtu := r.mtu + if r.mtu == 0 { + mtu = c.DefaultMTU + } + + // We only need to set advmss if the route MTU does not match the device MTU + if mtu != c.MaxMTU { + return mtu - 40 + } + return 0 +} diff --git a/tun_linux_test.go b/tun_linux_test.go new file mode 100644 index 0000000..4e70aa0 --- /dev/null +++ b/tun_linux_test.go @@ -0,0 +1,31 @@ +package nebula + +import "testing" + +var runAdvMSSTests = []struct { + name string + tun Tun + r route + expected int +}{ + // Standard case, default MTU is the device max MTU + {"default", Tun{DefaultMTU: 1440, MaxMTU: 1440}, route{}, 0}, + {"default-min", Tun{DefaultMTU: 1440, MaxMTU: 1440}, route{mtu: 1440}, 0}, + {"default-low", Tun{DefaultMTU: 1440, MaxMTU: 1440}, route{mtu: 1200}, 1160}, + + // Case where we have a route MTU set higher than the default + {"route", Tun{DefaultMTU: 1440, MaxMTU: 8941}, route{}, 1400}, + {"route-min", Tun{DefaultMTU: 1440, MaxMTU: 8941}, route{mtu: 1440}, 1400}, + {"route-high", Tun{DefaultMTU: 1440, MaxMTU: 8941}, route{mtu: 8941}, 0}, +} + +func TestTunAdvMSS(t *testing.T) { + for _, tt := range runAdvMSSTests { + t.Run(tt.name, func(t *testing.T) { + o := tt.tun.advMSS(tt.r) + if o != tt.expected { + t.Errorf("got %d, want %d", o, tt.expected) + } + }) + } +}