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