readwrite_go1_9_test.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Copyright 2017 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 ipv6_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/ipv6"
  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 := []byte{
  25. 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
  26. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
  27. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  28. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
  29. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  30. }
  31. greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
  32. datagram := append(greh, append(iph, payload...)...)
  33. bb := make([]byte, 128)
  34. cm := ipv6.ControlMessage{
  35. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  36. HopLimit: 1,
  37. Src: net.IPv6loopback,
  38. }
  39. if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil {
  40. cm.IfIndex = ifi.Index
  41. }
  42. b.Run("UDP", func(b *testing.B) {
  43. c, err := nettest.NewLocalPacketListener("udp6")
  44. if err != nil {
  45. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  46. }
  47. defer c.Close()
  48. p := ipv6.NewPacketConn(c)
  49. dst := c.LocalAddr()
  50. cf := ipv6.FlagHopLimit | ipv6.FlagInterface
  51. if err := p.SetControlMessage(cf, true); err != nil {
  52. b.Fatal(err)
  53. }
  54. wms := []ipv6.Message{
  55. {
  56. Buffers: [][]byte{payload},
  57. Addr: dst,
  58. OOB: cm.Marshal(),
  59. },
  60. }
  61. rms := []ipv6.Message{
  62. {
  63. Buffers: [][]byte{bb},
  64. OOB: ipv6.NewControlMessage(cf),
  65. },
  66. }
  67. b.Run("Net", func(b *testing.B) {
  68. for i := 0; i < b.N; i++ {
  69. if _, err := c.WriteTo(payload, dst); err != nil {
  70. b.Fatal(err)
  71. }
  72. if _, _, err := c.ReadFrom(bb); err != nil {
  73. b.Fatal(err)
  74. }
  75. }
  76. })
  77. b.Run("ToFrom", func(b *testing.B) {
  78. for i := 0; i < b.N; i++ {
  79. if _, err := p.WriteTo(payload, &cm, dst); err != nil {
  80. b.Fatal(err)
  81. }
  82. if _, _, _, err := p.ReadFrom(bb); err != nil {
  83. b.Fatal(err)
  84. }
  85. }
  86. })
  87. b.Run("Batch", func(b *testing.B) {
  88. for i := 0; i < b.N; i++ {
  89. if _, err := p.WriteBatch(wms, 0); err != nil {
  90. b.Fatal(err)
  91. }
  92. if _, err := p.ReadBatch(rms, 0); err != nil {
  93. b.Fatal(err)
  94. }
  95. }
  96. })
  97. })
  98. b.Run("IP", func(b *testing.B) {
  99. switch runtime.GOOS {
  100. case "netbsd":
  101. b.Skip("need to configure gre on netbsd")
  102. case "openbsd":
  103. b.Skip("net.inet.gre.allow=0 by default on openbsd")
  104. }
  105. c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
  106. if err != nil {
  107. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  108. }
  109. defer c.Close()
  110. p := ipv6.NewPacketConn(c)
  111. dst := c.LocalAddr()
  112. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  113. if err := p.SetControlMessage(cf, true); err != nil {
  114. b.Fatal(err)
  115. }
  116. wms := []ipv6.Message{
  117. {
  118. Buffers: [][]byte{datagram},
  119. Addr: dst,
  120. OOB: cm.Marshal(),
  121. },
  122. }
  123. rms := []ipv6.Message{
  124. {
  125. Buffers: [][]byte{bb},
  126. OOB: ipv6.NewControlMessage(cf),
  127. },
  128. }
  129. b.Run("Net", func(b *testing.B) {
  130. for i := 0; i < b.N; i++ {
  131. if _, err := c.WriteTo(datagram, dst); err != nil {
  132. b.Fatal(err)
  133. }
  134. if _, _, err := c.ReadFrom(bb); err != nil {
  135. b.Fatal(err)
  136. }
  137. }
  138. })
  139. b.Run("ToFrom", func(b *testing.B) {
  140. for i := 0; i < b.N; i++ {
  141. if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
  142. b.Fatal(err)
  143. }
  144. if _, _, _, err := p.ReadFrom(bb); err != nil {
  145. b.Fatal(err)
  146. }
  147. }
  148. })
  149. b.Run("Batch", func(b *testing.B) {
  150. for i := 0; i < b.N; i++ {
  151. if _, err := p.WriteBatch(wms, 0); err != nil {
  152. b.Fatal(err)
  153. }
  154. if _, err := p.ReadBatch(rms, 0); err != nil {
  155. b.Fatal(err)
  156. }
  157. }
  158. })
  159. })
  160. }
  161. func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
  162. switch runtime.GOOS {
  163. case "js", "nacl", "plan9", "windows":
  164. t.Skipf("not supported on %s", runtime.GOOS)
  165. }
  166. payload := []byte("HELLO-R-U-THERE")
  167. iph := []byte{
  168. 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
  169. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
  170. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  171. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
  172. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  173. }
  174. greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
  175. datagram := append(greh, append(iph, payload...)...)
  176. t.Run("UDP", func(t *testing.T) {
  177. c, err := nettest.NewLocalPacketListener("udp6")
  178. if err != nil {
  179. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  180. }
  181. defer c.Close()
  182. p := ipv6.NewPacketConn(c)
  183. t.Run("ToFrom", func(t *testing.T) {
  184. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
  185. })
  186. t.Run("Batch", func(t *testing.T) {
  187. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
  188. })
  189. })
  190. t.Run("IP", func(t *testing.T) {
  191. switch runtime.GOOS {
  192. case "netbsd":
  193. t.Skip("need to configure gre on netbsd")
  194. case "openbsd":
  195. t.Skip("net.inet.gre.allow=0 by default on openbsd")
  196. }
  197. c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
  198. if err != nil {
  199. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  200. }
  201. defer c.Close()
  202. p := ipv6.NewPacketConn(c)
  203. t.Run("ToFrom", func(t *testing.T) {
  204. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
  205. })
  206. t.Run("Batch", func(t *testing.T) {
  207. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
  208. })
  209. })
  210. }
  211. func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr, batch bool) {
  212. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  213. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  214. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  215. if nettest.ProtocolNotSupported(err) {
  216. t.Skipf("not supported on %s", runtime.GOOS)
  217. }
  218. t.Fatal(err)
  219. }
  220. var wg sync.WaitGroup
  221. reader := func() {
  222. defer wg.Done()
  223. b := make([]byte, 128)
  224. n, cm, _, err := p.ReadFrom(b)
  225. if err != nil {
  226. t.Error(err)
  227. return
  228. }
  229. if !bytes.Equal(b[:n], data) {
  230. t.Errorf("got %#v; want %#v", b[:n], data)
  231. return
  232. }
  233. s := cm.String()
  234. if strings.Contains(s, ",") {
  235. t.Errorf("should be space-separated values: %s", s)
  236. return
  237. }
  238. }
  239. batchReader := func() {
  240. defer wg.Done()
  241. ms := []ipv6.Message{
  242. {
  243. Buffers: [][]byte{make([]byte, 128)},
  244. OOB: ipv6.NewControlMessage(cf),
  245. },
  246. }
  247. n, err := p.ReadBatch(ms, 0)
  248. if err != nil {
  249. t.Error(err)
  250. return
  251. }
  252. if n != len(ms) {
  253. t.Errorf("got %d; want %d", n, len(ms))
  254. return
  255. }
  256. var cm ipv6.ControlMessage
  257. if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
  258. t.Error(err)
  259. return
  260. }
  261. b := ms[0].Buffers[0][:ms[0].N]
  262. if !bytes.Equal(b, data) {
  263. t.Errorf("got %#v; want %#v", b, data)
  264. return
  265. }
  266. s := cm.String()
  267. if strings.Contains(s, ",") {
  268. t.Errorf("should be space-separated values: %s", s)
  269. return
  270. }
  271. }
  272. writer := func(toggle bool) {
  273. defer wg.Done()
  274. cm := ipv6.ControlMessage{
  275. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  276. HopLimit: 1,
  277. Src: net.IPv6loopback,
  278. }
  279. if ifi != nil {
  280. cm.IfIndex = ifi.Index
  281. }
  282. if err := p.SetControlMessage(cf, toggle); err != nil {
  283. t.Error(err)
  284. return
  285. }
  286. n, err := p.WriteTo(data, &cm, dst)
  287. if err != nil {
  288. t.Error(err)
  289. return
  290. }
  291. if n != len(data) {
  292. t.Errorf("got %d; want %d", n, len(data))
  293. return
  294. }
  295. }
  296. batchWriter := func(toggle bool) {
  297. defer wg.Done()
  298. cm := ipv6.ControlMessage{
  299. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  300. HopLimit: 1,
  301. Src: net.IPv6loopback,
  302. }
  303. if ifi != nil {
  304. cm.IfIndex = ifi.Index
  305. }
  306. if err := p.SetControlMessage(cf, toggle); err != nil {
  307. t.Error(err)
  308. return
  309. }
  310. ms := []ipv6.Message{
  311. {
  312. Buffers: [][]byte{data},
  313. OOB: cm.Marshal(),
  314. Addr: dst,
  315. },
  316. }
  317. n, err := p.WriteBatch(ms, 0)
  318. if err != nil {
  319. t.Error(err)
  320. return
  321. }
  322. if n != len(ms) {
  323. t.Errorf("got %d; want %d", n, len(ms))
  324. return
  325. }
  326. if ms[0].N != len(data) {
  327. t.Errorf("got %d; want %d", ms[0].N, len(data))
  328. return
  329. }
  330. }
  331. const N = 10
  332. wg.Add(N)
  333. for i := 0; i < N; i++ {
  334. if batch {
  335. go batchReader()
  336. } else {
  337. go reader()
  338. }
  339. }
  340. wg.Add(2 * N)
  341. for i := 0; i < 2*N; i++ {
  342. if batch {
  343. go batchWriter(i%2 != 0)
  344. } else {
  345. go writer(i%2 != 0)
  346. }
  347. }
  348. wg.Add(N)
  349. for i := 0; i < N; i++ {
  350. if batch {
  351. go batchReader()
  352. } else {
  353. go reader()
  354. }
  355. }
  356. wg.Wait()
  357. }