readwrite_test.go 4.2 KB

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