Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 1 | // Copyright 2011 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 | |
| 5 | package net |
| 6 | |
| 7 | import ( |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 8 | "reflect" |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 9 | "runtime" |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 10 | "testing" |
| 11 | ) |
| 12 | |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 13 | // loopbackInterface returns an available logical network interface |
| 14 | // for loopback tests. It returns nil if no suitable interface is |
| 15 | // found. |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 16 | func loopbackInterface() *Interface { |
| 17 | ift, err := Interfaces() |
| 18 | if err != nil { |
| 19 | return nil |
| 20 | } |
| 21 | for _, ifi := range ift { |
| 22 | if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 { |
| 23 | return &ifi |
| 24 | } |
| 25 | } |
| 26 | return nil |
| 27 | } |
| 28 | |
Mikio Hara | aa0dda7 | 2013-03-23 09:57:40 +0900 | [diff] [blame] | 29 | // ipv6LinkLocalUnicastAddr returns an IPv6 link-local unicast address |
| 30 | // on the given network interface for tests. It returns "" if no |
| 31 | // suitable address is found. |
| 32 | func ipv6LinkLocalUnicastAddr(ifi *Interface) string { |
| 33 | if ifi == nil { |
| 34 | return "" |
| 35 | } |
| 36 | ifat, err := ifi.Addrs() |
| 37 | if err != nil { |
| 38 | return "" |
| 39 | } |
| 40 | for _, ifa := range ifat { |
mattn | ea22a08 | 2015-01-19 16:56:04 +0900 | [diff] [blame] | 41 | if ifa, ok := ifa.(*IPNet); ok { |
Mikio Hara | aa0dda7 | 2013-03-23 09:57:40 +0900 | [diff] [blame] | 42 | if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() { |
| 43 | return ifa.IP.String() |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | return "" |
| 48 | } |
| 49 | |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 50 | type routeStats struct { |
| 51 | loop int // # of active loopback interfaces |
| 52 | other int // # of active other interfaces |
| 53 | |
| 54 | uni4, uni6 int // # of active connected unicast, anycast routes |
| 55 | multi4, multi6 int // # of active connected multicast route clones |
| 56 | } |
| 57 | |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 58 | func TestInterfaces(t *testing.T) { |
| 59 | ift, err := Interfaces() |
| 60 | if err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 61 | t.Fatal(err) |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 62 | } |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 63 | var stats routeStats |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 64 | for _, ifi := range ift { |
| 65 | ifxi, err := InterfaceByIndex(ifi.Index) |
| 66 | if err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 67 | t.Fatal(err) |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 68 | } |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 69 | if !reflect.DeepEqual(ifxi, &ifi) { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 70 | t.Errorf("got %v; want %v", ifxi, ifi) |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 71 | } |
| 72 | ifxn, err := InterfaceByName(ifi.Name) |
| 73 | if err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 74 | t.Fatal(err) |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 75 | } |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 76 | if !reflect.DeepEqual(ifxn, &ifi) { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 77 | t.Errorf("got %v; want %v", ifxn, ifi) |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 78 | } |
Mikio Hara | 3a112a8 | 2012-07-22 01:49:58 +0900 | [diff] [blame] | 79 | t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 80 | t.Logf("hardware address %q", ifi.HardwareAddr.String()) |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 81 | if ifi.Flags&FlagUp != 0 { |
| 82 | if ifi.Flags&FlagLoopback != 0 { |
| 83 | stats.loop++ |
| 84 | } else { |
| 85 | stats.other++ |
| 86 | } |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 87 | } |
| 88 | n4, n6 := testInterfaceAddrs(t, &ifi) |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 89 | stats.uni4 += n4 |
| 90 | stats.uni6 += n6 |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 91 | n4, n6 = testInterfaceMulticastAddrs(t, &ifi) |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 92 | stats.multi4 += n4 |
| 93 | stats.multi6 += n6 |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 94 | } |
| 95 | switch runtime.GOOS { |
| 96 | case "nacl", "plan9", "solaris": |
| 97 | default: |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 98 | // Test the existence of connected unicast routes for |
| 99 | // IPv4. |
| 100 | if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 { |
| 101 | t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 102 | } |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 103 | // Test the existence of connected unicast routes for |
| 104 | // IPv6. We can assume the existence of ::1/128 when |
| 105 | // at least one looopback interface is installed. |
| 106 | if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 { |
| 107 | t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 108 | } |
| 109 | } |
| 110 | switch runtime.GOOS { |
| 111 | case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris": |
| 112 | default: |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 113 | // Test the existence of connected multicast route |
| 114 | // clones for IPv4. Unlike IPv6, IPv4 multicast |
| 115 | // capability is not a mandatory feature, and so this |
| 116 | // test is disabled. |
| 117 | //if supportsIPv4 && stats.loop > 0 && stats.uni4 > 1 && stats.multi4 == 0 { |
| 118 | // t.Errorf("num IPv4 multicast route clones = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 119 | //} |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 120 | // Test the existence of connected multicast route |
| 121 | // clones for IPv6. Some platform never uses loopback |
| 122 | // interface as the nexthop for multicast routing. |
| 123 | // We can assume the existence of connected multicast |
| 124 | // route clones when at least two connected unicast |
| 125 | // routes, ::1/128 and other, are installed. |
| 126 | if supportsIPv6 && stats.loop > 0 && stats.uni6 > 1 && stats.multi6 == 0 { |
| 127 | t.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 128 | } |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 129 | } |
| 130 | } |
| 131 | |
| 132 | func TestInterfaceAddrs(t *testing.T) { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 133 | ift, err := Interfaces() |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 134 | if err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 135 | t.Fatal(err) |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 136 | } |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 137 | var stats routeStats |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 138 | for _, ifi := range ift { |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 139 | if ifi.Flags&FlagUp != 0 { |
| 140 | if ifi.Flags&FlagLoopback != 0 { |
| 141 | stats.loop++ |
| 142 | } else { |
| 143 | stats.other++ |
| 144 | } |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 145 | } |
| 146 | } |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 147 | ifat, err := InterfaceAddrs() |
| 148 | if err != nil { |
| 149 | t.Fatal(err) |
| 150 | } |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 151 | stats.uni4, stats.uni6 = testAddrs(t, ifat) |
| 152 | // Test the existence of connected unicast routes for IPv4. |
| 153 | if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 { |
| 154 | t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 155 | } |
Mikio Hara | 14082fa | 2015-03-23 06:43:43 +0900 | [diff] [blame] | 156 | // Test the existence of connected unicast routes for IPv6. |
| 157 | // We can assume the existence of ::1/128 when at least one |
| 158 | // looopback interface is installed. |
| 159 | if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 { |
| 160 | t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats) |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 161 | } |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 162 | } |
| 163 | |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 164 | func testInterfaceAddrs(t *testing.T, ifi *Interface) (naf4, naf6 int) { |
| 165 | ifat, err := ifi.Addrs() |
| 166 | if err != nil { |
| 167 | t.Fatal(err) |
| 168 | } |
| 169 | return testAddrs(t, ifat) |
| 170 | } |
| 171 | |
| 172 | func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) (nmaf4, nmaf6 int) { |
| 173 | ifmat, err := ifi.MulticastAddrs() |
| 174 | if err != nil { |
| 175 | t.Fatal(err) |
| 176 | } |
| 177 | return testMulticastAddrs(t, ifmat) |
| 178 | } |
| 179 | |
| 180 | func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) { |
| 181 | for _, ifa := range ifat { |
| 182 | switch ifa := ifa.(type) { |
| 183 | case *IPNet: |
| 184 | if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || ifa.IP.IsMulticast() || ifa.Mask == nil { |
| 185 | t.Errorf("unexpected value: %#v", ifa) |
| 186 | continue |
| 187 | } |
| 188 | prefixLen, maxPrefixLen := ifa.Mask.Size() |
| 189 | if ifa.IP.To4() != nil { |
| 190 | if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len { |
| 191 | t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen) |
| 192 | continue |
| 193 | } |
| 194 | naf4++ |
| 195 | } else if ifa.IP.To16() != nil { |
| 196 | if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len { |
| 197 | t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen) |
| 198 | continue |
| 199 | } |
| 200 | naf6++ |
| 201 | } |
| 202 | t.Logf("interface address %q", ifa.String()) |
| 203 | default: |
| 204 | t.Errorf("unexpected type: %T", ifa) |
| 205 | } |
| 206 | } |
| 207 | return |
| 208 | } |
| 209 | |
| 210 | func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) { |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 211 | for _, ifma := range ifmat { |
Mikio Hara | aa0dda7 | 2013-03-23 09:57:40 +0900 | [diff] [blame] | 212 | switch ifma := ifma.(type) { |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 213 | case *IPAddr: |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 214 | if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() { |
| 215 | t.Errorf("unexpected value: %#v", ifma) |
| 216 | continue |
Mikio Hara | 12e7397 | 2013-01-23 07:11:22 +0900 | [diff] [blame] | 217 | } |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 218 | if ifma.IP.To4() != nil { |
| 219 | nmaf4++ |
| 220 | } else if ifma.IP.To16() != nil { |
| 221 | nmaf6++ |
| 222 | } |
| 223 | t.Logf("joined group address %q", ifma.String()) |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 224 | default: |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 225 | t.Errorf("unexpected type: %T", ifma) |
Mikio Hara | 8361056 | 2011-12-21 21:39:00 +0900 | [diff] [blame] | 226 | } |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 227 | } |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 228 | return |
Mikio Hara | 518331d | 2011-06-03 14:35:42 -0400 | [diff] [blame] | 229 | } |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 230 | |
| 231 | func BenchmarkInterfaces(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 232 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 233 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 234 | for i := 0; i < b.N; i++ { |
| 235 | if _, err := Interfaces(); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 236 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 237 | } |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | func BenchmarkInterfaceByIndex(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 242 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 243 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 244 | ifi := loopbackInterface() |
| 245 | if ifi == nil { |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 246 | b.Skip("loopback interface not found") |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 247 | } |
| 248 | for i := 0; i < b.N; i++ { |
| 249 | if _, err := InterfaceByIndex(ifi.Index); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 250 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 251 | } |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | func BenchmarkInterfaceByName(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 256 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 257 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 258 | ifi := loopbackInterface() |
| 259 | if ifi == nil { |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 260 | b.Skip("loopback interface not found") |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 261 | } |
| 262 | for i := 0; i < b.N; i++ { |
| 263 | if _, err := InterfaceByName(ifi.Name); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 264 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 265 | } |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | func BenchmarkInterfaceAddrs(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 270 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 271 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 272 | for i := 0; i < b.N; i++ { |
| 273 | if _, err := InterfaceAddrs(); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 274 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 275 | } |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | func BenchmarkInterfacesAndAddrs(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 280 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 281 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 282 | ifi := loopbackInterface() |
| 283 | if ifi == nil { |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 284 | b.Skip("loopback interface not found") |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 285 | } |
| 286 | for i := 0; i < b.N; i++ { |
| 287 | if _, err := ifi.Addrs(); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 288 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 289 | } |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) { |
Mikio Hara | ef54930 | 2015-05-14 09:25:24 +0900 | [diff] [blame] | 294 | testHookUninstaller.Do(uninstallTestHooks) |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 295 | |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 296 | ifi := loopbackInterface() |
| 297 | if ifi == nil { |
Mikio Hara | cd81db8 | 2013-02-25 23:05:40 +0900 | [diff] [blame] | 298 | b.Skip("loopback interface not found") |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 299 | } |
| 300 | for i := 0; i < b.N; i++ { |
| 301 | if _, err := ifi.MulticastAddrs(); err != nil { |
Mikio Hara | bed884e | 2015-01-26 18:04:44 +0900 | [diff] [blame] | 302 | b.Fatal(err) |
Mikio Hara | 0ad88a4 | 2013-02-22 01:19:04 +0900 | [diff] [blame] | 303 | } |
| 304 | } |
| 305 | } |