readwrite_go1_9_test.go 8.7 KB

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