readwrite_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  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. "fmt"
  8. "net"
  9. "runtime"
  10. "strings"
  11. "sync"
  12. "testing"
  13. "golang.org/x/net/internal/iana"
  14. "golang.org/x/net/internal/nettest"
  15. "golang.org/x/net/ipv6"
  16. )
  17. func BenchmarkReadWriteUnicast(b *testing.B) {
  18. c, err := nettest.NewLocalPacketListener("udp6")
  19. if err != nil {
  20. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  21. }
  22. defer c.Close()
  23. dst := c.LocalAddr()
  24. wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
  25. b.Run("NetUDP", func(b *testing.B) {
  26. for i := 0; i < b.N; i++ {
  27. if _, err := c.WriteTo(wb, dst); err != nil {
  28. b.Fatal(err)
  29. }
  30. if _, _, err := c.ReadFrom(rb); err != nil {
  31. b.Fatal(err)
  32. }
  33. }
  34. })
  35. b.Run("IPv6UDP", func(b *testing.B) {
  36. p := ipv6.NewPacketConn(c)
  37. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  38. if err := p.SetControlMessage(cf, true); err != nil {
  39. b.Fatal(err)
  40. }
  41. cm := ipv6.ControlMessage{
  42. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  43. HopLimit: 1,
  44. }
  45. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  46. if ifi != nil {
  47. cm.IfIndex = ifi.Index
  48. }
  49. for i := 0; i < b.N; i++ {
  50. if _, err := p.WriteTo(wb, &cm, dst); err != nil {
  51. b.Fatal(err)
  52. }
  53. if _, _, _, err := p.ReadFrom(rb); err != nil {
  54. b.Fatal(err)
  55. }
  56. }
  57. })
  58. }
  59. func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
  60. switch runtime.GOOS {
  61. case "js", "nacl", "plan9", "windows":
  62. b.Skipf("not supported on %s", runtime.GOOS)
  63. }
  64. payload := []byte("HELLO-R-U-THERE")
  65. iph := []byte{
  66. 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
  67. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  69. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  71. }
  72. greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
  73. datagram := append(greh, append(iph, payload...)...)
  74. bb := make([]byte, 128)
  75. cm := ipv6.ControlMessage{
  76. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  77. HopLimit: 1,
  78. Src: net.IPv6loopback,
  79. }
  80. if ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); ifi != nil {
  81. cm.IfIndex = ifi.Index
  82. }
  83. b.Run("UDP", func(b *testing.B) {
  84. c, err := nettest.NewLocalPacketListener("udp6")
  85. if err != nil {
  86. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  87. }
  88. defer c.Close()
  89. p := ipv6.NewPacketConn(c)
  90. dst := c.LocalAddr()
  91. cf := ipv6.FlagHopLimit | ipv6.FlagInterface
  92. if err := p.SetControlMessage(cf, true); err != nil {
  93. b.Fatal(err)
  94. }
  95. wms := []ipv6.Message{
  96. {
  97. Buffers: [][]byte{payload},
  98. Addr: dst,
  99. OOB: cm.Marshal(),
  100. },
  101. }
  102. rms := []ipv6.Message{
  103. {
  104. Buffers: [][]byte{bb},
  105. OOB: ipv6.NewControlMessage(cf),
  106. },
  107. }
  108. b.Run("Net", func(b *testing.B) {
  109. for i := 0; i < b.N; i++ {
  110. if _, err := c.WriteTo(payload, dst); err != nil {
  111. b.Fatal(err)
  112. }
  113. if _, _, err := c.ReadFrom(bb); err != nil {
  114. b.Fatal(err)
  115. }
  116. }
  117. })
  118. b.Run("ToFrom", func(b *testing.B) {
  119. for i := 0; i < b.N; i++ {
  120. if _, err := p.WriteTo(payload, &cm, dst); err != nil {
  121. b.Fatal(err)
  122. }
  123. if _, _, _, err := p.ReadFrom(bb); err != nil {
  124. b.Fatal(err)
  125. }
  126. }
  127. })
  128. b.Run("Batch", func(b *testing.B) {
  129. for i := 0; i < b.N; i++ {
  130. if _, err := p.WriteBatch(wms, 0); err != nil {
  131. b.Fatal(err)
  132. }
  133. if _, err := p.ReadBatch(rms, 0); err != nil {
  134. b.Fatal(err)
  135. }
  136. }
  137. })
  138. })
  139. b.Run("IP", func(b *testing.B) {
  140. switch runtime.GOOS {
  141. case "netbsd":
  142. b.Skip("need to configure gre on netbsd")
  143. case "openbsd":
  144. b.Skip("net.inet.gre.allow=0 by default on openbsd")
  145. }
  146. c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
  147. if err != nil {
  148. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  149. }
  150. defer c.Close()
  151. p := ipv6.NewPacketConn(c)
  152. dst := c.LocalAddr()
  153. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  154. if err := p.SetControlMessage(cf, true); err != nil {
  155. b.Fatal(err)
  156. }
  157. wms := []ipv6.Message{
  158. {
  159. Buffers: [][]byte{datagram},
  160. Addr: dst,
  161. OOB: cm.Marshal(),
  162. },
  163. }
  164. rms := []ipv6.Message{
  165. {
  166. Buffers: [][]byte{bb},
  167. OOB: ipv6.NewControlMessage(cf),
  168. },
  169. }
  170. b.Run("Net", func(b *testing.B) {
  171. for i := 0; i < b.N; i++ {
  172. if _, err := c.WriteTo(datagram, dst); err != nil {
  173. b.Fatal(err)
  174. }
  175. if _, _, err := c.ReadFrom(bb); err != nil {
  176. b.Fatal(err)
  177. }
  178. }
  179. })
  180. b.Run("ToFrom", func(b *testing.B) {
  181. for i := 0; i < b.N; i++ {
  182. if _, err := p.WriteTo(datagram, &cm, dst); err != nil {
  183. b.Fatal(err)
  184. }
  185. if _, _, _, err := p.ReadFrom(bb); err != nil {
  186. b.Fatal(err)
  187. }
  188. }
  189. })
  190. b.Run("Batch", func(b *testing.B) {
  191. for i := 0; i < b.N; i++ {
  192. if _, err := p.WriteBatch(wms, 0); err != nil {
  193. b.Fatal(err)
  194. }
  195. if _, err := p.ReadBatch(rms, 0); err != nil {
  196. b.Fatal(err)
  197. }
  198. }
  199. })
  200. })
  201. }
  202. func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
  203. switch runtime.GOOS {
  204. case "js", "nacl", "plan9", "windows":
  205. t.Skipf("not supported on %s", runtime.GOOS)
  206. }
  207. if !supportsIPv6 {
  208. t.Skip("ipv6 is not supported")
  209. }
  210. c, err := nettest.NewLocalPacketListener("udp6")
  211. if err != nil {
  212. t.Fatal(err)
  213. }
  214. defer c.Close()
  215. p := ipv6.NewPacketConn(c)
  216. defer p.Close()
  217. dst := c.LocalAddr()
  218. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  219. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  220. wb := []byte("HELLO-R-U-THERE")
  221. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  222. if nettest.ProtocolNotSupported(err) {
  223. t.Skipf("not supported on %s", runtime.GOOS)
  224. }
  225. t.Fatal(err)
  226. }
  227. var wg sync.WaitGroup
  228. reader := func() {
  229. defer wg.Done()
  230. rb := make([]byte, 128)
  231. if n, cm, _, err := p.ReadFrom(rb); err != nil {
  232. t.Error(err)
  233. return
  234. } else if !bytes.Equal(rb[:n], wb) {
  235. t.Errorf("got %v; want %v", rb[:n], wb)
  236. return
  237. } else {
  238. s := cm.String()
  239. if strings.Contains(s, ",") {
  240. t.Errorf("should be space-separated values: %s", s)
  241. }
  242. }
  243. }
  244. writer := func(toggle bool) {
  245. defer wg.Done()
  246. cm := ipv6.ControlMessage{
  247. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  248. Src: net.IPv6loopback,
  249. }
  250. if ifi != nil {
  251. cm.IfIndex = ifi.Index
  252. }
  253. if err := p.SetControlMessage(cf, toggle); err != nil {
  254. t.Error(err)
  255. return
  256. }
  257. if n, err := p.WriteTo(wb, &cm, dst); err != nil {
  258. t.Error(err)
  259. return
  260. } else if n != len(wb) {
  261. t.Errorf("got %d; want %d", n, len(wb))
  262. return
  263. }
  264. }
  265. const N = 10
  266. wg.Add(N)
  267. for i := 0; i < N; i++ {
  268. go reader()
  269. }
  270. wg.Add(2 * N)
  271. for i := 0; i < 2*N; i++ {
  272. go writer(i%2 != 0)
  273. }
  274. wg.Add(N)
  275. for i := 0; i < N; i++ {
  276. go reader()
  277. }
  278. wg.Wait()
  279. }
  280. func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
  281. switch runtime.GOOS {
  282. case "js", "nacl", "plan9", "windows":
  283. t.Skipf("not supported on %s", runtime.GOOS)
  284. }
  285. payload := []byte("HELLO-R-U-THERE")
  286. iph := []byte{
  287. 0x69, 0x8b, 0xee, 0xf1, 0xca, 0xfe, 0xff, 0x01,
  288. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00,
  289. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  290. 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x02, 0x00, 0x00,
  291. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  292. }
  293. greh := []byte{0x00, 0x00, 0x86, 0xdd, 0x00, 0x00, 0x00, 0x00}
  294. datagram := append(greh, append(iph, payload...)...)
  295. t.Run("UDP", func(t *testing.T) {
  296. c, err := nettest.NewLocalPacketListener("udp6")
  297. if err != nil {
  298. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  299. }
  300. defer c.Close()
  301. p := ipv6.NewPacketConn(c)
  302. t.Run("ToFrom", func(t *testing.T) {
  303. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
  304. })
  305. t.Run("Batch", func(t *testing.T) {
  306. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
  307. })
  308. })
  309. t.Run("IP", func(t *testing.T) {
  310. switch runtime.GOOS {
  311. case "netbsd":
  312. t.Skip("need to configure gre on netbsd")
  313. case "openbsd":
  314. t.Skip("net.inet.gre.allow=0 by default on openbsd")
  315. }
  316. c, err := net.ListenPacket(fmt.Sprintf("ip6:%d", iana.ProtocolGRE), "::1")
  317. if err != nil {
  318. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  319. }
  320. defer c.Close()
  321. p := ipv6.NewPacketConn(c)
  322. t.Run("ToFrom", func(t *testing.T) {
  323. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
  324. })
  325. t.Run("Batch", func(t *testing.T) {
  326. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
  327. })
  328. })
  329. }
  330. func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv6.PacketConn, data []byte, dst net.Addr, batch bool) {
  331. ifi := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback)
  332. cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU
  333. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  334. if nettest.ProtocolNotSupported(err) {
  335. t.Skipf("not supported on %s", runtime.GOOS)
  336. }
  337. t.Fatal(err)
  338. }
  339. var wg sync.WaitGroup
  340. reader := func() {
  341. defer wg.Done()
  342. b := make([]byte, 128)
  343. n, cm, _, err := p.ReadFrom(b)
  344. if err != nil {
  345. t.Error(err)
  346. return
  347. }
  348. if !bytes.Equal(b[:n], data) {
  349. t.Errorf("got %#v; want %#v", b[:n], data)
  350. return
  351. }
  352. s := cm.String()
  353. if strings.Contains(s, ",") {
  354. t.Errorf("should be space-separated values: %s", s)
  355. return
  356. }
  357. }
  358. batchReader := func() {
  359. defer wg.Done()
  360. ms := []ipv6.Message{
  361. {
  362. Buffers: [][]byte{make([]byte, 128)},
  363. OOB: ipv6.NewControlMessage(cf),
  364. },
  365. }
  366. n, err := p.ReadBatch(ms, 0)
  367. if err != nil {
  368. t.Error(err)
  369. return
  370. }
  371. if n != len(ms) {
  372. t.Errorf("got %d; want %d", n, len(ms))
  373. return
  374. }
  375. var cm ipv6.ControlMessage
  376. if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
  377. t.Error(err)
  378. return
  379. }
  380. b := ms[0].Buffers[0][:ms[0].N]
  381. if !bytes.Equal(b, data) {
  382. t.Errorf("got %#v; want %#v", b, data)
  383. return
  384. }
  385. s := cm.String()
  386. if strings.Contains(s, ",") {
  387. t.Errorf("should be space-separated values: %s", s)
  388. return
  389. }
  390. }
  391. writer := func(toggle bool) {
  392. defer wg.Done()
  393. cm := ipv6.ControlMessage{
  394. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  395. HopLimit: 1,
  396. Src: net.IPv6loopback,
  397. }
  398. if ifi != nil {
  399. cm.IfIndex = ifi.Index
  400. }
  401. if err := p.SetControlMessage(cf, toggle); err != nil {
  402. t.Error(err)
  403. return
  404. }
  405. n, err := p.WriteTo(data, &cm, dst)
  406. if err != nil {
  407. t.Error(err)
  408. return
  409. }
  410. if n != len(data) {
  411. t.Errorf("got %d; want %d", n, len(data))
  412. return
  413. }
  414. }
  415. batchWriter := func(toggle bool) {
  416. defer wg.Done()
  417. cm := ipv6.ControlMessage{
  418. TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced,
  419. HopLimit: 1,
  420. Src: net.IPv6loopback,
  421. }
  422. if ifi != nil {
  423. cm.IfIndex = ifi.Index
  424. }
  425. if err := p.SetControlMessage(cf, toggle); err != nil {
  426. t.Error(err)
  427. return
  428. }
  429. ms := []ipv6.Message{
  430. {
  431. Buffers: [][]byte{data},
  432. OOB: cm.Marshal(),
  433. Addr: dst,
  434. },
  435. }
  436. n, err := p.WriteBatch(ms, 0)
  437. if err != nil {
  438. t.Error(err)
  439. return
  440. }
  441. if n != len(ms) {
  442. t.Errorf("got %d; want %d", n, len(ms))
  443. return
  444. }
  445. if ms[0].N != len(data) {
  446. t.Errorf("got %d; want %d", ms[0].N, len(data))
  447. return
  448. }
  449. }
  450. const N = 10
  451. wg.Add(N)
  452. for i := 0; i < N; i++ {
  453. if batch {
  454. go batchReader()
  455. } else {
  456. go reader()
  457. }
  458. }
  459. wg.Add(2 * N)
  460. for i := 0; i < 2*N; i++ {
  461. if batch {
  462. go batchWriter(i%2 != 0)
  463. } else {
  464. go writer(i%2 != 0)
  465. }
  466. }
  467. wg.Add(N)
  468. for i := 0; i < N; i++ {
  469. if batch {
  470. go batchReader()
  471. } else {
  472. go reader()
  473. }
  474. }
  475. wg.Wait()
  476. }