unicast_test.go 8.1 KB

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