k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/proxy/winkernel/hns_test.go (about) 1 //go:build windows 2 // +build windows 3 4 /* 5 Copyright 2018 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package winkernel 21 22 import ( 23 "encoding/json" 24 25 "github.com/Microsoft/hcsshim/hcn" 26 "github.com/stretchr/testify/assert" 27 28 "strings" 29 "testing" 30 31 "github.com/google/go-cmp/cmp" 32 ) 33 34 const ( 35 sourceVip = "192.168.1.2" 36 serviceVip = "11.0.0.1" 37 addressPrefix = "192.168.1.0/24" 38 gatewayAddress = "192.168.1.1" 39 epMacAddress = "00-11-22-33-44-55" 40 epIpAddress = "192.168.1.3" 41 epIpv6Address = "192::3" 42 epIpAddressB = "192.168.1.4" 43 epIpAddressRemote = "192.168.2.3" 44 epPaAddress = "10.0.0.3" 45 protocol = 6 46 internalPort = 80 47 externalPort = 32440 48 ) 49 50 func TestGetNetworkByName(t *testing.T) { 51 // TODO: remove skip once the test has been fixed. 52 t.Skip("Skipping failing test on Windows.") 53 hns := hns{hcn: newHcnImpl()} 54 Network := mustTestNetwork(t) 55 56 network, err := hns.getNetworkByName(Network.Name) 57 if err != nil { 58 t.Error(err) 59 } 60 61 if !strings.EqualFold(network.id, Network.Id) { 62 t.Errorf("%v does not match %v", network.id, Network.Id) 63 } 64 err = Network.Delete() 65 if err != nil { 66 t.Error(err) 67 } 68 } 69 70 func TestGetAllEndpointsByNetwork(t *testing.T) { 71 // TODO: remove skip once the test has been fixed. 72 t.Skip("Skipping failing test on Windows.") 73 hns := hns{hcn: newHcnImpl()} 74 Network := mustTestNetwork(t) 75 76 ipv4Config := &hcn.IpConfig{ 77 IpAddress: epIpAddress, 78 } 79 ipv6Config := &hcn.IpConfig{ 80 IpAddress: epIpv6Address, 81 } 82 Endpoint := &hcn.HostComputeEndpoint{ 83 IpConfigurations: []hcn.IpConfig{*ipv4Config, *ipv6Config}, 84 MacAddress: epMacAddress, 85 SchemaVersion: hcn.SchemaVersion{ 86 Major: 2, 87 Minor: 0, 88 }, 89 } 90 Endpoint, err := Network.CreateEndpoint(Endpoint) 91 if err != nil { 92 t.Error(err) 93 } 94 95 mapEndpointsInfo, err := hns.getAllEndpointsByNetwork(Network.Name) 96 if err != nil { 97 t.Error(err) 98 } 99 endpointIpv4, ipv4EpPresent := mapEndpointsInfo[ipv4Config.IpAddress] 100 assert.True(t, ipv4EpPresent, "IPV4 endpoint is missing in Dualstack mode") 101 assert.Equal(t, endpointIpv4.ip, epIpAddress, "IPV4 IP is missing in Dualstack mode") 102 103 endpointIpv6, ipv6EpPresent := mapEndpointsInfo[ipv6Config.IpAddress] 104 assert.True(t, ipv6EpPresent, "IPV6 endpoint is missing in Dualstack mode") 105 assert.Equal(t, endpointIpv6.ip, epIpv6Address, "IPV6 IP is missing in Dualstack mode") 106 107 err = Endpoint.Delete() 108 if err != nil { 109 t.Error(err) 110 } 111 err = Network.Delete() 112 if err != nil { 113 t.Error(err) 114 } 115 } 116 117 func TestGetEndpointByID(t *testing.T) { 118 // TODO: remove skip once the test has been fixed. 119 t.Skip("Skipping failing test on Windows.") 120 hns := hns{hcn: newHcnImpl()} 121 Network := mustTestNetwork(t) 122 123 ipConfig := &hcn.IpConfig{ 124 IpAddress: epIpAddress, 125 } 126 Endpoint := &hcn.HostComputeEndpoint{ 127 IpConfigurations: []hcn.IpConfig{*ipConfig}, 128 MacAddress: epMacAddress, 129 SchemaVersion: hcn.SchemaVersion{ 130 Major: 2, 131 Minor: 0, 132 }, 133 } 134 135 Endpoint, err := Network.CreateEndpoint(Endpoint) 136 if err != nil { 137 t.Error(err) 138 } 139 140 endpoint, err := hns.getEndpointByID(Endpoint.Id) 141 if err != nil { 142 t.Error(err) 143 } 144 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) { 145 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id) 146 } 147 148 err = Endpoint.Delete() 149 if err != nil { 150 t.Error(err) 151 } 152 err = Network.Delete() 153 if err != nil { 154 t.Error(err) 155 } 156 } 157 158 func TestGetEndpointByIpAddressAndName(t *testing.T) { 159 // TODO: remove skip once the test has been fixed. 160 t.Skip("Skipping failing test on Windows.") 161 hns := hns{hcn: newHcnImpl()} 162 Network := mustTestNetwork(t) 163 164 ipConfig := &hcn.IpConfig{ 165 IpAddress: epIpAddress, 166 } 167 Endpoint := &hcn.HostComputeEndpoint{ 168 IpConfigurations: []hcn.IpConfig{*ipConfig}, 169 MacAddress: epMacAddress, 170 SchemaVersion: hcn.SchemaVersion{ 171 Major: 2, 172 Minor: 0, 173 }, 174 } 175 Endpoint, err := Network.CreateEndpoint(Endpoint) 176 if err != nil { 177 t.Error(err) 178 } 179 180 endpoint, err := hns.getEndpointByIpAddress(Endpoint.IpConfigurations[0].IpAddress, Network.Name) 181 if err != nil { 182 t.Error(err) 183 } 184 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) { 185 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id) 186 } 187 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress { 188 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress) 189 } 190 191 endpoint2, err := hns.getEndpointByName(Endpoint.Name) 192 if err != nil { 193 t.Error(err) 194 } 195 diff := cmp.Diff(endpoint, endpoint2) 196 if diff != "" { 197 t.Errorf("getEndpointByName(%s) returned a different endpoint. Diff: %s ", Endpoint.Name, diff) 198 } 199 200 err = Endpoint.Delete() 201 if err != nil { 202 t.Error(err) 203 } 204 err = Network.Delete() 205 if err != nil { 206 t.Error(err) 207 } 208 } 209 210 func TestCreateEndpointLocal(t *testing.T) { 211 // TODO: remove skip once the test has been fixed. 212 t.Skip("Skipping failing test on Windows.") 213 hns := hns{hcn: newHcnImpl()} 214 Network := mustTestNetwork(t) 215 216 endpoint := &endpointInfo{ 217 ip: epIpAddress, 218 macAddress: epMacAddress, 219 isLocal: true, 220 } 221 222 endpoint, err := hns.createEndpoint(endpoint, Network.Name) 223 if err != nil { 224 t.Error(err) 225 } 226 Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID) 227 if err != nil { 228 t.Error(err) 229 } 230 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) { 231 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id) 232 } 233 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress { 234 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress) 235 } 236 if endpoint.macAddress != Endpoint.MacAddress { 237 t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress) 238 } 239 240 err = Endpoint.Delete() 241 if err != nil { 242 t.Error(err) 243 } 244 err = Network.Delete() 245 if err != nil { 246 t.Error(err) 247 } 248 } 249 250 func TestCreateEndpointRemote(t *testing.T) { 251 // TODO: remove skip once the test has been fixed. 252 t.Skip("Skipping failing test on Windows.") 253 hns := hns{hcn: newHcnImpl()} 254 Network := mustTestNetwork(t) 255 providerAddress := epPaAddress 256 257 endpoint := &endpointInfo{ 258 ip: epIpAddressRemote, 259 macAddress: epMacAddress, 260 isLocal: false, 261 providerAddress: providerAddress, 262 } 263 264 endpoint, err := hns.createEndpoint(endpoint, Network.Name) 265 if err != nil { 266 t.Error(err) 267 } 268 Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID) 269 if err != nil { 270 t.Error(err) 271 } 272 if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) { 273 t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id) 274 } 275 if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress { 276 t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress) 277 } 278 if endpoint.macAddress != Endpoint.MacAddress { 279 t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress) 280 } 281 if len(providerAddress) != 0 && endpoint.providerAddress != epPaAddress { 282 t.Errorf("%v does not match %v", endpoint.providerAddress, providerAddress) 283 } 284 285 err = Endpoint.Delete() 286 if err != nil { 287 t.Error(err) 288 } 289 err = Network.Delete() 290 if err != nil { 291 t.Error(err) 292 } 293 } 294 295 func TestDeleteEndpoint(t *testing.T) { 296 // TODO: remove skip once the test has been fixed. 297 t.Skip("Skipping failing test on Windows.") 298 hns := hns{hcn: newHcnImpl()} 299 Network := mustTestNetwork(t) 300 301 ipConfig := &hcn.IpConfig{ 302 IpAddress: epIpAddress, 303 } 304 Endpoint := &hcn.HostComputeEndpoint{ 305 IpConfigurations: []hcn.IpConfig{*ipConfig}, 306 MacAddress: epMacAddress, 307 SchemaVersion: hcn.SchemaVersion{ 308 Major: 2, 309 Minor: 0, 310 }, 311 } 312 Endpoint, err := Network.CreateEndpoint(Endpoint) 313 if err != nil { 314 t.Error(err) 315 } 316 err = hns.deleteEndpoint(Endpoint.Id) 317 if err != nil { 318 t.Error(err) 319 } 320 // Endpoint should no longer exist so this should fail 321 Endpoint, err = hcn.GetEndpointByID(Endpoint.Id) 322 if err == nil { 323 t.Error(err) 324 } 325 326 err = Network.Delete() 327 if err != nil { 328 t.Error(err) 329 } 330 } 331 332 func TestGetLoadBalancerExisting(t *testing.T) { 333 // TODO: remove skip once the test has been fixed. 334 t.Skip("Skipping failing test on Windows.") 335 hns := hns{hcn: newHcnImpl()} 336 Network := mustTestNetwork(t) 337 lbs := make(map[loadBalancerIdentifier]*(loadBalancerInfo)) 338 339 ipConfig := &hcn.IpConfig{ 340 IpAddress: epIpAddress, 341 } 342 Endpoint := &hcn.HostComputeEndpoint{ 343 IpConfigurations: []hcn.IpConfig{*ipConfig}, 344 MacAddress: epMacAddress, 345 SchemaVersion: hcn.SchemaVersion{ 346 Major: 2, 347 Minor: 0, 348 }, 349 } 350 Endpoint, err := Network.CreateEndpoint(Endpoint) 351 if err != nil { 352 t.Error(err) 353 } 354 355 Endpoints := []hcn.HostComputeEndpoint{*Endpoint} 356 LoadBalancer, err := hcn.AddLoadBalancer( 357 Endpoints, 358 hcn.LoadBalancerFlagsNone, 359 hcn.LoadBalancerPortMappingFlagsNone, 360 sourceVip, 361 []string{serviceVip}, 362 protocol, 363 internalPort, 364 externalPort, 365 ) 366 if err != nil { 367 t.Error(err) 368 } 369 endpoint := &endpointInfo{ 370 ip: Endpoint.IpConfigurations[0].IpAddress, 371 hnsID: Endpoint.Id, 372 } 373 endpoints := []endpointInfo{*endpoint} 374 hash, err := hashEndpoints(endpoints) 375 if err != nil { 376 t.Error(err) 377 } 378 379 // We populate this to ensure we test for getting existing load balancer 380 id := loadBalancerIdentifier{protocol: protocol, internalPort: internalPort, externalPort: externalPort, vip: serviceVip, endpointsHash: hash} 381 lbs[id] = &loadBalancerInfo{hnsID: LoadBalancer.Id} 382 383 lb, err := hns.getLoadBalancer(endpoints, loadBalancerFlags{}, sourceVip, serviceVip, protocol, internalPort, externalPort, lbs) 384 385 if err != nil { 386 t.Error(err) 387 } 388 389 if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) { 390 t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id) 391 } 392 393 err = LoadBalancer.Delete() 394 if err != nil { 395 t.Error(err) 396 } 397 err = Endpoint.Delete() 398 if err != nil { 399 t.Error(err) 400 } 401 err = Network.Delete() 402 if err != nil { 403 t.Error(err) 404 } 405 } 406 407 func TestGetLoadBalancerNew(t *testing.T) { 408 // TODO: remove skip once the test has been fixed. 409 t.Skip("Skipping failing test on Windows.") 410 hns := hns{hcn: newHcnImpl()} 411 Network := mustTestNetwork(t) 412 // We keep this empty to ensure we test for new load balancer creation. 413 lbs := make(map[loadBalancerIdentifier]*(loadBalancerInfo)) 414 415 ipConfig := &hcn.IpConfig{ 416 IpAddress: epIpAddress, 417 } 418 Endpoint := &hcn.HostComputeEndpoint{ 419 IpConfigurations: []hcn.IpConfig{*ipConfig}, 420 MacAddress: epMacAddress, 421 SchemaVersion: hcn.SchemaVersion{ 422 Major: 2, 423 Minor: 0, 424 }, 425 } 426 Endpoint, err := Network.CreateEndpoint(Endpoint) 427 if err != nil { 428 t.Error(err) 429 } 430 endpoint := &endpointInfo{ 431 ip: Endpoint.IpConfigurations[0].IpAddress, 432 hnsID: Endpoint.Id, 433 } 434 endpoints := []endpointInfo{*endpoint} 435 lb, err := hns.getLoadBalancer(endpoints, loadBalancerFlags{}, sourceVip, serviceVip, protocol, internalPort, externalPort, lbs) 436 if err != nil { 437 t.Error(err) 438 } 439 LoadBalancer, err := hcn.GetLoadBalancerByID(lb.hnsID) 440 if err != nil { 441 t.Error(err) 442 } 443 if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) { 444 t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id) 445 } 446 err = LoadBalancer.Delete() 447 if err != nil { 448 t.Error(err) 449 } 450 451 err = Endpoint.Delete() 452 if err != nil { 453 t.Error(err) 454 } 455 err = Network.Delete() 456 if err != nil { 457 t.Error(err) 458 } 459 } 460 461 func TestDeleteLoadBalancer(t *testing.T) { 462 // TODO: remove skip once the test has been fixed. 463 t.Skip("Skipping failing test on Windows.") 464 hns := hns{hcn: newHcnImpl()} 465 Network := mustTestNetwork(t) 466 467 ipConfig := &hcn.IpConfig{ 468 IpAddress: epIpAddress, 469 } 470 Endpoint := &hcn.HostComputeEndpoint{ 471 IpConfigurations: []hcn.IpConfig{*ipConfig}, 472 MacAddress: epMacAddress, 473 SchemaVersion: hcn.SchemaVersion{ 474 Major: 2, 475 Minor: 0, 476 }, 477 } 478 Endpoint, err := Network.CreateEndpoint(Endpoint) 479 if err != nil { 480 t.Error(err) 481 } 482 483 Endpoints := []hcn.HostComputeEndpoint{*Endpoint} 484 LoadBalancer, err := hcn.AddLoadBalancer( 485 Endpoints, 486 hcn.LoadBalancerFlagsNone, 487 hcn.LoadBalancerPortMappingFlagsNone, 488 sourceVip, 489 []string{serviceVip}, 490 protocol, 491 internalPort, 492 externalPort, 493 ) 494 if err != nil { 495 t.Error(err) 496 } 497 err = hns.deleteLoadBalancer(LoadBalancer.Id) 498 if err != nil { 499 t.Error(err) 500 } 501 // Load balancer should not longer exist 502 LoadBalancer, err = hcn.GetLoadBalancerByID(LoadBalancer.Id) 503 if err == nil { 504 t.Error(err) 505 } 506 507 err = Endpoint.Delete() 508 if err != nil { 509 t.Error(err) 510 } 511 err = Network.Delete() 512 if err != nil { 513 t.Error(err) 514 } 515 } 516 517 func mustTestNetwork(t *testing.T) *hcn.HostComputeNetwork { 518 network, err := createTestNetwork() 519 if err != nil { 520 t.Fatalf("cannot create test network: %v", err) 521 } 522 if network == nil { 523 t.Fatal("test network was nil without error") 524 } 525 return network 526 } 527 528 func TestHashEndpoints(t *testing.T) { 529 // TODO: remove skip once the test has been fixed. 530 t.Skip("Skipping failing test on Windows.") 531 Network := mustTestNetwork(t) 532 // Create endpoint A 533 ipConfigA := &hcn.IpConfig{ 534 IpAddress: epIpAddress, 535 } 536 endpointASpec := &hcn.HostComputeEndpoint{ 537 IpConfigurations: []hcn.IpConfig{*ipConfigA}, 538 MacAddress: epMacAddress, 539 SchemaVersion: hcn.SchemaVersion{ 540 Major: 2, 541 Minor: 0, 542 }, 543 } 544 endpointA, err := Network.CreateEndpoint(endpointASpec) 545 if err != nil { 546 t.Error(err) 547 } 548 endpointInfoA := &endpointInfo{ 549 ip: endpointA.IpConfigurations[0].IpAddress, 550 hnsID: endpointA.Id, 551 } 552 // Create Endpoint B 553 ipConfigB := &hcn.IpConfig{ 554 IpAddress: epIpAddressB, 555 } 556 endpointBSpec := &hcn.HostComputeEndpoint{ 557 IpConfigurations: []hcn.IpConfig{*ipConfigB}, 558 MacAddress: epMacAddress, 559 SchemaVersion: hcn.SchemaVersion{ 560 Major: 2, 561 Minor: 0, 562 }, 563 } 564 endpointB, err := Network.CreateEndpoint(endpointBSpec) 565 if err != nil { 566 t.Error(err) 567 } 568 endpointInfoB := &endpointInfo{ 569 ip: endpointB.IpConfigurations[0].IpAddress, 570 hnsID: endpointB.Id, 571 } 572 endpoints := []endpointInfo{*endpointInfoA, *endpointInfoB} 573 endpointsReverse := []endpointInfo{*endpointInfoB, *endpointInfoA} 574 h1, err := hashEndpoints(endpoints) 575 if err != nil { 576 t.Error(err) 577 } else if len(h1) < 1 { 578 t.Error("HashEndpoints failed for endpoints", endpoints) 579 } 580 581 h2, err := hashEndpoints(endpointsReverse) 582 if err != nil { 583 t.Error(err) 584 } 585 if h1 != h2 { 586 t.Errorf("%x does not match %x", h1, h2) 587 } 588 589 // Clean up 590 err = endpointA.Delete() 591 if err != nil { 592 t.Error(err) 593 } 594 err = endpointB.Delete() 595 if err != nil { 596 t.Error(err) 597 } 598 err = Network.Delete() 599 if err != nil { 600 t.Error(err) 601 } 602 } 603 604 func createTestNetwork() (*hcn.HostComputeNetwork, error) { 605 network := &hcn.HostComputeNetwork{ 606 Type: NETWORK_TYPE_OVERLAY, 607 Name: "TestOverlay", 608 MacPool: hcn.MacPool{ 609 Ranges: []hcn.MacRange{ 610 { 611 StartMacAddress: "00-15-5D-52-C0-00", 612 EndMacAddress: "00-15-5D-52-CF-FF", 613 }, 614 }, 615 }, 616 Ipams: []hcn.Ipam{ 617 { 618 Type: "Static", 619 Subnets: []hcn.Subnet{ 620 { 621 IpAddressPrefix: addressPrefix, 622 Routes: []hcn.Route{ 623 { 624 NextHop: gatewayAddress, 625 DestinationPrefix: "0.0.0.0/0", 626 }, 627 }, 628 }, 629 }, 630 }, 631 }, 632 SchemaVersion: hcn.SchemaVersion{ 633 Major: 2, 634 Minor: 0, 635 }, 636 } 637 638 vsid := &hcn.VsidPolicySetting{ 639 IsolationId: 5000, 640 } 641 vsidJson, err := json.Marshal(vsid) 642 if err != nil { 643 return nil, err 644 } 645 646 sp := &hcn.SubnetPolicy{ 647 Type: hcn.VSID, 648 } 649 sp.Settings = vsidJson 650 651 spJson, err := json.Marshal(sp) 652 if err != nil { 653 return nil, err 654 } 655 656 network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson) 657 658 return network.Create() 659 }