udp_mtu_test.go 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package amneziawgnet
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "net/netip"
  6. "testing"
  7. "time"
  8. "gvisor.dev/gvisor/pkg/tcpip"
  9. "gvisor.dev/gvisor/pkg/tcpip/checksum"
  10. "gvisor.dev/gvisor/pkg/tcpip/header"
  11. )
  12. // TestWriteUDPReplyMTU exercises the actual channel-backed TUN output, not a packet builder.
  13. func TestWriteUDPReplyMTU(t *testing.T) {
  14. for _, tc := range []struct {
  15. name string
  16. payload int
  17. fragments bool
  18. }{
  19. {"small", 32, false}, {"boundary", 1252, false}, {"oversize", 1452, true},
  20. } {
  21. t.Run(tc.name, func(t *testing.T) {
  22. tun, gstack, err := createNetTUNWithStack([]netip.Addr{netip.MustParseAddr("10.77.0.1")}, 1280)
  23. if err != nil {
  24. t.Fatal(err)
  25. }
  26. defer tun.Close()
  27. enablePromiscuousRouting(gstack)
  28. from := netip.MustParseAddrPort("203.0.113.9:5353")
  29. to := netip.MustParseAddrPort("10.77.0.2:49152")
  30. payload := make([]byte, tc.payload)
  31. for i := range payload {
  32. payload[i] = byte(i*37 + 11)
  33. }
  34. if err := WriteUDPReply(gstack, from, to, payload); err != nil {
  35. t.Fatal(err)
  36. }
  37. st := tun.(*stackTun)
  38. var data []byte
  39. var received int
  40. var id uint16
  41. for {
  42. select {
  43. case v := <-st.incomingPacket:
  44. p := v.AsSlice()
  45. packet := append([]byte(nil), p...)
  46. v.Release()
  47. if len(packet) > 1280 {
  48. t.Fatalf("TUN packet length %d exceeds MTU 1280", len(packet))
  49. }
  50. ip := header.IPv4(packet)
  51. if ip.SourceAddress().String() != from.Addr().String() || ip.DestinationAddress().String() != to.Addr().String() {
  52. t.Fatalf("IP addresses %s -> %s", ip.SourceAddress(), ip.DestinationAddress())
  53. }
  54. if ip.TotalLength() != uint16(len(packet)) || checksum.Checksum(packet[:ip.HeaderLength()], 0) != 0xffff {
  55. t.Fatalf("bad IPv4 header, len %d", len(packet))
  56. }
  57. if received == 0 {
  58. id = ip.ID()
  59. } else if id != ip.ID() {
  60. t.Fatalf("fragment IDs differ: %d != %d", id, ip.ID())
  61. }
  62. offset := int(ip.FragmentOffset())
  63. part := packet[ip.HeaderLength():]
  64. if offset != received {
  65. t.Fatalf("fragment offset %d, expected %d", offset, received)
  66. }
  67. data = append(data, part...)
  68. received += len(part)
  69. if ip.Flags()&header.IPv4FlagMoreFragments == 0 {
  70. if tc.fragments && offset == 0 {
  71. t.Fatal("oversize reply was not fragmented")
  72. }
  73. goto reassembled
  74. }
  75. case <-time.After(time.Second):
  76. t.Fatal("timed out waiting for TUN packets")
  77. }
  78. }
  79. reassembled:
  80. if len(data) != header.UDPMinimumSize+len(payload) {
  81. t.Fatalf("UDP bytes %d, want %d", len(data), 8+len(payload))
  82. }
  83. if binary.BigEndian.Uint16(data[:2]) != from.Port() || binary.BigEndian.Uint16(data[2:4]) != to.Port() || binary.BigEndian.Uint16(data[4:6]) != uint16(len(data)) {
  84. t.Fatalf("UDP ports/length incorrect: %x", data[:8])
  85. }
  86. if !bytes.Equal(data[8:], payload) {
  87. t.Fatal("UDP payload changed")
  88. }
  89. if checksum.Checksum(data, header.PseudoHeaderChecksum(header.UDPProtocolNumber, tcpip.AddrFromSlice(from.Addr().AsSlice()), tcpip.AddrFromSlice(to.Addr().AsSlice()), uint16(len(data)))) != 0xffff {
  90. t.Fatal("UDP checksum invalid")
  91. }
  92. })
  93. }
  94. }