OLD | NEW |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // +build darwin freebsd linux netbsd openbsd | |
6 | |
7 package ipv4_test | 5 package ipv4_test |
8 | 6 |
9 import ( | 7 import ( |
10 "code.google.com/p/go.net/ipv4" | 8 "code.google.com/p/go.net/ipv4" |
11 "net" | 9 "net" |
12 "os" | 10 "os" |
| 11 "runtime" |
13 "testing" | 12 "testing" |
| 13 "time" |
14 ) | 14 ) |
15 | 15 |
16 func benchmarkUDPListener() (net.PacketConn, net.Addr, error) { | 16 func benchmarkUDPListener() (net.PacketConn, net.Addr, error) { |
17 c, err := net.ListenPacket("udp4", "127.0.0.1:0") | 17 c, err := net.ListenPacket("udp4", "127.0.0.1:0") |
18 if err != nil { | 18 if err != nil { |
19 return nil, nil, err | 19 return nil, nil, err |
20 } | 20 } |
21 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String()) | 21 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String()) |
22 if err != nil { | 22 if err != nil { |
23 c.Close() | 23 c.Close() |
(...skipping 26 matching lines...) Expand all Loading... |
50 } | 50 } |
51 | 51 |
52 func BenchmarkReadWriteIPv4UDP(b *testing.B) { | 52 func BenchmarkReadWriteIPv4UDP(b *testing.B) { |
53 c, dst, err := benchmarkUDPListener() | 53 c, dst, err := benchmarkUDPListener() |
54 if err != nil { | 54 if err != nil { |
55 b.Fatalf("benchmarkUDPListener failed: %v", err) | 55 b.Fatalf("benchmarkUDPListener failed: %v", err) |
56 } | 56 } |
57 defer c.Close() | 57 defer c.Close() |
58 | 58 |
59 p := ipv4.NewPacketConn(c) | 59 p := ipv4.NewPacketConn(c) |
| 60 defer p.Close() |
60 cf := ipv4.FlagTTL | ipv4.FlagInterface | 61 cf := ipv4.FlagTTL | ipv4.FlagInterface |
61 if err := p.SetControlMessage(cf, true); err != nil { | 62 if err := p.SetControlMessage(cf, true); err != nil { |
62 b.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err) | 63 b.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v", err) |
63 } | 64 } |
64 ifi := loopbackInterface() | 65 ifi := loopbackInterface() |
65 | 66 |
66 wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128) | 67 wb, rb := []byte("HELLO-R-U-THERE"), make([]byte, 128) |
67 b.ResetTimer() | 68 b.ResetTimer() |
68 for i := 0; i < b.N; i++ { | 69 for i := 0; i < b.N; i++ { |
69 benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi) | 70 benchmarkReadWriteIPv4UDP(b, p, wb, rb, dst, ifi) |
70 } | 71 } |
71 } | 72 } |
72 | 73 |
73 func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte,
dst net.Addr, ifi *net.Interface) { | 74 func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte,
dst net.Addr, ifi *net.Interface) { |
74 cm := ipv4.ControlMessage{TTL: 1} | 75 cm := ipv4.ControlMessage{TTL: 1} |
75 if ifi != nil { | 76 if ifi != nil { |
76 cm.IfIndex = ifi.Index | 77 cm.IfIndex = ifi.Index |
77 } | 78 } |
78 if _, err := p.WriteTo(wb, &cm, dst); err != nil { | 79 if _, err := p.WriteTo(wb, &cm, dst); err != nil { |
79 b.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) | 80 b.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) |
80 } | 81 } |
81 if _, _, _, err := p.ReadFrom(rb); err != nil { | 82 if _, _, _, err := p.ReadFrom(rb); err != nil { |
82 b.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) | 83 b.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) |
83 } | 84 } |
84 } | 85 } |
85 | 86 |
86 func TestReadWriteUnicastIPPayloadUDP(t *testing.T) { | 87 func TestPacketConnReadWriteUnicastUDP(t *testing.T) { |
| 88 » switch runtime.GOOS { |
| 89 » case "plan9", "windows": |
| 90 » » t.Skipf("not supported on %q", runtime.GOOS) |
| 91 » } |
| 92 » if !supportsIPv4 { |
| 93 » » t.Skip("ipv4 is not supported") |
| 94 » } |
| 95 » ifi := loopbackInterface() |
| 96 » if ifi == nil { |
| 97 » » t.Skipf("not available on %q", runtime.GOOS) |
| 98 » } |
| 99 |
87 c, err := net.ListenPacket("udp4", "127.0.0.1:0") | 100 c, err := net.ListenPacket("udp4", "127.0.0.1:0") |
88 if err != nil { | 101 if err != nil { |
89 t.Fatalf("net.ListenPacket failed: %v", err) | 102 t.Fatalf("net.ListenPacket failed: %v", err) |
90 } | 103 } |
91 defer c.Close() | 104 defer c.Close() |
92 | 105 |
93 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String()) | 106 dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String()) |
94 if err != nil { | 107 if err != nil { |
95 t.Fatalf("net.ResolveUDPAddr failed: %v", err) | 108 t.Fatalf("net.ResolveUDPAddr failed: %v", err) |
96 } | 109 } |
97 p := ipv4.NewPacketConn(c) | 110 p := ipv4.NewPacketConn(c) |
| 111 defer p.Close() |
98 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface | 112 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface |
| 113 |
99 for i, toggle := range []bool{true, false, true} { | 114 for i, toggle := range []bool{true, false, true} { |
100 if err := p.SetControlMessage(cf, toggle); err != nil { | 115 if err := p.SetControlMessage(cf, toggle); err != nil { |
101 t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v",
err) | 116 t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v",
err) |
102 } | 117 } |
103 » » writeThenReadPayload(t, i, p, []byte("HELLO-R-U-THERE"), dst) | 118 » » p.SetTTL(i + 1) |
| 119 » » if err := p.SetWriteDeadline(time.Now().Add(time.Millisecond * 1
00)); err != nil { |
| 120 » » » t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v",
err) |
| 121 » » } |
| 122 » » if _, err := p.WriteTo([]byte("HELLO-R-U-THERE"), nil, dst); err
!= nil { |
| 123 » » » t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) |
| 124 » » } |
| 125 » » b := make([]byte, 128) |
| 126 » » if err := p.SetReadDeadline(time.Now().Add(time.Millisecond * 10
0)); err != nil { |
| 127 » » » t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", e
rr) |
| 128 » » } |
| 129 » » if _, cm, _, err := p.ReadFrom(b); err != nil { |
| 130 » » » t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) |
| 131 » » } else { |
| 132 » » » t.Logf("rcvd cmsg: %v", cm) |
| 133 » » } |
104 } | 134 } |
105 } | 135 } |
106 | 136 |
107 func TestReadWriteUnicastIPPayloadICMP(t *testing.T) { | 137 func TestPacketConnReadWriteUnicastICMP(t *testing.T) { |
| 138 » switch runtime.GOOS { |
| 139 » case "plan9", "windows": |
| 140 » » t.Skipf("not supported on %q", runtime.GOOS) |
| 141 » } |
| 142 » if !supportsIPv4 { |
| 143 » » t.Skip("ipv4 is not supported") |
| 144 » } |
108 if os.Getuid() != 0 { | 145 if os.Getuid() != 0 { |
109 t.Skip("must be root") | 146 t.Skip("must be root") |
110 } | 147 } |
| 148 ifi := loopbackInterface() |
| 149 if ifi == nil { |
| 150 t.Skipf("not available on %q", runtime.GOOS) |
| 151 } |
111 | 152 |
112 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") | 153 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") |
113 if err != nil { | 154 if err != nil { |
114 t.Fatalf("net.ListenPacket failed: %v", err) | 155 t.Fatalf("net.ListenPacket failed: %v", err) |
115 } | 156 } |
116 defer c.Close() | 157 defer c.Close() |
117 | 158 |
118 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") | 159 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") |
119 if err != nil { | 160 if err != nil { |
120 t.Fatalf("ResolveIPAddr failed: %v", err) | 161 t.Fatalf("ResolveIPAddr failed: %v", err) |
121 } | 162 } |
122 p := ipv4.NewPacketConn(c) | 163 p := ipv4.NewPacketConn(c) |
| 164 defer p.Close() |
123 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface | 165 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface |
| 166 |
124 for i, toggle := range []bool{true, false, true} { | 167 for i, toggle := range []bool{true, false, true} { |
125 wb, err := (&icmpMessage{ | 168 wb, err := (&icmpMessage{ |
126 Type: ipv4.ICMPTypeEcho, Code: 0, | 169 Type: ipv4.ICMPTypeEcho, Code: 0, |
127 Body: &icmpEcho{ | 170 Body: &icmpEcho{ |
128 ID: os.Getpid() & 0xffff, Seq: i + 1, | 171 ID: os.Getpid() & 0xffff, Seq: i + 1, |
129 Data: []byte("HELLO-R-U-THERE"), | 172 Data: []byte("HELLO-R-U-THERE"), |
130 }, | 173 }, |
131 }).Marshal() | 174 }).Marshal() |
132 if err != nil { | 175 if err != nil { |
133 t.Fatalf("icmpMessage.Marshal failed: %v", err) | 176 t.Fatalf("icmpMessage.Marshal failed: %v", err) |
134 } | 177 } |
135 if err := p.SetControlMessage(cf, toggle); err != nil { | 178 if err := p.SetControlMessage(cf, toggle); err != nil { |
136 t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v",
err) | 179 t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v",
err) |
137 } | 180 } |
138 » » rb := writeThenReadPayload(t, i, p, wb, dst) | 181 » » p.SetTTL(i + 1) |
139 » » m, err := parseICMPMessage(rb) | 182 » » if err := p.SetWriteDeadline(time.Now().Add(time.Millisecond * 1
00)); err != nil { |
140 » » if err != nil { | 183 » » » t.Fatalf("ipv4.PacketConn.SetWriteDeadline failed: %v",
err) |
141 » » » t.Fatalf("parseICMPMessage failed: %v", err) | |
142 } | 184 } |
143 » » if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { | 185 » » if _, err := p.WriteTo(wb, nil, dst); err != nil { |
144 » » » t.Fatalf("got type=%v, code=%v; expected type=%v, code=%
v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) | 186 » » » t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) |
| 187 » » } |
| 188 » » b := make([]byte, 128) |
| 189 » loop: |
| 190 » » if err := p.SetReadDeadline(time.Now().Add(time.Millisecond * 10
0)); err != nil { |
| 191 » » » t.Fatalf("ipv4.PacketConn.SetReadDeadline failed: %v", e
rr) |
| 192 » » } |
| 193 » » if n, cm, _, err := p.ReadFrom(b); err != nil { |
| 194 » » » t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) |
| 195 » » } else { |
| 196 » » » t.Logf("rcvd cmsg: %v", cm) |
| 197 » » » m, err := parseICMPMessage(b[:n]) |
| 198 » » » if err != nil { |
| 199 » » » » t.Fatalf("parseICMPMessage failed: %v", err) |
| 200 » » » } |
| 201 » » » if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEch
o { |
| 202 » » » » // On Linux we must handle own sent packets. |
| 203 » » » » goto loop |
| 204 » » » } |
| 205 » » » if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { |
| 206 » » » » t.Fatalf("got type=%v, code=%v; expected type=%v
, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) |
| 207 » » » } |
145 } | 208 } |
146 } | 209 } |
147 } | 210 } |
148 | 211 |
149 func TestReadWriteUnicastIPDatagram(t *testing.T) { | 212 func TestRawConnReadWriteUnicastICMP(t *testing.T) { |
| 213 » switch runtime.GOOS { |
| 214 » case "plan9", "windows": |
| 215 » » t.Skipf("not supported on %q", runtime.GOOS) |
| 216 » } |
| 217 » if !supportsIPv4 { |
| 218 » » t.Skip("ipv4 is not supported") |
| 219 » } |
150 if os.Getuid() != 0 { | 220 if os.Getuid() != 0 { |
151 t.Skip("must be root") | 221 t.Skip("must be root") |
152 } | 222 } |
| 223 ifi := loopbackInterface() |
| 224 if ifi == nil { |
| 225 t.Skipf("not available on %q", runtime.GOOS) |
| 226 } |
153 | 227 |
154 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") | 228 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") |
155 if err != nil { | 229 if err != nil { |
156 t.Fatalf("net.ListenPacket failed: %v", err) | 230 t.Fatalf("net.ListenPacket failed: %v", err) |
157 } | 231 } |
158 defer c.Close() | 232 defer c.Close() |
159 | 233 |
160 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") | 234 dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") |
161 if err != nil { | 235 if err != nil { |
162 t.Fatalf("ResolveIPAddr failed: %v", err) | 236 t.Fatalf("ResolveIPAddr failed: %v", err) |
163 } | 237 } |
164 r, err := ipv4.NewRawConn(c) | 238 r, err := ipv4.NewRawConn(c) |
165 if err != nil { | 239 if err != nil { |
166 t.Fatalf("ipv4.NewRawConn failed: %v", err) | 240 t.Fatalf("ipv4.NewRawConn failed: %v", err) |
167 } | 241 } |
| 242 defer r.Close() |
168 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface | 243 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface |
| 244 |
169 for i, toggle := range []bool{true, false, true} { | 245 for i, toggle := range []bool{true, false, true} { |
170 wb, err := (&icmpMessage{ | 246 wb, err := (&icmpMessage{ |
171 Type: ipv4.ICMPTypeEcho, Code: 0, | 247 Type: ipv4.ICMPTypeEcho, Code: 0, |
172 Body: &icmpEcho{ | 248 Body: &icmpEcho{ |
173 ID: os.Getpid() & 0xffff, Seq: i + 1, | 249 ID: os.Getpid() & 0xffff, Seq: i + 1, |
174 Data: []byte("HELLO-R-U-THERE"), | 250 Data: []byte("HELLO-R-U-THERE"), |
175 }, | 251 }, |
176 }).Marshal() | 252 }).Marshal() |
177 if err != nil { | 253 if err != nil { |
178 t.Fatalf("icmpMessage.Marshal failed: %v", err) | 254 t.Fatalf("icmpMessage.Marshal failed: %v", err) |
179 } | 255 } |
| 256 wh := &ipv4.Header{ |
| 257 Version: ipv4.Version, |
| 258 Len: ipv4.HeaderLen, |
| 259 TOS: i + 1, |
| 260 TotalLen: ipv4.HeaderLen + len(wb), |
| 261 TTL: i + 1, |
| 262 Protocol: 1, |
| 263 Dst: dst.IP, |
| 264 } |
180 if err := r.SetControlMessage(cf, toggle); err != nil { | 265 if err := r.SetControlMessage(cf, toggle); err != nil { |
181 t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", er
r) | 266 t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", er
r) |
182 } | 267 } |
183 » » rb := writeThenReadDatagram(t, i, r, wb, nil, dst) | 268 » » if err := r.SetWriteDeadline(time.Now().Add(time.Millisecond * 1
00)); err != nil { |
184 » » m, err := parseICMPMessage(rb) | 269 » » » t.Fatalf("ipv4.RawConn.SetWriteDeadline failed: %v", err
) |
185 » » if err != nil { | |
186 » » » t.Fatalf("parseICMPMessage failed: %v", err) | |
187 } | 270 } |
188 » » if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { | 271 » » if err := r.WriteTo(wh, wb, nil); err != nil { |
189 » » » t.Fatalf("got type=%v, code=%v; expected type=%v, code=%
v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) | 272 » » » t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err) |
| 273 » » } |
| 274 » » rb := make([]byte, ipv4.HeaderLen+128) |
| 275 » loop: |
| 276 » » if err := r.SetReadDeadline(time.Now().Add(time.Millisecond * 10
0)); err != nil { |
| 277 » » » t.Fatalf("ipv4.RawConn.SetReadDeadline failed: %v", err) |
| 278 » » } |
| 279 » » if _, b, cm, err := r.ReadFrom(rb); err != nil { |
| 280 » » » t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err) |
| 281 » » } else { |
| 282 » » » t.Logf("rcvd cmsg: %v", cm) |
| 283 » » » m, err := parseICMPMessage(b) |
| 284 » » » if err != nil { |
| 285 » » » » t.Fatalf("parseICMPMessage failed: %v", err) |
| 286 » » » } |
| 287 » » » if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEch
o { |
| 288 » » » » // On Linux we must handle own sent packets. |
| 289 » » » » goto loop |
| 290 » » » } |
| 291 » » » if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { |
| 292 » » » » t.Fatalf("got type=%v, code=%v; expected type=%v
, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) |
| 293 » » » } |
190 } | 294 } |
191 } | 295 } |
192 } | 296 } |
OLD | NEW |