readwrite_go1_8_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // Copyright 2012 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. // +build !go1.9
  5. package ipv4_test
  6. import (
  7. "bytes"
  8. "fmt"
  9. "net"
  10. "runtime"
  11. "strings"
  12. "sync"
  13. "testing"
  14. "golang.org/x/net/internal/iana"
  15. "golang.org/x/net/internal/nettest"
  16. "golang.org/x/net/ipv4"
  17. )
  18. func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
  19. switch runtime.GOOS {
  20. case "js", "nacl", "plan9", "windows":
  21. b.Skipf("not supported on %s", runtime.GOOS)
  22. }
  23. payload := []byte("HELLO-R-U-THERE")
  24. iph, err := (&ipv4.Header{
  25. Version: ipv4.Version,
  26. Len: ipv4.HeaderLen,
  27. TotalLen: ipv4.HeaderLen + len(payload),
  28. TTL: 1,
  29. Protocol: iana.ProtocolReserved,
  30. Src: net.IPv4(192, 0, 2, 1),
  31. Dst: net.IPv4(192, 0, 2, 254),
  32. }).Marshal()
  33. if err != nil {
  34. b.Fatal(err)
  35. }
  36. greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
  37. datagram := append(greh, append(iph, payload...)...)
  38. bb := make([]byte, 128)
  39. cm := ipv4.ControlMessage{
  40. Src: net.IPv4(127, 0, 0, 1),
  41. }
  42. if ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); ifi != nil {
  43. cm.IfIndex = ifi.Index
  44. }
  45. b.Run("UDP", func(b *testing.B) {
  46. c, err := nettest.NewLocalPacketListener("udp4")
  47. if err != nil {
  48. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  49. }
  50. defer c.Close()
  51. p := ipv4.NewPacketConn(c)
  52. dst := c.LocalAddr()
  53. cf := ipv4.FlagTTL | ipv4.FlagInterface
  54. if err := p.SetControlMessage(cf, true); err != nil {
  55. b.Fatal(err)
  56. }
  57. b.Run("Net", func(b *testing.B) {
  58. for i := 0; i < b.N; i++ {
  59. if _, err := c.WriteTo(payload, dst); err != nil {
  60. b.Fatal(err)
  61. }
  62. if _, _, err := c.ReadFrom(bb); err != nil {
  63. b.Fatal(err)
  64. }
  65. }
  66. })
  67. b.Run("ToFrom", func(b *testing.B) {
  68. for i := 0; i < b.N; i++ {
  69. if _, err := p.WriteTo(payload, &cm, dst); err != nil {
  70. b.Fatal(err)
  71. }
  72. if _, _, _, err := p.ReadFrom(bb); err != nil {
  73. b.Fatal(err)
  74. }
  75. }
  76. })
  77. })
  78. b.Run("IP", func(b *testing.B) {
  79. switch runtime.GOOS {
  80. case "netbsd":
  81. b.Skip("need to configure gre on netbsd")
  82. case "openbsd":
  83. b.Skip("net.inet.gre.allow=0 by default on openbsd")
  84. }
  85. c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
  86. if err != nil {
  87. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  88. }
  89. defer c.Close()
  90. p := ipv4.NewPacketConn(c)
  91. dst := c.LocalAddr()
  92. cf := ipv4.FlagTTL | ipv4.FlagInterface
  93. if err := p.SetControlMessage(cf, true); err != nil {
  94. b.Fatal(err)
  95. }
  96. b.Run("Net", func(b *testing.B) {
  97. for i := 0; i < b.N; i++ {
  98. if _, err := c.WriteTo(datagram, dst); err != nil {
  99. b.Fatal(err)
  100. }
  101. if _, _, err := c.ReadFrom(bb); err != nil {
  102. b.Fatal(err)
  103. }
  104. }
  105. })
  106. b.Run("ToFrom", func(b *testing.B) {
  107. for i := 0; i < b.N; i++ {
  108. if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
  109. b.Fatal(err)
  110. }
  111. if _, _, _, err := p.ReadFrom(bb); err != nil {
  112. b.Fatal(err)
  113. }
  114. }
  115. })
  116. })
  117. }
  118. func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
  119. switch runtime.GOOS {
  120. case "js", "nacl", "plan9", "windows":
  121. t.Skipf("not supported on %s", runtime.GOOS)
  122. }
  123. payload := []byte("HELLO-R-U-THERE")
  124. iph, err := (&ipv4.Header{
  125. Version: ipv4.Version,
  126. Len: ipv4.HeaderLen,
  127. TotalLen: ipv4.HeaderLen + len(payload),
  128. TTL: 1,
  129. Protocol: iana.ProtocolReserved,
  130. Src: net.IPv4(192, 0, 2, 1),
  131. Dst: net.IPv4(192, 0, 2, 254),
  132. }).Marshal()
  133. if err != nil {
  134. t.Fatal(err)
  135. }
  136. greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
  137. datagram := append(greh, append(iph, payload...)...)
  138. t.Run("UDP", func(t *testing.T) {
  139. c, err := nettest.NewLocalPacketListener("udp4")
  140. if err != nil {
  141. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  142. }
  143. defer c.Close()
  144. p := ipv4.NewPacketConn(c)
  145. t.Run("ToFrom", func(t *testing.T) {
  146. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr())
  147. })
  148. })
  149. t.Run("IP", func(t *testing.T) {
  150. switch runtime.GOOS {
  151. case "netbsd":
  152. t.Skip("need to configure gre on netbsd")
  153. case "openbsd":
  154. t.Skip("net.inet.gre.allow=0 by default on openbsd")
  155. }
  156. c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
  157. if err != nil {
  158. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  159. }
  160. defer c.Close()
  161. p := ipv4.NewPacketConn(c)
  162. t.Run("ToFrom", func(t *testing.T) {
  163. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr())
  164. })
  165. })
  166. }
  167. func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr) {
  168. ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
  169. cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
  170. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  171. if nettest.ProtocolNotSupported(err) {
  172. t.Skipf("not supported on %s", runtime.GOOS)
  173. }
  174. t.Fatal(err)
  175. }
  176. var wg sync.WaitGroup
  177. reader := func() {
  178. defer wg.Done()
  179. b := make([]byte, 128)
  180. n, cm, _, err := p.ReadFrom(b)
  181. if err != nil {
  182. t.Error(err)
  183. return
  184. }
  185. if !bytes.Equal(b[:n], data) {
  186. t.Errorf("got %#v; want %#v", b[:n], data)
  187. return
  188. }
  189. s := cm.String()
  190. if strings.Contains(s, ",") {
  191. t.Errorf("should be space-separated values: %s", s)
  192. return
  193. }
  194. }
  195. writer := func(toggle bool) {
  196. defer wg.Done()
  197. cm := ipv4.ControlMessage{
  198. Src: net.IPv4(127, 0, 0, 1),
  199. }
  200. if ifi != nil {
  201. cm.IfIndex = ifi.Index
  202. }
  203. if err := p.SetControlMessage(cf, toggle); err != nil {
  204. t.Error(err)
  205. return
  206. }
  207. n, err := p.WriteTo(data, &cm, dst)
  208. if err != nil {
  209. t.Error(err)
  210. return
  211. }
  212. if n != len(data) {
  213. t.Errorf("got %d; want %d", n, len(data))
  214. return
  215. }
  216. }
  217. const N = 10
  218. wg.Add(N)
  219. for i := 0; i < N; i++ {
  220. go reader()
  221. }
  222. wg.Add(2 * N)
  223. for i := 0; i < 2*N; i++ {
  224. go writer(i%2 != 0)
  225. }
  226. wg.Add(N)
  227. for i := 0; i < N; i++ {
  228. go reader()
  229. }
  230. wg.Wait()
  231. }