25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

517 satır
12 KiB

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