unicast_test.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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. "code.google.com/p/go.net/ipv4"
  7. "net"
  8. "os"
  9. "runtime"
  10. "testing"
  11. "time"
  12. )
  13. func benchmarkUDPListener() (net.PacketConn, net.Addr, error) {
  14. c, err := net.ListenPacket("udp4", "127.0.0.1:0")
  15. if err != nil {
  16. return nil, nil, err
  17. }
  18. dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
  19. if err != nil {
  20. c.Close()
  21. return nil, nil, err
  22. }
  23. return c, dst, nil
  24. }
  25. func BenchmarkReadWriteNetUDP(b *testing.B) {
  26. c, dst, err := benchmarkUDPListener()
  27. if err != nil {
  28. b.Fatalf("benchmarkUDPListener failed: %v", err)
  29. }
  30. defer c.Close()
  31. wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
  32. b.ResetTimer()
  33. for i := 0; i < b.N; i++ {
  34. benchmarkReadWriteNetUDP(b, c, wb, rb, dst)
  35. }
  36. }
  37. func benchmarkReadWriteNetUDP(b *testing.B, c net.PacketConn, wb, rb []byte, dst net.Addr) {
  38. if _, err := c.WriteTo(wb, dst); err != nil {
  39. b.Fatalf("net.PacketConn.WriteTo failed: %v", err)
  40. }
  41. if _, _, err := c.ReadFrom(rb); err != nil {
  42. b.Fatalf("net.PacketConn.ReadFrom failed: %v", err)
  43. }
  44. }
  45. func BenchmarkReadWriteIPv4UDP(b *testing.B) {
  46. c, dst, err := benchmarkUDPListener()
  47. if err != nil {
  48. b.Fatalf("benchmarkUDPListener failed: %v", err)
  49. }
  50. defer c.Close()
  51. p := ipv4.NewPacketConn(c)
  52. defer p.Close()
  53. cf := ipv4.FlagTTL | ipv4.FlagInterface
  54. if err := p.SetControlMessage(cf, true); err != nil {
  55. b.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
  56. }
  57. ifi := loopbackInterface()
  58. wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128)
  59. b.ResetTimer()
  60. for i := 0; i < b.N; i++ {
  61. benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi)
  62. }
  63. }
  64. func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
  65. cm := ipv4.ControlMessage{TTL: 1}
  66. if ifi != nil {
  67. cm.IfIndex = ifi.Index
  68. }
  69. if _, err := p.WriteTo(wb, &cm, dst); err != nil {
  70. b.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
  71. }
  72. if _, _, _, err := p.ReadFrom(rb); err != nil {
  73. b.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
  74. }
  75. }
  76. func TestPacketConnReadWriteUnicastUDP(t *testing.T) {
  77. switch runtime.GOOS {
  78. case "plan9", "windows":
  79. t.Skipf("not supported on %q", runtime.GOOS)
  80. }
  81. ifi := loopbackInterface()
  82. if ifi == nil {
  83. t.Skipf("not available on %q", runtime.GOOS)
  84. }
  85. c, err := net.ListenPacket("udp4", "127.0.0.1:0")
  86. if err != nil {
  87. t.Fatalf("net.ListenPacket failed: %v", err)
  88. }
  89. defer c.Close()
  90. dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
  91. if err != nil {
  92. t.Fatalf("net.ResolveUDPAddr failed: %v", err)
  93. }
  94. p := ipv4.NewPacketConn(c)
  95. defer p.Close()
  96. cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
  97. for i, toggle := range []bool{true, false, true} {
  98. if err := p.SetControlMessage(cf, toggle); err != nil {
  99. t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
  100. }
  101. p.SetTTL(i + 1)
  102. if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  103. t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v", err)
  104. }
  105. if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), nil, dst); err != nil {
  106. t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
  107. }
  108. rb := make([]byte, 128)
  109. if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  110. t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", err)
  111. }
  112. if _, cm, _, err := p.ReadFrom(rb); err != nil {
  113. t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
  114. } else {
  115. t.Logf("rcvd cmsg: %v", cm)
  116. }
  117. }
  118. }
  119. func TestPacketConnReadWriteUnicastICMP(t *testing.T) {
  120. switch runtime.GOOS {
  121. case "plan9", "windows":
  122. t.Skipf("not supported on %q", runtime.GOOS)
  123. }
  124. if os.Getuid() != 0 {
  125. t.Skip("must be root")
  126. }
  127. ifi := loopbackInterface()
  128. if ifi == nil {
  129. t.Skipf("not available on %q", runtime.GOOS)
  130. }
  131. c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
  132. if err != nil {
  133. t.Fatalf("net.ListenPacket failed: %v", err)
  134. }
  135. defer c.Close()
  136. dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
  137. if err != nil {
  138. t.Fatalf("ResolveIPAddr failed: %v", err)
  139. }
  140. p := ipv4.NewPacketConn(c)
  141. defer p.Close()
  142. cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
  143. for i, toggle := range []bool{true, false, true} {
  144. wb, err := (&icmpMessage{
  145. Type: ipv4.ICMPTypeEcho, Code: 0,
  146. Body: &icmpEcho{
  147. ID: os.Getpid() & 0xffff, Seq: i + 1,
  148. Data: []byte("HELLO-R-U-THERE"),
  149. },
  150. }).Marshal()
  151. if err != nil {
  152. t.Fatalf("icmpMessage.Marshal failed: %v", err)
  153. }
  154. if err := p.SetControlMessage(cf, toggle); err != nil {
  155. t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err)
  156. }
  157. p.SetTTL(i + 1)
  158. if err := p.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  159. t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v", err)
  160. }
  161. if _, err := p.WriteTo(wb, nil, dst); err != nil {
  162. t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err)
  163. }
  164. b := make([]byte, 128)
  165. loop:
  166. if err := p.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  167. t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", err)
  168. }
  169. if n, cm, _, err := p.ReadFrom(b); err != nil {
  170. t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err)
  171. } else {
  172. t.Logf("rcvd cmsg: %v", cm)
  173. m, err := parseICMPMessage(b[:n])
  174. if err != nil {
  175. t.Fatalf("parseICMPMessage failed: %v", err)
  176. }
  177. if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
  178. // On Linux we must handle own sent packets.
  179. goto loop
  180. }
  181. if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
  182. t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
  183. }
  184. }
  185. }
  186. }
  187. func TestRawConnReadWriteUnicastICMP(t *testing.T) {
  188. switch runtime.GOOS {
  189. case "plan9", "windows":
  190. t.Skipf("not supported on %q", runtime.GOOS)
  191. }
  192. if os.Getuid() != 0 {
  193. t.Skip("must be root")
  194. }
  195. ifi := loopbackInterface()
  196. if ifi == nil {
  197. t.Skipf("not available on %q", runtime.GOOS)
  198. }
  199. c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
  200. if err != nil {
  201. t.Fatalf("net.ListenPacket failed: %v", err)
  202. }
  203. defer c.Close()
  204. dst, err := net.ResolveIPAddr("ip4", "127.0.0.1")
  205. if err != nil {
  206. t.Fatalf("ResolveIPAddr failed: %v", err)
  207. }
  208. r, err := ipv4.NewRawConn(c)
  209. if err != nil {
  210. t.Fatalf("ipv4.NewRawConn failed: %v", err)
  211. }
  212. defer r.Close()
  213. cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
  214. for i, toggle := range []bool{true, false, true} {
  215. wb, err := (&icmpMessage{
  216. Type: ipv4.ICMPTypeEcho, Code: 0,
  217. Body: &icmpEcho{
  218. ID: os.Getpid() & 0xffff, Seq: i + 1,
  219. Data: []byte("HELLO-R-U-THERE"),
  220. },
  221. }).Marshal()
  222. if err != nil {
  223. t.Fatalf("icmpMessage.Marshal failed: %v", err)
  224. }
  225. wh := &ipv4.Header{
  226. Version: ipv4.Version,
  227. Len: ipv4.HeaderLen,
  228. TOS: i + 1,
  229. TotalLen: ipv4.HeaderLen + len(wb),
  230. TTL: i + 1,
  231. Protocol: 1,
  232. Dst: dst.IP,
  233. }
  234. if err := r.SetControlMessage(cf, toggle); err != nil {
  235. t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", err)
  236. }
  237. if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  238. t.Fatalf("ipv4.RawConn.SetWriteDeadline failed: %v", err)
  239. }
  240. if err := r.WriteTo(wh, wb, nil); err != nil {
  241. t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err)
  242. }
  243. rb := make([]byte, ipv4.HeaderLen+128)
  244. loop:
  245. if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil {
  246. t.Fatalf("ipv4.RawConn.SetReadDeadline failed: %v", err)
  247. }
  248. if _, b, cm, err := r.ReadFrom(rb); err != nil {
  249. t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err)
  250. } else {
  251. t.Logf("rcvd cmsg: %v", cm)
  252. m, err := parseICMPMessage(b)
  253. if err != nil {
  254. t.Fatalf("parseICMPMessage failed: %v", err)
  255. }
  256. if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho {
  257. // On Linux we must handle own sent packets.
  258. goto loop
  259. }
  260. if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 {
  261. t.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
  262. }
  263. }
  264. }
  265. }