You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

509 lines
12 KiB

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