github.com/gopacket/gopacket@v1.1.0/routing/routing_test.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. 6 7 //go:build linux 8 // +build linux 9 10 package routing 11 12 import ( 13 "fmt" 14 "net" 15 "runtime" 16 "sort" 17 "testing" 18 19 "github.com/vishvananda/netlink" 20 "github.com/vishvananda/netns" 21 ) 22 23 func TestPrivateRoute(t *testing.T) { 24 tests := []struct { 25 name string 26 router router 27 routes routeSlice 28 input net.HardwareAddr 29 src, dst net.IP 30 wantIface int 31 wantGateway, wantPreferredSrc net.IP 32 wantErr error 33 }{ 34 { 35 name: "only static routes", 36 router: router{ 37 ifaces: map[int]*net.Interface{ 38 1: { 39 Index: 1, 40 MTU: 1500, 41 Name: "eth0", 42 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 43 Flags: net.FlagUp, 44 }, 45 2: { 46 Index: 2, 47 MTU: 1500, 48 Name: "eth1", 49 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02}, 50 Flags: net.FlagUp, 51 }, 52 }, 53 addrs: map[int]ipAddrs{ 54 1: { 55 v4: net.ParseIP("192.168.10.1/24"), 56 }, 57 2: { 58 v4: net.ParseIP("192.168.20.1/24"), 59 }, 60 }, 61 }, 62 routes: []*rtInfo{ 63 { 64 Dst: &net.IPNet{ 65 IP: net.ParseIP("192.168.10.0"), 66 Mask: net.IPv4Mask(255, 255, 255, 0), 67 }, 68 PrefSrc: net.ParseIP("192.168.10.1"), 69 OutputIface: 1, 70 }, 71 { 72 Dst: &net.IPNet{ 73 IP: net.ParseIP("192.168.20.0"), 74 Mask: net.IPv4Mask(255, 255, 255, 0), 75 }, 76 PrefSrc: net.ParseIP("192.168.20.1"), 77 OutputIface: 2, 78 }, 79 }, 80 input: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 81 src: net.ParseIP("192.168.10.1"), 82 dst: net.ParseIP("192.168.20.1"), 83 wantIface: 2, 84 wantGateway: nil, 85 wantPreferredSrc: net.ParseIP("192.168.20.1"), 86 wantErr: nil, 87 }, 88 { 89 name: "not exists route with default gateway", 90 router: router{ 91 ifaces: map[int]*net.Interface{ 92 1: { 93 Index: 1, 94 MTU: 1500, 95 Name: "eth0", 96 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 97 Flags: net.FlagUp, 98 }, 99 2: { 100 Index: 2, 101 MTU: 1500, 102 Name: "eth1", 103 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02}, 104 Flags: net.FlagUp, 105 }, 106 }, 107 addrs: map[int]ipAddrs{ 108 1: { 109 v4: net.ParseIP("192.168.10.1/24"), 110 }, 111 2: { 112 v4: net.ParseIP("192.168.20.1/24"), 113 }, 114 }, 115 }, 116 routes: []*rtInfo{ 117 { 118 Gateway: net.ParseIP("192.168.20.254"), 119 PrefSrc: net.ParseIP("192.168.20.1"), 120 OutputIface: 2, 121 }, 122 { 123 Dst: &net.IPNet{ 124 IP: net.ParseIP("192.168.10.0"), 125 Mask: net.IPv4Mask(255, 255, 255, 0), 126 }, 127 PrefSrc: net.ParseIP("192.168.10.1"), 128 OutputIface: 1, 129 }, 130 { 131 Dst: &net.IPNet{ 132 IP: net.ParseIP("192.168.20.0"), 133 Mask: net.IPv4Mask(255, 255, 255, 0), 134 }, 135 PrefSrc: net.ParseIP("192.168.20.1"), 136 OutputIface: 2, 137 }, 138 }, 139 input: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 140 src: net.ParseIP("192.168.10.1"), 141 dst: net.ParseIP("192.168.30.2"), 142 wantIface: 2, 143 wantGateway: net.ParseIP("192.168.20.254"), 144 wantPreferredSrc: net.ParseIP("192.168.20.1"), 145 wantErr: nil, 146 }, 147 { 148 name: "exists route with default gateway", 149 router: router{ 150 ifaces: map[int]*net.Interface{ 151 1: { 152 Index: 1, 153 MTU: 1500, 154 Name: "eth0", 155 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 156 Flags: net.FlagUp, 157 }, 158 2: { 159 Index: 2, 160 MTU: 1500, 161 Name: "eth1", 162 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02}, 163 Flags: net.FlagUp, 164 }, 165 }, 166 addrs: map[int]ipAddrs{ 167 1: { 168 v4: net.ParseIP("192.168.10.1/24"), 169 }, 170 2: { 171 v4: net.ParseIP("192.168.20.1/24"), 172 }, 173 }, 174 }, 175 routes: []*rtInfo{ 176 { 177 Gateway: net.ParseIP("192.168.20.254"), 178 PrefSrc: net.ParseIP("192.168.20.1"), 179 OutputIface: 2, 180 }, 181 { 182 Dst: &net.IPNet{ 183 IP: net.ParseIP("192.168.10.0"), 184 Mask: net.IPv4Mask(255, 255, 255, 0), 185 }, 186 PrefSrc: net.ParseIP("192.168.10.1"), 187 OutputIface: 1, 188 }, 189 { 190 Dst: &net.IPNet{ 191 IP: net.ParseIP("192.168.20.0"), 192 Mask: net.IPv4Mask(255, 255, 255, 0), 193 }, 194 PrefSrc: net.ParseIP("192.168.20.1"), 195 OutputIface: 2, 196 }, 197 }, 198 input: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 199 src: net.ParseIP("192.168.10.1"), 200 dst: net.ParseIP("192.168.20.2"), 201 wantIface: 2, 202 wantGateway: nil, 203 wantPreferredSrc: net.ParseIP("192.168.20.1"), 204 wantErr: nil, 205 }, 206 { 207 name: "not exists route without default gateway", 208 router: router{ 209 ifaces: map[int]*net.Interface{ 210 1: { 211 Index: 1, 212 MTU: 1500, 213 Name: "eth0", 214 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 215 Flags: net.FlagUp, 216 }, 217 2: { 218 Index: 2, 219 MTU: 1500, 220 Name: "eth1", 221 HardwareAddr: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x02}, 222 Flags: net.FlagUp, 223 }, 224 }, 225 addrs: map[int]ipAddrs{ 226 1: { 227 v4: net.ParseIP("192.168.10.1/24"), 228 }, 229 2: { 230 v4: net.ParseIP("192.168.20.1/24"), 231 }, 232 }, 233 }, 234 routes: []*rtInfo{ 235 { 236 Dst: &net.IPNet{ 237 IP: net.ParseIP("192.168.10.0"), 238 Mask: net.IPv4Mask(255, 255, 255, 0), 239 }, 240 PrefSrc: net.ParseIP("192.168.10.1"), 241 OutputIface: 1, 242 }, 243 { 244 Dst: &net.IPNet{ 245 IP: net.ParseIP("192.168.20.0"), 246 Mask: net.IPv4Mask(255, 255, 255, 0), 247 }, 248 PrefSrc: net.ParseIP("192.168.20.1"), 249 OutputIface: 2, 250 }, 251 }, 252 input: net.HardwareAddr{0x54, 0x52, 0x00, 0x00, 0x00, 0x01}, 253 src: net.ParseIP("192.168.10.1"), 254 dst: net.ParseIP("192.168.30.2"), 255 wantIface: 2, 256 wantGateway: nil, 257 wantPreferredSrc: nil, 258 wantErr: fmt.Errorf("no route found for 192.168.30.2"), 259 }, 260 } 261 262 for _, tt := range tests { 263 t.Run(tt.name, func(t *testing.T) { 264 iface, gateway, preferredSrc, err := tt.router.route(tt.routes, tt.input, tt.src, tt.dst) 265 if tt.wantErr != nil { 266 if err != nil && tt.wantErr.Error() == err.Error() { 267 return 268 } 269 t.Errorf("route() illegal return value `err`:\ngot :%#v\n\nwant: %#v\n\n", err, tt.wantErr) 270 271 } 272 if err != nil { 273 t.Errorf("route() illegal return value `err`:\ngot :%#v\n\nwant: nil\n\n", err) 274 } 275 276 if tt.wantIface != iface { 277 t.Errorf("route() illegal return value `iface`:\ngot :%d\n\nwant: %d\n\n", iface, tt.wantIface) 278 } 279 280 if !tt.wantGateway.Equal(gateway) { 281 t.Errorf("route() illegal return value `gateway`:\ngot :%#v\n\nwant :%#v\n\n", gateway, tt.wantGateway) 282 } 283 284 if !tt.wantPreferredSrc.Equal(preferredSrc) { 285 t.Errorf("route() illegal return value `preferredSrc`:\ngot :%#v\n\nwant :%#v\n\n", preferredSrc, tt.wantPreferredSrc) 286 } 287 288 }) 289 } 290 291 } 292 293 func TestRouting(t *testing.T) { 294 runtime.LockOSThread() 295 defer runtime.UnlockOSThread() 296 297 // parent network namespace 298 testNs, _ := netns.New() 299 defer testNs.Close() 300 301 // child network namespace 302 newns, _ := netns.New() 303 defer newns.Close() 304 305 veth0 := &netlink.Veth{ 306 LinkAttrs: netlink.LinkAttrs{ 307 Name: "veth0", 308 }, 309 PeerName: "veth0-peer", 310 } 311 312 veth1 := &netlink.Veth{ 313 LinkAttrs: netlink.LinkAttrs{ 314 Name: "veth1", 315 }, 316 PeerName: "veth1-peer", 317 } 318 319 // ip link add veth0 type veth peer name veth0-peer 320 if err := netlink.LinkAdd(veth0); err != nil { 321 t.Errorf("\nFailed SetUp Test Environment: link add veth0 type veth peer name veth0-peer: %#v\n\n", err) 322 return 323 } 324 325 // ip link add veth1 type veth peer name veth1-peer 326 if err := netlink.LinkAdd(veth1); err != nil { 327 t.Errorf("\nFailed SetUp Test Environment: link add veth1 type veth peer name veth1-peer: %#v\n\n", err) 328 return 329 } 330 331 // ip address add 192.168.10.1/24 dev veth0 332 veth0Addr, err := netlink.ParseAddr("192.168.10.1/24") 333 if err != nil { 334 t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.10.1/24: %#v\n\n", err) 335 return 336 } 337 if err := netlink.AddrAdd(veth0, veth0Addr); err != nil { 338 t.Errorf("\nFailed SetUp Test Environment: address add 192.168.10.1/24 dev veth0: %#v\n\n", err) 339 return 340 } 341 342 // ip address add 192.168.20.1/24 dev veth1 343 veth1Addr, err := netlink.ParseAddr("192.168.20.1/24") 344 if err != nil { 345 t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.20.1/24: %#v\n\n", err) 346 return 347 } 348 if err := netlink.AddrAdd(veth1, veth1Addr); err != nil { 349 t.Errorf("\nFailed SetUp Test Environment: parse addr 192.168.20.1/24 dev veth1: %#v\n\n", err) 350 return 351 } 352 353 // ip link set up veth0 354 if err := netlink.LinkSetUp(veth0); err != nil { 355 t.Errorf("\nFailed SetUp Test Environment: link set up veth0: %#v\n\n", err) 356 return 357 } 358 359 // ip link set up veth1 360 if err := netlink.LinkSetUp(veth1); err != nil { 361 t.Errorf("\nFailed SetUp Test Environment: link set up veth1: %#v\n\n", err) 362 return 363 } 364 365 veth0Peer, err := netlink.LinkByName("veth0-peer") 366 if err != nil { 367 t.Errorf("\nFailed SetUp Test Environment: link by name veth0-peer: %#v\n\n", err) 368 return 369 } 370 // ip link set up veth0-peer 371 if err := netlink.LinkSetUp(veth0Peer); err != nil { 372 t.Errorf("\nFailed SetUp Test Environment: link set up veth0-peer: %#v\n\n", err) 373 return 374 } 375 // ip link set dev veth0-peer netns {testNs} 376 if err := netlink.LinkSetNsFd(veth0Peer, int(testNs)); err != nil { 377 t.Errorf("\nFailed SetUp Test Environment: link set dev veth0-peer netns testNs: %#v\n\n", err) 378 return 379 } 380 381 veth1Peer, err := netlink.LinkByName("veth1-peer") 382 if err != nil { 383 t.Errorf("\nFailed SetUp Test Environment: link by name veth1-peer: %#v\n\n", err) 384 return 385 } 386 // ip link set up veth1-peer 387 if err := netlink.LinkSetUp(veth1Peer); err != nil { 388 t.Errorf("\nFailed SetUp Test Environment: link set up veth1-peer: %#v\n\n", err) 389 return 390 } 391 // ip link set dev veth1-peer netns {testNs} 392 if err := netlink.LinkSetNsFd(veth1Peer, int(testNs)); err != nil { 393 t.Errorf("\nFailed SetUp Test Environment: link set dev veth1-peer netns testNs: %#v\n\n", err) 394 return 395 } 396 397 /** 398 * routing table 399 * 192.168.10.0/24 dev veth0 proto kernel scope link src 192.168.10.1 400 * 192.168.20.0/24 dev veth1 proto kernel scope link src 192.168.20.1 401 */ 402 403 t.Run("exists route without default gateway", func(t *testing.T) { 404 netns.Set(newns) 405 r, err := New() 406 if err != nil { 407 t.Errorf("\ngot: %#v\nwant: nil", err) 408 return 409 } 410 411 iface, _, _, err := r.Route(net.ParseIP("192.168.10.2")) 412 if err != nil { 413 t.Errorf("\ngot: %#v\nwant: nil", err) 414 } 415 416 if veth0.Index != iface.Index { 417 t.Errorf("\ngot: %d\nwant: %d\n\n", iface.Index, veth0.Index) 418 } 419 420 iface, _, _, err = r.Route(net.ParseIP("192.168.20.2")) 421 if err != nil { 422 t.Errorf("\ngot: %#v\nwant: nil", err) 423 } 424 425 if veth1.Index != iface.Index { 426 t.Errorf("\ngot: %d\nwant: %d\n\n", iface.Index, veth1.Index) 427 } 428 }) 429 430 t.Run("not exists route without default gateway", func(t *testing.T) { 431 netns.Set(newns) 432 433 r, err := New() 434 if err != nil { 435 t.Errorf("\ngot: %#v\nwant: nil\n\n", err) 436 return 437 } 438 439 if _, _, _, err = r.Route(net.ParseIP("172.16.0.1")); err == nil && err == fmt.Errorf("no route found for 172.16.0.1") { 440 t.Errorf("\ngot: %#v\nwant: %#v\n\n", err, fmt.Errorf("no route found for 172.16.0.1")) 441 return 442 } 443 }) 444 445 t.Run("exists route with default gateway", func(t *testing.T) { 446 netns.Set(newns) 447 448 netlink.RouteAdd(&netlink.Route{ 449 Gw: net.ParseIP("192.168.20.254"), 450 LinkIndex: veth1.Index, 451 }) 452 defer func() { 453 // teardown 454 netlink.RouteDel(&netlink.Route{ 455 Gw: net.ParseIP("192.168.20.254"), 456 LinkIndex: veth1.Index, 457 }) 458 }() 459 460 r, err := New() 461 if err != nil { 462 t.Errorf("\ngot: %#v\nwant: nil\n\n", err) 463 return 464 } 465 466 iface, gateway, prefSrc, err := r.Route(net.ParseIP("192.168.10.2")) 467 if err != nil { 468 t.Errorf("\ngot: %#v\nwant: nil\n\n", err) 469 return 470 } 471 472 if veth0.Index != iface.Index { 473 t.Errorf("\ngot: %d\nwant: %d\n\n", iface.Index, veth0.Index) 474 } 475 476 if gateway != nil { 477 t.Errorf("\ngot: %#v\nwant: nil\n\n", gateway) 478 } 479 480 if !prefSrc.Equal(net.ParseIP("192.168.10.1")) { 481 t.Errorf("\ngot: %#v\nwant: %#v\n\n", prefSrc, net.ParseIP("192.168.10.1")) 482 } 483 }) 484 485 t.Run("not exists route with default gateway", func(t *testing.T) { 486 netns.Set(newns) 487 488 netlink.RouteAdd(&netlink.Route{ 489 Gw: net.ParseIP("192.168.20.254"), 490 LinkIndex: veth1.Index, 491 }) 492 defer func() { 493 // teardown 494 netlink.RouteDel(&netlink.Route{ 495 Gw: net.ParseIP("192.168.20.254"), 496 LinkIndex: veth1.Index, 497 }) 498 }() 499 500 r, err := New() 501 if err != nil { 502 t.Errorf("\ngot: %#v\nwant: nil\n\n", err) 503 return 504 } 505 506 iface, gateway, prefSrc, err := r.Route(net.ParseIP("172.16.0.1")) 507 if err != nil { 508 t.Errorf("\ngot: %#v\nwant: nil\n\n", err) 509 return 510 } 511 512 if veth1.Index != iface.Index { 513 t.Errorf("\ngot: %d\nwant: %d\n\n", iface.Index, veth1.Index) 514 } 515 516 if !gateway.Equal(net.ParseIP("192.168.20.254")) { 517 t.Errorf("\ngot: %#v\nwant: %#v\n\n", gateway, net.ParseIP("192.168.20.254")) 518 } 519 520 if !prefSrc.Equal(net.ParseIP("192.168.20.1")) { 521 t.Errorf("\ngot: %#v\nwant: %#v\n\n", prefSrc, net.ParseIP("192.168.20.1")) 522 } 523 }) 524 } 525 526 var testRouter router 527 528 func init() { 529 testRouter = router{ifaces: make(map[int]*net.Interface), addrs: make(map[int]ipAddrs)} 530 // Configure default route 531 defaultHW, _ := net.ParseMAC("01:23:45:67:89:ab") 532 defaultInterface := net.Interface{Index: 5, MTU: 1500, Name: "Default", HardwareAddr: defaultHW, Flags: 1} 533 testRouter.ifaces[2] = &defaultInterface 534 testRouter.addrs[2] = ipAddrs{v4: net.IPv4(192, 168, 1, 2)} 535 defaultRoute := &rtInfo{Gateway: net.IPv4(192, 168, 1, 1), InputIface: 0, OutputIface: 2, Priority: 600} 536 testRouter.v4 = append(testRouter.v4, defaultRoute) 537 // Configure local route 538 localHW, _ := net.ParseMAC("01:23:45:67:89:ac") 539 localInterface := net.Interface{Index: 1, MTU: 1500, Name: "Local", HardwareAddr: localHW, Flags: 1} 540 testRouter.ifaces[1] = &localInterface 541 testRouter.addrs[1] = ipAddrs{v4: net.IPv4(10, 0, 0, 2)} 542 localRoute := &rtInfo{Dst: &net.IPNet{IP: net.IPv4(10, 0, 0, 0), Mask: net.CIDRMask(8, 32)}, 543 Gateway: net.IPv4(10, 0, 0, 1), InputIface: 0, OutputIface: 1, Priority: 300} 544 testRouter.v4 = append(testRouter.v4, localRoute) 545 sort.Sort(testRouter.v4) 546 } 547 548 var routeTests = []struct { 549 dst net.IP 550 ifaceName string 551 }{ 552 {net.IPv4(8, 8, 8, 8), "Default"}, 553 {net.IPv4(192, 168, 2, 3), "Default"}, 554 {net.IPv4(10, 0, 0, 3), "Local"}, 555 } 556 557 func TestRoute(t *testing.T) { 558 for _, tt := range routeTests { 559 t.Run(tt.dst.String(), func(t *testing.T) { 560 iface, _, _, _ := testRouter.Route(tt.dst) 561 if tt.ifaceName != iface.Name { 562 t.Fatalf("test %s\n want:%s\n got:%s\n", tt.dst.String(), tt.ifaceName, iface.Name) 563 } 564 }) 565 } 566 }