readwrite_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  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. package ipv4_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/ipv4"
  16. )
  17. func BenchmarkReadWriteUnicast(b *testing.B) {
  18. c, err := nettest.NewLocalPacketListener("udp4")
  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("IPv4UDP", func(b *testing.B) {
  36. p := ipv4.NewPacketConn(c)
  37. cf := ipv4.FlagTTL | ipv4.FlagInterface
  38. if err := p.SetControlMessage(cf, true); err != nil {
  39. b.Fatal(err)
  40. }
  41. cm := ipv4.ControlMessage{TTL: 1}
  42. ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
  43. if ifi != nil {
  44. cm.IfIndex = ifi.Index
  45. }
  46. for i := 0; i < b.N; i++ {
  47. if _, err := p.WriteTo(wb, &cm, dst); err != nil {
  48. b.Fatal(err)
  49. }
  50. if _, _, _, err := p.ReadFrom(rb); err != nil {
  51. b.Fatal(err)
  52. }
  53. }
  54. })
  55. }
  56. func BenchmarkPacketConnReadWriteUnicast(b *testing.B) {
  57. switch runtime.GOOS {
  58. case "js", "nacl", "plan9", "windows":
  59. b.Skipf("not supported on %s", runtime.GOOS)
  60. }
  61. payload := []byte("HELLO-R-U-THERE")
  62. iph, err := (&ipv4.Header{
  63. Version: ipv4.Version,
  64. Len: ipv4.HeaderLen,
  65. TotalLen: ipv4.HeaderLen + len(payload),
  66. TTL: 1,
  67. Protocol: iana.ProtocolReserved,
  68. Src: net.IPv4(192, 0, 2, 1),
  69. Dst: net.IPv4(192, 0, 2, 254),
  70. }).Marshal()
  71. if err != nil {
  72. b.Fatal(err)
  73. }
  74. greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
  75. datagram := append(greh, append(iph, payload...)...)
  76. bb := make([]byte, 128)
  77. cm := ipv4.ControlMessage{
  78. Src: net.IPv4(127, 0, 0, 1),
  79. }
  80. if ifi := nettest.RoutedInterface("ip4", 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("udp4")
  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 := ipv4.NewPacketConn(c)
  90. dst := c.LocalAddr()
  91. cf := ipv4.FlagTTL | ipv4.FlagInterface
  92. if err := p.SetControlMessage(cf, true); err != nil {
  93. b.Fatal(err)
  94. }
  95. wms := []ipv4.Message{
  96. {
  97. Buffers: [][]byte{payload},
  98. Addr: dst,
  99. OOB: cm.Marshal(),
  100. },
  101. }
  102. rms := []ipv4.Message{
  103. {
  104. Buffers: [][]byte{bb},
  105. OOB: ipv4.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("ip4:%d", iana.ProtocolGRE), "127.0.0.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 := ipv4.NewPacketConn(c)
  152. dst := c.LocalAddr()
  153. cf := ipv4.FlagTTL | ipv4.FlagInterface
  154. if err := p.SetControlMessage(cf, true); err != nil {
  155. b.Fatal(err)
  156. }
  157. wms := []ipv4.Message{
  158. {
  159. Buffers: [][]byte{datagram},
  160. Addr: dst,
  161. OOB: cm.Marshal(),
  162. },
  163. }
  164. rms := []ipv4.Message{
  165. {
  166. Buffers: [][]byte{bb},
  167. OOB: ipv4.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. c, err := nettest.NewLocalPacketListener("udp4")
  208. if err != nil {
  209. t.Fatal(err)
  210. }
  211. defer c.Close()
  212. p := ipv4.NewPacketConn(c)
  213. defer p.Close()
  214. dst := c.LocalAddr()
  215. ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
  216. cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
  217. wb := []byte("HELLO-R-U-THERE")
  218. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  219. if nettest.ProtocolNotSupported(err) {
  220. t.Skipf("not supported on %s", runtime.GOOS)
  221. }
  222. t.Fatal(err)
  223. }
  224. var wg sync.WaitGroup
  225. reader := func() {
  226. defer wg.Done()
  227. rb := make([]byte, 128)
  228. if n, cm, _, err := p.ReadFrom(rb); err != nil {
  229. t.Error(err)
  230. return
  231. } else if !bytes.Equal(rb[:n], wb) {
  232. t.Errorf("got %v; want %v", rb[:n], wb)
  233. return
  234. } else {
  235. s := cm.String()
  236. if strings.Contains(s, ",") {
  237. t.Errorf("should be space-separated values: %s", s)
  238. }
  239. }
  240. }
  241. writer := func(toggle bool) {
  242. defer wg.Done()
  243. cm := ipv4.ControlMessage{
  244. Src: net.IPv4(127, 0, 0, 1),
  245. }
  246. if ifi != nil {
  247. cm.IfIndex = ifi.Index
  248. }
  249. if err := p.SetControlMessage(cf, toggle); err != nil {
  250. t.Error(err)
  251. return
  252. }
  253. if n, err := p.WriteTo(wb, &cm, dst); err != nil {
  254. t.Error(err)
  255. return
  256. } else if n != len(wb) {
  257. t.Errorf("got %d; want %d", n, len(wb))
  258. return
  259. }
  260. }
  261. const N = 10
  262. wg.Add(N)
  263. for i := 0; i < N; i++ {
  264. go reader()
  265. }
  266. wg.Add(2 * N)
  267. for i := 0; i < 2*N; i++ {
  268. go writer(i%2 != 0)
  269. }
  270. wg.Add(N)
  271. for i := 0; i < N; i++ {
  272. go reader()
  273. }
  274. wg.Wait()
  275. }
  276. func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) {
  277. switch runtime.GOOS {
  278. case "js", "nacl", "plan9", "windows":
  279. t.Skipf("not supported on %s", runtime.GOOS)
  280. }
  281. payload := []byte("HELLO-R-U-THERE")
  282. iph, err := (&ipv4.Header{
  283. Version: ipv4.Version,
  284. Len: ipv4.HeaderLen,
  285. TotalLen: ipv4.HeaderLen + len(payload),
  286. TTL: 1,
  287. Protocol: iana.ProtocolReserved,
  288. Src: net.IPv4(192, 0, 2, 1),
  289. Dst: net.IPv4(192, 0, 2, 254),
  290. }).Marshal()
  291. if err != nil {
  292. t.Fatal(err)
  293. }
  294. greh := []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}
  295. datagram := append(greh, append(iph, payload...)...)
  296. t.Run("UDP", func(t *testing.T) {
  297. c, err := nettest.NewLocalPacketListener("udp4")
  298. if err != nil {
  299. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  300. }
  301. defer c.Close()
  302. p := ipv4.NewPacketConn(c)
  303. t.Run("ToFrom", func(t *testing.T) {
  304. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), false)
  305. })
  306. t.Run("Batch", func(t *testing.T) {
  307. testPacketConnConcurrentReadWriteUnicast(t, p, payload, c.LocalAddr(), true)
  308. })
  309. })
  310. t.Run("IP", func(t *testing.T) {
  311. switch runtime.GOOS {
  312. case "netbsd":
  313. t.Skip("need to configure gre on netbsd")
  314. case "openbsd":
  315. t.Skip("net.inet.gre.allow=0 by default on openbsd")
  316. }
  317. c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolGRE), "127.0.0.1")
  318. if err != nil {
  319. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  320. }
  321. defer c.Close()
  322. p := ipv4.NewPacketConn(c)
  323. t.Run("ToFrom", func(t *testing.T) {
  324. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), false)
  325. })
  326. t.Run("Batch", func(t *testing.T) {
  327. testPacketConnConcurrentReadWriteUnicast(t, p, datagram, c.LocalAddr(), true)
  328. })
  329. })
  330. }
  331. func testPacketConnConcurrentReadWriteUnicast(t *testing.T, p *ipv4.PacketConn, data []byte, dst net.Addr, batch bool) {
  332. ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
  333. cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
  334. if err := p.SetControlMessage(cf, true); err != nil { // probe before test
  335. if nettest.ProtocolNotSupported(err) {
  336. t.Skipf("not supported on %s", runtime.GOOS)
  337. }
  338. t.Fatal(err)
  339. }
  340. var wg sync.WaitGroup
  341. reader := func() {
  342. defer wg.Done()
  343. b := make([]byte, 128)
  344. n, cm, _, err := p.ReadFrom(b)
  345. if err != nil {
  346. t.Error(err)
  347. return
  348. }
  349. if !bytes.Equal(b[:n], data) {
  350. t.Errorf("got %#v; want %#v", b[:n], data)
  351. return
  352. }
  353. s := cm.String()
  354. if strings.Contains(s, ",") {
  355. t.Errorf("should be space-separated values: %s", s)
  356. return
  357. }
  358. }
  359. batchReader := func() {
  360. defer wg.Done()
  361. ms := []ipv4.Message{
  362. {
  363. Buffers: [][]byte{make([]byte, 128)},
  364. OOB: ipv4.NewControlMessage(cf),
  365. },
  366. }
  367. n, err := p.ReadBatch(ms, 0)
  368. if err != nil {
  369. t.Error(err)
  370. return
  371. }
  372. if n != len(ms) {
  373. t.Errorf("got %d; want %d", n, len(ms))
  374. return
  375. }
  376. var cm ipv4.ControlMessage
  377. if err := cm.Parse(ms[0].OOB[:ms[0].NN]); err != nil {
  378. t.Error(err)
  379. return
  380. }
  381. var b []byte
  382. if _, ok := dst.(*net.IPAddr); ok {
  383. var h ipv4.Header
  384. if err := h.Parse(ms[0].Buffers[0][:ms[0].N]); err != nil {
  385. t.Error(err)
  386. return
  387. }
  388. b = ms[0].Buffers[0][h.Len:ms[0].N]
  389. } else {
  390. b = ms[0].Buffers[0][:ms[0].N]
  391. }
  392. if !bytes.Equal(b, data) {
  393. t.Errorf("got %#v; want %#v", b, data)
  394. return
  395. }
  396. s := cm.String()
  397. if strings.Contains(s, ",") {
  398. t.Errorf("should be space-separated values: %s", s)
  399. return
  400. }
  401. }
  402. writer := func(toggle bool) {
  403. defer wg.Done()
  404. cm := ipv4.ControlMessage{
  405. Src: net.IPv4(127, 0, 0, 1),
  406. }
  407. if ifi != nil {
  408. cm.IfIndex = ifi.Index
  409. }
  410. if err := p.SetControlMessage(cf, toggle); err != nil {
  411. t.Error(err)
  412. return
  413. }
  414. n, err := p.WriteTo(data, &cm, dst)
  415. if err != nil {
  416. t.Error(err)
  417. return
  418. }
  419. if n != len(data) {
  420. t.Errorf("got %d; want %d", n, len(data))
  421. return
  422. }
  423. }
  424. batchWriter := func(toggle bool) {
  425. defer wg.Done()
  426. cm := ipv4.ControlMessage{
  427. Src: net.IPv4(127, 0, 0, 1),
  428. }
  429. if ifi != nil {
  430. cm.IfIndex = ifi.Index
  431. }
  432. if err := p.SetControlMessage(cf, toggle); err != nil {
  433. t.Error(err)
  434. return
  435. }
  436. ms := []ipv4.Message{
  437. {
  438. Buffers: [][]byte{data},
  439. OOB: cm.Marshal(),
  440. Addr: dst,
  441. },
  442. }
  443. n, err := p.WriteBatch(ms, 0)
  444. if err != nil {
  445. t.Error(err)
  446. return
  447. }
  448. if n != len(ms) {
  449. t.Errorf("got %d; want %d", n, len(ms))
  450. return
  451. }
  452. if ms[0].N != len(data) {
  453. t.Errorf("got %d; want %d", ms[0].N, len(data))
  454. return
  455. }
  456. }
  457. const N = 10
  458. wg.Add(N)
  459. for i := 0; i < N; i++ {
  460. if batch {
  461. go batchReader()
  462. } else {
  463. go reader()
  464. }
  465. }
  466. wg.Add(2 * N)
  467. for i := 0; i < 2*N; i++ {
  468. if batch {
  469. go batchWriter(i%2 != 0)
  470. } else {
  471. go writer(i%2 != 0)
  472. }
  473. }
  474. wg.Add(N)
  475. for i := 0; i < N; i++ {
  476. if batch {
  477. go batchReader()
  478. } else {
  479. go reader()
  480. }
  481. }
  482. wg.Wait()
  483. }