gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/netmon/netmon_test.go (about) 1 // Copyright (c) 2018 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package main 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "io/ioutil" 12 "net" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "reflect" 17 "runtime" 18 "testing" 19 20 ktu "github.com/kata-containers/runtime/pkg/katatestutils" 21 vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" 22 "github.com/sirupsen/logrus" 23 "github.com/stretchr/testify/assert" 24 "github.com/vishvananda/netlink" 25 "github.com/vishvananda/netns" 26 "golang.org/x/sys/unix" 27 ) 28 29 const ( 30 testSandboxID = "123456789" 31 testRuntimePath = "/foo/bar/test-runtime" 32 testLogLevel = "info" 33 testStorageParentPath = "/tmp/netmon" 34 testSharedFile = "foo-shared.json" 35 testWrongNetlinkFamily = -1 36 testIfaceName = "test_eth0" 37 testMTU = 12345 38 testHwAddr = "02:00:ca:fe:00:48" 39 testIPAddress = "192.168.0.15" 40 testIPAddressWithMask = "192.168.0.15/32" 41 testIP6Address = "2001:db8:1::242:ac11:2" 42 testIP6AddressWithMask = "2001:db8:1::/64" 43 testScope = 1 44 testTxQLen = -1 45 testIfaceIndex = 5 46 ) 47 48 func skipUnlessRoot(t *testing.T) { 49 tc := ktu.NewTestConstraint(false) 50 51 if tc.NotValid(ktu.NeedRoot()) { 52 t.Skip("Test disabled as requires root user") 53 } 54 } 55 56 func TestNewNetmon(t *testing.T) { 57 skipUnlessRoot(t) 58 59 // Override storageParentPath 60 savedStorageParentPath := storageParentPath 61 storageParentPath = testStorageParentPath 62 defer func() { 63 storageParentPath = savedStorageParentPath 64 }() 65 66 params := netmonParams{ 67 sandboxID: testSandboxID, 68 runtimePath: testRuntimePath, 69 debug: true, 70 logLevel: testLogLevel, 71 } 72 73 expected := &netmon{ 74 netmonParams: params, 75 storagePath: filepath.Join(storageParentPath, params.sandboxID), 76 sharedFile: filepath.Join(storageParentPath, params.sandboxID, sharedFile), 77 } 78 79 os.RemoveAll(expected.storagePath) 80 81 got, err := newNetmon(params) 82 assert.Nil(t, err) 83 assert.True(t, reflect.DeepEqual(expected.netmonParams, got.netmonParams), 84 "Got %+v\nExpected %+v", got.netmonParams, expected.netmonParams) 85 assert.True(t, reflect.DeepEqual(expected.storagePath, got.storagePath), 86 "Got %+v\nExpected %+v", got.storagePath, expected.storagePath) 87 assert.True(t, reflect.DeepEqual(expected.sharedFile, got.sharedFile), 88 "Got %+v\nExpected %+v", got.sharedFile, expected.sharedFile) 89 90 _, err = os.Stat(got.storagePath) 91 assert.Nil(t, err) 92 93 os.RemoveAll(got.storagePath) 94 } 95 96 func TestNewNetmonErrorWrongFamilyType(t *testing.T) { 97 // Override netlinkFamily 98 savedNetlinkFamily := netlinkFamily 99 netlinkFamily = testWrongNetlinkFamily 100 defer func() { 101 netlinkFamily = savedNetlinkFamily 102 }() 103 104 n, err := newNetmon(netmonParams{}) 105 assert.NotNil(t, err) 106 assert.Nil(t, n) 107 } 108 109 func TestCleanup(t *testing.T) { 110 skipUnlessRoot(t) 111 112 // Override storageParentPath 113 savedStorageParentPath := storageParentPath 114 storageParentPath = testStorageParentPath 115 defer func() { 116 storageParentPath = savedStorageParentPath 117 }() 118 119 handler, err := netlink.NewHandle(netlinkFamily) 120 assert.Nil(t, err) 121 122 n := &netmon{ 123 storagePath: filepath.Join(storageParentPath, testSandboxID), 124 linkDoneCh: make(chan struct{}), 125 rtDoneCh: make(chan struct{}), 126 netHandler: handler, 127 } 128 129 err = os.MkdirAll(n.storagePath, storageDirPerm) 130 assert.Nil(t, err) 131 _, err = os.Stat(n.storagePath) 132 assert.Nil(t, err) 133 134 n.cleanup() 135 136 _, err = os.Stat(n.storagePath) 137 assert.NotNil(t, err) 138 _, ok := (<-n.linkDoneCh) 139 assert.False(t, ok) 140 _, ok = (<-n.rtDoneCh) 141 assert.False(t, ok) 142 } 143 144 func TestLogger(t *testing.T) { 145 fields := logrus.Fields{ 146 "name": netmonName, 147 "pid": os.Getpid(), 148 "source": "netmon", 149 "sandbox": testSandboxID, 150 } 151 152 expected := netmonLog.WithFields(fields) 153 154 n := &netmon{ 155 netmonParams: netmonParams{ 156 sandboxID: testSandboxID, 157 }, 158 } 159 160 got := n.logger() 161 assert.True(t, reflect.DeepEqual(*expected, *got), 162 "Got %+v\nExpected %+v", *got, *expected) 163 } 164 165 func TestConvertInterface(t *testing.T) { 166 hwAddr, err := net.ParseMAC(testHwAddr) 167 assert.Nil(t, err) 168 169 addrs := []netlink.Addr{ 170 { 171 IPNet: &net.IPNet{ 172 IP: net.ParseIP(testIPAddress), 173 }, 174 }, 175 { 176 IPNet: &net.IPNet{ 177 IP: net.ParseIP(testIP6Address), 178 }, 179 }, 180 } 181 182 linkAttrs := &netlink.LinkAttrs{ 183 Name: testIfaceName, 184 MTU: testMTU, 185 HardwareAddr: hwAddr, 186 } 187 188 linkType := "link_type_test" 189 190 expected := vcTypes.Interface{ 191 Device: testIfaceName, 192 Name: testIfaceName, 193 Mtu: uint64(testMTU), 194 HwAddr: testHwAddr, 195 IPAddresses: []*vcTypes.IPAddress{ 196 { 197 Family: netlink.FAMILY_V4, 198 Address: testIPAddress, 199 Mask: "0", 200 }, 201 { 202 Family: netlink.FAMILY_V6, 203 Address: testIP6Address, 204 Mask: "0", 205 }, 206 }, 207 LinkType: linkType, 208 } 209 210 got := convertInterface(linkAttrs, linkType, addrs) 211 212 assert.True(t, reflect.DeepEqual(expected, got), 213 "Got %+v\nExpected %+v", got, expected) 214 } 215 216 func TestConvertRoutes(t *testing.T) { 217 ip, ipNet, err := net.ParseCIDR(testIPAddressWithMask) 218 assert.Nil(t, err) 219 assert.NotNil(t, ipNet) 220 221 _, ip6Net, err := net.ParseCIDR(testIP6AddressWithMask) 222 assert.Nil(t, err) 223 assert.NotNil(t, ipNet) 224 225 routes := []netlink.Route{ 226 { 227 Dst: ipNet, 228 Src: ip, 229 Gw: ip, 230 LinkIndex: -1, 231 Scope: testScope, 232 }, 233 { 234 Dst: ip6Net, 235 Src: nil, 236 Gw: nil, 237 LinkIndex: -1, 238 Scope: testScope, 239 }, 240 } 241 242 expected := []vcTypes.Route{ 243 { 244 Dest: testIPAddressWithMask, 245 Gateway: testIPAddress, 246 Source: testIPAddress, 247 Scope: uint32(testScope), 248 }, 249 { 250 Dest: testIP6AddressWithMask, 251 Gateway: "", 252 Source: "", 253 Scope: uint32(testScope), 254 }, 255 } 256 257 got := convertRoutes(routes) 258 assert.True(t, reflect.DeepEqual(expected, got), 259 "Got %+v\nExpected %+v", got, expected) 260 } 261 262 type testTeardownNetwork func() 263 264 func testSetupNetwork(t *testing.T) testTeardownNetwork { 265 skipUnlessRoot(t) 266 267 // new temporary namespace so we don't pollute the host 268 // lock thread since the namespace is thread local 269 runtime.LockOSThread() 270 var err error 271 ns, err := netns.New() 272 if err != nil { 273 t.Fatal("Failed to create newns", ns) 274 } 275 276 return func() { 277 ns.Close() 278 runtime.UnlockOSThread() 279 } 280 } 281 282 func testCreateDummyNetwork(t *testing.T, handler *netlink.Handle) (int, vcTypes.Interface) { 283 hwAddr, err := net.ParseMAC(testHwAddr) 284 assert.Nil(t, err) 285 286 link := &netlink.Dummy{ 287 LinkAttrs: netlink.LinkAttrs{ 288 MTU: testMTU, 289 TxQLen: testTxQLen, 290 Name: testIfaceName, 291 HardwareAddr: hwAddr, 292 }, 293 } 294 295 err = handler.LinkAdd(link) 296 assert.Nil(t, err) 297 err = handler.LinkSetUp(link) 298 assert.Nil(t, err) 299 300 attrs := link.Attrs() 301 assert.NotNil(t, attrs) 302 303 addrs, err := handler.AddrList(link, netlinkFamily) 304 assert.Nil(t, err) 305 306 var ipAddrs []*vcTypes.IPAddress 307 308 // Scan addresses for ipv6 link local address which is automatically assigned 309 for _, addr := range addrs { 310 if addr.IPNet == nil { 311 continue 312 } 313 314 netMask, _ := addr.Mask.Size() 315 316 ipAddr := &vcTypes.IPAddress{ 317 Address: addr.IP.String(), 318 Mask: fmt.Sprintf("%d", netMask), 319 } 320 321 if addr.IP.To4() != nil { 322 ipAddr.Family = netlink.FAMILY_V4 323 } else { 324 ipAddr.Family = netlink.FAMILY_V6 325 } 326 327 ipAddrs = append(ipAddrs, ipAddr) 328 } 329 330 iface := vcTypes.Interface{ 331 Device: testIfaceName, 332 Name: testIfaceName, 333 Mtu: uint64(testMTU), 334 HwAddr: testHwAddr, 335 LinkType: link.Type(), 336 IPAddresses: ipAddrs, 337 } 338 339 return attrs.Index, iface 340 } 341 342 func TestScanNetwork(t *testing.T) { 343 tearDownNetworkCb := testSetupNetwork(t) 344 defer tearDownNetworkCb() 345 346 handler, err := netlink.NewHandle(netlinkFamily) 347 assert.Nil(t, err) 348 assert.NotNil(t, handler) 349 defer handler.Delete() 350 351 idx, expected := testCreateDummyNetwork(t, handler) 352 353 n := &netmon{ 354 netIfaces: make(map[int]vcTypes.Interface), 355 netHandler: handler, 356 } 357 358 err = n.scanNetwork() 359 assert.Nil(t, err) 360 assert.True(t, reflect.DeepEqual(expected, n.netIfaces[idx]), 361 "Got %+v\nExpected %+v", n.netIfaces[idx], expected) 362 } 363 364 func TestStoreDataToSend(t *testing.T) { 365 var got vcTypes.Interface 366 367 expected := vcTypes.Interface{ 368 Device: testIfaceName, 369 Name: testIfaceName, 370 Mtu: uint64(testMTU), 371 HwAddr: testHwAddr, 372 } 373 374 n := &netmon{ 375 sharedFile: filepath.Join(testStorageParentPath, testSharedFile), 376 } 377 378 err := os.MkdirAll(testStorageParentPath, storageDirPerm) 379 defer os.RemoveAll(testStorageParentPath) 380 assert.Nil(t, err) 381 382 err = n.storeDataToSend(expected) 383 assert.Nil(t, err) 384 385 // Check the file has been created, check the content, and delete it. 386 _, err = os.Stat(n.sharedFile) 387 assert.Nil(t, err) 388 byteArray, err := ioutil.ReadFile(n.sharedFile) 389 assert.Nil(t, err) 390 err = json.Unmarshal(byteArray, &got) 391 assert.Nil(t, err) 392 assert.True(t, reflect.DeepEqual(expected, got), 393 "Got %+v\nExpected %+v", got, expected) 394 } 395 396 func TestExecKataCmdSuccess(t *testing.T) { 397 trueBinPath, err := exec.LookPath("true") 398 assert.Nil(t, err) 399 assert.NotEmpty(t, trueBinPath) 400 401 params := netmonParams{ 402 runtimePath: trueBinPath, 403 } 404 405 n := &netmon{ 406 netmonParams: params, 407 sharedFile: filepath.Join(testStorageParentPath, testSharedFile), 408 } 409 410 err = os.MkdirAll(testStorageParentPath, storageDirPerm) 411 assert.Nil(t, err) 412 defer os.RemoveAll(testStorageParentPath) 413 414 file, err := os.Create(n.sharedFile) 415 assert.Nil(t, err) 416 assert.NotNil(t, file) 417 file.Close() 418 419 _, err = os.Stat(n.sharedFile) 420 assert.Nil(t, err) 421 422 err = n.execKataCmd("") 423 assert.Nil(t, err) 424 _, err = os.Stat(n.sharedFile) 425 assert.NotNil(t, err) 426 } 427 428 func TestExecKataCmdFailure(t *testing.T) { 429 falseBinPath, err := exec.LookPath("false") 430 assert.Nil(t, err) 431 assert.NotEmpty(t, falseBinPath) 432 433 params := netmonParams{ 434 runtimePath: falseBinPath, 435 } 436 437 n := &netmon{ 438 netmonParams: params, 439 } 440 441 err = n.execKataCmd("") 442 assert.NotNil(t, err) 443 } 444 445 func TestActionsCLI(t *testing.T) { 446 trueBinPath, err := exec.LookPath("true") 447 assert.Nil(t, err) 448 assert.NotEmpty(t, trueBinPath) 449 450 params := netmonParams{ 451 runtimePath: trueBinPath, 452 } 453 454 n := &netmon{ 455 netmonParams: params, 456 sharedFile: filepath.Join(testStorageParentPath, testSharedFile), 457 } 458 459 err = os.MkdirAll(testStorageParentPath, storageDirPerm) 460 assert.Nil(t, err) 461 defer os.RemoveAll(testStorageParentPath) 462 463 // Test addInterfaceCLI 464 err = n.addInterfaceCLI(vcTypes.Interface{}) 465 assert.Nil(t, err) 466 467 // Test delInterfaceCLI 468 err = n.delInterfaceCLI(vcTypes.Interface{}) 469 assert.Nil(t, err) 470 471 // Test updateRoutesCLI 472 err = n.updateRoutesCLI([]vcTypes.Route{}) 473 assert.Nil(t, err) 474 475 tearDownNetworkCb := testSetupNetwork(t) 476 defer tearDownNetworkCb() 477 478 handler, err := netlink.NewHandle(netlinkFamily) 479 assert.Nil(t, err) 480 assert.NotNil(t, handler) 481 defer handler.Delete() 482 483 n.netHandler = handler 484 485 // Test updateRoutes 486 err = n.updateRoutes() 487 assert.Nil(t, err) 488 489 // Test handleRTMDelRoute 490 err = n.handleRTMDelRoute(netlink.RouteUpdate{}) 491 assert.Nil(t, err) 492 } 493 494 func TestHandleRTMNewAddr(t *testing.T) { 495 n := &netmon{} 496 497 err := n.handleRTMNewAddr(netlink.LinkUpdate{}) 498 assert.Nil(t, err) 499 } 500 501 func TestHandleRTMDelAddr(t *testing.T) { 502 n := &netmon{} 503 504 err := n.handleRTMDelAddr(netlink.LinkUpdate{}) 505 assert.Nil(t, err) 506 } 507 508 func TestHandleRTMNewLink(t *testing.T) { 509 n := &netmon{} 510 ev := netlink.LinkUpdate{ 511 Link: &netlink.Dummy{}, 512 } 513 514 // LinkAttrs is nil 515 err := n.handleRTMNewLink(ev) 516 assert.Nil(t, err) 517 518 // Link name contains "kata" suffix 519 ev = netlink.LinkUpdate{ 520 Link: &netlink.Dummy{ 521 LinkAttrs: netlink.LinkAttrs{ 522 Name: "foo_kata", 523 }, 524 }, 525 } 526 err = n.handleRTMNewLink(ev) 527 assert.Nil(t, err) 528 529 // Interface already exist in list 530 n.netIfaces = make(map[int]vcTypes.Interface) 531 n.netIfaces[testIfaceIndex] = vcTypes.Interface{} 532 ev = netlink.LinkUpdate{ 533 Link: &netlink.Dummy{ 534 LinkAttrs: netlink.LinkAttrs{ 535 Name: "foo0", 536 }, 537 }, 538 } 539 ev.Index = testIfaceIndex 540 err = n.handleRTMNewLink(ev) 541 assert.Nil(t, err) 542 543 // Flags are not up and running 544 n.netIfaces = make(map[int]vcTypes.Interface) 545 ev = netlink.LinkUpdate{ 546 Link: &netlink.Dummy{ 547 LinkAttrs: netlink.LinkAttrs{ 548 Name: "foo0", 549 }, 550 }, 551 } 552 ev.Index = testIfaceIndex 553 err = n.handleRTMNewLink(ev) 554 assert.Nil(t, err) 555 556 // Invalid link 557 n.netIfaces = make(map[int]vcTypes.Interface) 558 ev = netlink.LinkUpdate{ 559 Link: &netlink.Dummy{ 560 LinkAttrs: netlink.LinkAttrs{ 561 Name: "foo0", 562 }, 563 }, 564 } 565 ev.Index = testIfaceIndex 566 ev.Flags = unix.IFF_UP | unix.IFF_RUNNING 567 handler, err := netlink.NewHandle(netlinkFamily) 568 assert.Nil(t, err) 569 assert.NotNil(t, handler) 570 defer handler.Delete() 571 n.netHandler = handler 572 err = n.handleRTMNewLink(ev) 573 assert.NotNil(t, err) 574 } 575 576 func TestHandleRTMDelLink(t *testing.T) { 577 n := &netmon{} 578 ev := netlink.LinkUpdate{ 579 Link: &netlink.Dummy{}, 580 } 581 582 // LinkAttrs is nil 583 err := n.handleRTMDelLink(ev) 584 assert.Nil(t, err) 585 586 // Link name contains "kata" suffix 587 ev = netlink.LinkUpdate{ 588 Link: &netlink.Dummy{ 589 LinkAttrs: netlink.LinkAttrs{ 590 Name: "foo_kata", 591 }, 592 }, 593 } 594 err = n.handleRTMDelLink(ev) 595 assert.Nil(t, err) 596 597 // Interface does not exist in list 598 n.netIfaces = make(map[int]vcTypes.Interface) 599 ev = netlink.LinkUpdate{ 600 Link: &netlink.Dummy{ 601 LinkAttrs: netlink.LinkAttrs{ 602 Name: "foo0", 603 }, 604 }, 605 } 606 ev.Index = testIfaceIndex 607 err = n.handleRTMDelLink(ev) 608 assert.Nil(t, err) 609 } 610 611 func TestHandleRTMNewRouteIfaceNotFound(t *testing.T) { 612 n := &netmon{ 613 netIfaces: make(map[int]vcTypes.Interface), 614 } 615 616 err := n.handleRTMNewRoute(netlink.RouteUpdate{}) 617 assert.Nil(t, err) 618 } 619 620 func TestHandleLinkEvent(t *testing.T) { 621 n := &netmon{} 622 ev := netlink.LinkUpdate{} 623 624 // Unknown event 625 err := n.handleLinkEvent(ev) 626 assert.Nil(t, err) 627 628 // DONE event 629 ev.Header.Type = unix.NLMSG_DONE 630 err = n.handleLinkEvent(ev) 631 assert.Nil(t, err) 632 633 // ERROR event 634 ev.Header.Type = unix.NLMSG_ERROR 635 err = n.handleLinkEvent(ev) 636 assert.NotNil(t, err) 637 638 // NEWADDR event 639 ev.Header.Type = unix.RTM_NEWADDR 640 err = n.handleLinkEvent(ev) 641 assert.Nil(t, err) 642 643 // DELADDR event 644 ev.Header.Type = unix.RTM_DELADDR 645 err = n.handleLinkEvent(ev) 646 assert.Nil(t, err) 647 648 // NEWLINK event 649 ev.Header.Type = unix.RTM_NEWLINK 650 ev.Link = &netlink.Dummy{} 651 err = n.handleLinkEvent(ev) 652 assert.Nil(t, err) 653 654 // DELLINK event 655 ev.Header.Type = unix.RTM_DELLINK 656 ev.Link = &netlink.Dummy{} 657 err = n.handleLinkEvent(ev) 658 assert.Nil(t, err) 659 } 660 661 func TestHandleRouteEvent(t *testing.T) { 662 n := &netmon{} 663 ev := netlink.RouteUpdate{} 664 665 // Unknown event 666 err := n.handleRouteEvent(ev) 667 assert.Nil(t, err) 668 669 // RTM_NEWROUTE event 670 ev.Type = unix.RTM_NEWROUTE 671 err = n.handleRouteEvent(ev) 672 assert.Nil(t, err) 673 674 trueBinPath, err := exec.LookPath("true") 675 assert.Nil(t, err) 676 assert.NotEmpty(t, trueBinPath) 677 678 n.runtimePath = trueBinPath 679 n.sharedFile = filepath.Join(testStorageParentPath, testSharedFile) 680 681 err = os.MkdirAll(testStorageParentPath, storageDirPerm) 682 assert.Nil(t, err) 683 defer os.RemoveAll(testStorageParentPath) 684 685 tearDownNetworkCb := testSetupNetwork(t) 686 defer tearDownNetworkCb() 687 688 handler, err := netlink.NewHandle(netlinkFamily) 689 assert.Nil(t, err) 690 assert.NotNil(t, handler) 691 defer handler.Delete() 692 693 n.netHandler = handler 694 695 // RTM_DELROUTE event 696 ev.Type = unix.RTM_DELROUTE 697 err = n.handleRouteEvent(ev) 698 assert.Nil(t, err) 699 }