readwrite_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ipv6_test
  5. import (
  6. "bytes"
  7. "net"
  8. "runtime"
  9. "sync"
  10. "testing"
  11. "golang.org/x/net/internal/iana"
  12. "golang.org/x/net/internal/nettest"
  13. "golang.org/x/net/ipv6"
  14. )
  15. func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
  16. c, err := net.ListenPacket("udp6", "[::1]:0")
  17. if err != nil {
  18. return nil, nil, err
  19. }
  20. dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
  21. if err != nil {
  22. c.Close()
  23. return nil, nil, err
  24. }
  25. return c, dst, nil
  26. }
  27. func BenchmarkReadWriteNetUDP(b *testing.B) {
  28. c, dst, err := benchmarkUDPListener()
  29. if err != nil {
  30. b.Fatalf("benchmarkUDPListener failed: %v", err)
  31. }
  32. defer c.Close()
  33. wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
  34. b.ResetTimer()
  35. for i := 0; i < b.N; i++ {
  36. benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
  37. }
  38. }
  39. func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
  40. if _, err := c.WriteTo(wb, dst); err != nil {
  41. b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
  42. }
  43. if _, _, err := c.ReadFrom(rb); err != nil {
  44. b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
  45. }
  46. }
  47. func BenchmarkReadWriteIPv6UDP(b *testing.B) {
  48. c, dst, err := benchmarkUDPListener()
  49. if err != nil {
  50. b.Fatalf("benchmarkUDPListener failed: %v", err)
  51. }
  52. defer c.Close()
  53. p := ipv6.NewPacketConn(c)
  54. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  55. if err := p.SetControlMessage(cf, true); err != nil {
  56. b.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
  57. }
  58. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  59. wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
  60. b.ResetTimer()
  61. for i := 0; i < b.N; i++ {
  62. benchmarkReadWriteIPv6UDP(b, p, wb, rb, dst, ifi)
  63. }
  64. }
  65. func benchmarkReadWriteIPv6UDP(b *testing.B, p *ipv6.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
  66. cm := ipv6.ControlMessage{
  67. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  68. HopLimit: 1,
  69. }
  70. if ifi != nil {
  71. cm.IfIndex = ifi.Index
  72. }
  73. if n, err := p.WriteTo(wb, &cm, dst); err != nil {
  74. b.Fatalf("ipv6.PacketConn.WriteTo failed: %v", err)
  75. } else if n != len(wb) {
  76. b.Fatalf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
  77. }
  78. if _, _, _, err := p.ReadFrom(rb); err != nil {
  79. b.Fatalf("ipv6.PacketConn.ReadFrom failed: %v", err)
  80. }
  81. }
  82. func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
  83. switch runtime.GOOS {
  84. case "nacl", "plan9", "solaris", "windows":
  85. t.Skipf("not supported on %q", runtime.GOOS)
  86. }
  87. if !supportsIPv6 {
  88. t.Skip("ipv6 is not supported")
  89. }
  90. c, err := net.ListenPacket("udp6", "[::1]:0")
  91. if err != nil {
  92. t.Fatalf("net.ListenPacket failed: %v", err)
  93. }
  94. defer c.Close()
  95. p := ipv6.NewPacketConn(c)
  96. defer p.Close()
  97. dst, err := net.ResolveUDPAddr("udp6", c.LocalAddr().String())
  98. if err != nil {
  99. t.Fatalf("net.ResolveUDPAddr failed: %v", err)
  100. }
  101. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  102. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  103. wb := []byte("HELLO-R-U-THERE")
  104. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  105. if nettest.ProtocolNotSupported(err) {
  106. t.Skipf("not supported on %q", runtime.GOOS)
  107. }
  108. t.Fatalf("ipv6.PacketConn.SetControlMessage failed: %v", err)
  109. }
  110. var wg sync.WaitGroup
  111. reader := func() {
  112. defer wg.Done()
  113. rb := make([]byte, 128)
  114. if n, cm, _, err := p.ReadFrom(rb); err != nil {
  115. t.Errorf("ipv6.PacketConn.ReadFrom failed: %v", err)
  116. return
  117. } else if !bytes.Equal(rb[:n], wb) {
  118. t.Errorf("got %v; expected %v", rb[:n], wb)
  119. return
  120. } else {
  121. t.Logf("rcvd cmsg: %v", cm)
  122. }
  123. }
  124. writer := func(toggle bool) {
  125. defer wg.Done()
  126. cm := ipv6.ControlMessage{
  127. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  128. Src: net.IPv6loopback,
  129. }
  130. if ifi != nil {
  131. cm.IfIndex = ifi.Index
  132. }
  133. if err := p.SetControlMessage(cf, toggle); err != nil {
  134. t.Errorf("ipv6.PacketConn.SetControlMessage failed: %v", err)
  135. return
  136. }
  137. if n, err := p.WriteTo(wb, &cm, dst); err != nil {
  138. t.Errorf("ipv6.PacketConn.WriteTo failed: %v", err)
  139. return
  140. } else if n != len(wb) {
  141. t.Errorf("ipv6.PacketConn.WriteTo failed: short write: %v", n)
  142. return
  143. }
  144. }
  145. const N = 10
  146. wg.Add(N)
  147. for i := 0; i < N; i++ {
  148. go reader()
  149. }
  150. wg.Add(2 * N)
  151. for i := 0; i < 2*N; i++ {
  152. go writer(i%2 != 0)
  153. }
  154. wg.Add(N)
  155. for i := 0; i < N; i++ {
  156. go reader()
  157. }
  158. wg.Wait()
  159. }