github.phpd.cn/cilium/cilium@v1.6.12/test/runtime/connectivity.go (about) 1 package RuntimeTest 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "time" 8 9 . "github.com/cilium/cilium/test/ginkgo-ext" 10 "github.com/cilium/cilium/test/helpers" 11 "github.com/cilium/cilium/test/helpers/constants" 12 13 . "github.com/onsi/gomega" 14 "github.com/onsi/gomega/types" 15 ) 16 17 func runOnNetNextOnly(f func()) func() { 18 if helpers.RunsOnNetNext() { 19 return f 20 } 21 return func() {} 22 } 23 24 var _ = Describe("RuntimeConnectivityInVethModeTest", runtimeConnectivityTest("veth")) 25 var _ = Describe("RuntimeConnectivityInIpvlanModeTest", runOnNetNextOnly(runtimeConnectivityTest("ipvlan"))) 26 27 // TODO(brb) Either create a dummy netdev or determine the master device at runtime 28 const ipvlanMasterDevice = "enp0s8" 29 30 var runtimeConnectivityTest = func(datapathMode string) func() { 31 return func() { 32 var ( 33 vm *helpers.SSHMeta 34 monitorStop = func() error { return nil } 35 ) 36 37 BeforeAll(func() { 38 vm = helpers.InitRuntimeHelper(helpers.Runtime, logger) 39 40 if datapathMode == "ipvlan" { 41 vm.SetUpCiliumInIpvlanMode(ipvlanMasterDevice) 42 // cilium-docker has to be restarted because the datapath mode 43 // has changed 44 vm.Exec("sudo systemctl restart cilium-docker") 45 } 46 47 ExpectCiliumReady(vm) 48 }) 49 50 JustBeforeEach(func() { 51 monitorStop = vm.MonitorStart() 52 }) 53 54 AfterAll(func() { 55 // Restore the datapath mode and cilium-docker 56 if datapathMode == "ipvlan" { 57 vm.SetUpCilium() 58 vm.Exec("sudo systemctl restart cilium-docker") 59 } 60 vm.CloseSSHClient() 61 }) 62 63 removeContainer := func(containerName string) { 64 By("removing container %s", containerName) 65 res := vm.ContainerRm(containerName) 66 ExpectWithOffset(1, res).To(helpers.CMDSuccess(), "cannot delete container") 67 } 68 69 AfterEach(func() { 70 vm.PolicyDelAll().ExpectSuccess("Policies cannot be deleted") 71 }) 72 73 JustAfterEach(func() { 74 vm.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration) 75 Expect(monitorStop()).To(BeNil(), "cannot stop monitor command") 76 }) 77 78 AfterFailed(func() { 79 vm.ReportFailed() 80 }) 81 82 Context("Basic Connectivity test", func() { 83 84 BeforeEach(func() { 85 vm.ContainerCreate(helpers.Client, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.client") 86 vm.ContainerCreate(helpers.Server, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.server") 87 vm.PolicyDelAll() 88 vm.WaitEndpointsReady() 89 err := helpers.WithTimeout(func() bool { 90 if data, _ := vm.GetEndpointsNames(); len(data) < 2 { 91 logger.Info("Waiting for endpoints to be ready") 92 return false 93 } 94 return true 95 }, "Endpoints are not ready", &helpers.TimeoutConfig{Timeout: 150 * time.Second}) 96 Expect(err).Should(BeNil()) 97 98 err = helpers.WithTimeout(func() bool { 99 res := vm.ContainerExec(helpers.Server, "netperf -H 127.0.0.1 -l 1") 100 if !res.WasSuccessful() { 101 logger.Info("Waiting for netserver to come up") 102 } 103 return res.WasSuccessful() 104 }, "netserver did not come up in time", &helpers.TimeoutConfig{Timeout: 20 * time.Second}) 105 Expect(err).Should(BeNil(), "timeout while waiting for netserver to start inside netperf container") 106 }, 150) 107 108 AfterEach(func() { 109 removeContainer(helpers.Client) 110 removeContainer(helpers.Server) 111 return 112 }) 113 114 It("Test connectivity between containers without policies imported", func() { 115 // TODO: this code is duplicated in the next "It" in this file. refactor it into a function. 116 // See if we can make the "Filter" strings for getting IPv4 and IPv6 addresses into constants. 117 By("inspecting container %s", helpers.Server) 118 serverData := vm.ContainerInspect(helpers.Server) 119 serverIP, err := serverData.Filter(fmt.Sprintf("{[0].NetworkSettings.Networks.%s.IPAddress}", helpers.CiliumDockerNetwork)) 120 Expect(err).Should(BeNil()) 121 122 By("serverIP: %q", serverIP) 123 serverIPv6, err := serverData.Filter(fmt.Sprintf("{[0].NetworkSettings.Networks.%s.GlobalIPv6Address}", helpers.CiliumDockerNetwork)) 124 By("serverIPv6: %q", serverIPv6) 125 Expect(err).Should(BeNil()) 126 127 By("checking %q can ping to %q IPv6", helpers.Client, helpers.Server) 128 res := vm.ContainerExec(helpers.Client, helpers.Ping6(serverIPv6.String())) 129 res.ExpectSuccess() 130 131 By("checking %q can ping to %q IPv4", helpers.Client, helpers.Server) 132 res = vm.ContainerExec(helpers.Client, helpers.Ping(serverIP.String())) 133 res.ExpectSuccess() 134 135 // TODO: remove this hardcoding ; it is not clean. Have command wrappers that take maps of strings. 136 By("netperf to %q from %q IPv6", helpers.Server, helpers.Client) 137 cmd := fmt.Sprintf( 138 "netperf -c -C -t TCP_SENDFILE -H %s", serverIPv6) 139 140 res = vm.ContainerExec(helpers.Client, cmd) 141 res.ExpectSuccess() 142 }, 300) 143 144 It("Test connectivity between containers with policy imported", func() { 145 policyID, err := vm.PolicyImportAndWait( 146 fmt.Sprintf("%s/test.policy", vm.ManifestsPath()), 150*time.Second) 147 Expect(err).Should(BeNil()) 148 logger.Debugf("New policy created with id '%d'", policyID) 149 150 serverData := vm.ContainerInspect(helpers.Server) 151 serverIP, err := serverData.Filter(fmt.Sprintf("{[0].NetworkSettings.Networks.%s.IPAddress}", helpers.CiliumDockerNetwork)) 152 Expect(err).Should(BeNil()) 153 By("serverIP: %q", serverIP) 154 serverIPv6, err := serverData.Filter(fmt.Sprintf("{[0].NetworkSettings.Networks.%s.GlobalIPv6Address}", helpers.CiliumDockerNetwork)) 155 By("serverIPv6: %q", serverIPv6) 156 Expect(err).Should(BeNil()) 157 158 By("%q can ping to %q IPV6", helpers.Client, helpers.Server) 159 res := vm.ContainerExec(helpers.Client, helpers.Ping6(serverIPv6.String())) 160 res.ExpectSuccess() 161 162 By("%s can ping to %s IPv4", helpers.Client, helpers.Server) 163 res = vm.ContainerExec(helpers.Client, helpers.Ping(serverIP.String())) 164 res.ExpectSuccess() 165 166 By("netperf to %q from %q (should succeed)", helpers.Server, helpers.Client) 167 cmd := fmt.Sprintf("netperf -c -C -H %s", serverIP) 168 res = vm.ContainerExec(helpers.Client, cmd) 169 170 // TODO: remove this hardcoding ; it is not clean. Have command wrappers that take maps of strings. 171 By("netperf to %q from %q IPv6 with -t TCP_SENDFILE", helpers.Server, helpers.Client) 172 cmd = fmt.Sprintf( 173 "netperf -c -C -t TCP_SENDFILE -H %s", serverIPv6) 174 175 res = vm.ContainerExec(helpers.Client, cmd) 176 res.ExpectSuccess() 177 178 By("super_netperf to %q from %q (should succeed)", helpers.Server, helpers.Client) 179 cmd = fmt.Sprintf("super_netperf 10 -c -C -t TCP_SENDFILE -H %s", serverIP) 180 res = vm.ContainerExec(helpers.Client, cmd) 181 res.ExpectSuccess() 182 183 By("ping from %q to %q", helpers.Host, helpers.Server) 184 res = vm.Exec(helpers.Ping(serverIP.String())) 185 res.ExpectSuccess() 186 }, 300) 187 188 It("Test NAT46 connectivity between containers", func() { 189 if datapathMode == "ipvlan" { 190 Skip("NAT64 is not implemented in the ipvlan mode") 191 } 192 endpoints, err := vm.GetEndpointsIds() 193 Expect(err).Should(BeNil(), "could not get endpoint IDs") 194 195 server, err := vm.ContainerInspectNet(helpers.Server) 196 Expect(err).Should(BeNil()) 197 By("server: %q", server) 198 199 client, err := vm.ContainerInspectNet(helpers.Client) 200 Expect(err).Should(BeNil()) 201 By("client: %q", client) 202 203 status := vm.EndpointSetConfig(endpoints[helpers.Client], "NAT46", helpers.OptionEnabled) 204 Expect(status).Should(BeTrue()) 205 206 areEndpointsReady := vm.WaitEndpointsReady() 207 Expect(areEndpointsReady).Should(BeTrue(), "Endpoints not ready after timeout") 208 209 res := vm.ContainerExec(helpers.Client, helpers.Ping6(fmt.Sprintf( 210 "::FFFF:%s", server[helpers.IPv4]))) 211 212 res.ExpectSuccess() 213 214 res = vm.ContainerExec(helpers.Server, 215 helpers.Ping6(fmt.Sprintf("::FFFF:%s", client[helpers.IPv4]))) 216 res.ExpectFail(fmt.Sprintf("unexpectedly succeeded pinging IPv6 %s from %s", 217 client[helpers.IPv4], helpers.Server)) 218 }) 219 }) 220 221 Context("With CNI", func() { 222 var ( 223 cniPlugin = "/opt/cni/bin/cilium-cni" 224 cniServer = "cni-server" 225 cniClient = "cni-client" 226 netDPath = "/etc/cni/net.d/" 227 tmpDir *helpers.CmdRes 228 ) 229 230 BeforeAll(func() { 231 // Remove any CNI plugin installed in the provision server. This 232 // helps to avoid issues on installing the new CNI 233 _ = vm.ExecWithSudo(fmt.Sprintf("rm -rf %[1]s/*.conf", netDPath)).ExpectSuccess( 234 "CNI config cannot be deleted") 235 236 tmpDir = vm.Exec("mktemp -d") 237 tmpDir.ExpectSuccess("TMP folder cannot be created %s", tmpDir.Output()) 238 }) 239 240 AfterAll(func() { 241 vm.Exec(fmt.Sprintf("rm -rf %s", tmpDir.Output())) 242 }) 243 244 BeforeEach(func() { 245 vm.PolicyDelAll().ExpectSuccess("Policies cannot be deleted") 246 }) 247 248 AfterEach(func() { 249 vm.ContainerRm(cniServer) 250 vm.ContainerRm(cniClient) 251 vm.Exec(fmt.Sprintf("docker rm -f $(docker ps --filter ancestor=%s --format '{{.ID}}')", constants.BusyboxImage)) 252 }) 253 254 runCNIContainer := func(name string, label string) { 255 res := vm.Exec(fmt.Sprintf("docker run -t -d --net=none -l %s %s", label, constants.BusyboxImage)) 256 res.ExpectSuccess() 257 containerID := res.SingleOut() 258 259 pid := vm.Exec(fmt.Sprintf("docker inspect -f '{{ .State.Pid }}' %s", containerID)) 260 pid.ExpectSuccess() 261 netnspath := fmt.Sprintf("/proc/%s/ns/net", pid.SingleOut()) 262 263 res = vm.Exec(fmt.Sprintf( 264 "sudo -E PATH=$PATH:/opt/cni/bin -E CNI_PATH=%[1]s/bin %[1]s/cni/scripts/exec-plugins.sh add %s %s", 265 tmpDir.SingleOut(), containerID, netnspath)) 266 res.ExpectSuccess("CNI exec-plugins did not work correctly") 267 268 res = vm.ContainerCreate( 269 name, constants.NetperfImage, 270 fmt.Sprintf("container:%s", containerID), fmt.Sprintf("-l %s", label)) 271 res.ExpectSuccess("Container %s cannot be created", name) 272 } 273 274 It("Basic connectivity test", func() { 275 filename := "05-cilium-cni.conf" 276 cniConf := `{"name": "cilium", 277 "type": "cilium-cni"}` 278 err := helpers.RenderTemplateToFile(filename, cniConf, os.ModePerm) 279 Expect(err).To(BeNil()) 280 281 cmd := vm.ExecWithSudo(fmt.Sprintf("mv %s %s", 282 helpers.GetFilePath(filename), 283 filepath.Join(netDPath, filename))) 284 cmd.ExpectSuccess("cannot install cilium cni plugin conf") 285 script := fmt.Sprintf(` 286 cd %s && \ 287 git clone https://github.com/containernetworking/cni -b v0.5.2 --single-branch && \ 288 cd cni && \ 289 ./build.sh 290 `, tmpDir.SingleOut()) 291 vm.Exec(script).ExpectSuccess("Cannot install cni") 292 vm.Exec(fmt.Sprintf("cp %s %s", cniPlugin, filepath.Join(tmpDir.SingleOut(), "bin"))) 293 294 By("Importing policy") 295 policyFileName := "CNI-policy.json" 296 policy := ` 297 [{ 298 "endpointSelector": {"matchLabels":{"id.server":""}}, 299 "ingress": [{ 300 "fromEndpoints": [ 301 {"matchLabels":{"reserved:host":""}}, 302 {"matchLabels":{"id.client":""}} 303 ] 304 }] 305 }]` 306 err = helpers.RenderTemplateToFile(policyFileName, policy, os.ModePerm) 307 Expect(err).Should(BeNil()) 308 _, err = vm.PolicyImportAndWait(helpers.GetFilePath(policyFileName), helpers.HelperTimeout) 309 Expect(err).Should(BeNil(), fmt.Sprintf("Cannot import policy %s", policyFileName)) 310 311 By("Adding containers") 312 313 runCNIContainer(cniServer, "id.server") 314 runCNIContainer(cniClient, "id.client") 315 316 areEndpointsReady := vm.WaitEndpointsReady() 317 Expect(areEndpointsReady).Should(BeTrue()) 318 319 serverIPv4 := vm.ContainerExec( 320 cniServer, 321 `ip -4 a show dev eth0 scope global | grep inet | sed -e 's%.*inet \(.*\)\/.*%\1%'`) 322 323 serverIPv6 := vm.ContainerExec( 324 cniServer, 325 `ip -6 a show dev eth0 scope global | grep inet6 | sed -e 's%.*inet6 \(.*\)\/.*%\1%'`) 326 327 vm.ContainerExec(cniClient, helpers.Ping(serverIPv4.SingleOut())).ExpectSuccess( 328 "cannot ping from client to server %q", serverIPv4.SingleOut()) 329 330 vm.ContainerExec(cniClient, helpers.Ping6(serverIPv6.SingleOut())).ExpectSuccess( 331 "cannot ping6 from client to server %q", serverIPv6.SingleOut()) 332 }) 333 }) 334 } 335 } 336 337 var _ = Describe("RuntimeConntrackInVethModeTest", runtimeConntrackTest("veth")) 338 var _ = Describe("RuntimeConntrackInIpvlanModeTest", runOnNetNextOnly(runtimeConntrackTest("ipvlan"))) 339 340 var runtimeConntrackTest = func(datapathMode string) func() { 341 return func() { 342 var ( 343 vm *helpers.SSHMeta 344 monitorStop = func() error { return nil } 345 346 curl1ContainerName = "curl" 347 curl2ContainerName = "curl2" 348 CTPolicyConntrackLocalDisabled = "ct-test-policy-conntrack-local-disabled.json" 349 ) 350 351 type conntestCases struct { 352 from string 353 to string 354 destination string 355 assert func() types.GomegaMatcher 356 } 357 358 BeforeAll(func() { 359 vm = helpers.InitRuntimeHelper(helpers.Runtime, logger) 360 361 if datapathMode == "ipvlan" { 362 vm.SetUpCiliumInIpvlanMode(ipvlanMasterDevice) 363 // cilium-docker has to be restarted because the datapath mode 364 // has changed 365 vm.Exec("sudo systemctl restart cilium-docker") 366 } 367 368 ExpectCiliumReady(vm) 369 370 ExpectPolicyEnforcementUpdated(vm, helpers.PolicyEnforcementAlways) 371 }) 372 373 AfterAll(func() { 374 // Restore the datapath mode and cilium-docker 375 if datapathMode == "ipvlan" { 376 vm.SetUpCilium() 377 vm.Exec("sudo systemctl restart cilium-docker") 378 } 379 vm.CloseSSHClient() 380 }) 381 382 clientServerConnectivity := func() { 383 By("============= Starting Connectivity Test ============= ") 384 385 By("Getting IPs of each spawned container") 386 clientDockerNetworking, err := vm.ContainerInspectNet(helpers.Client) 387 ExpectWithOffset(1, err).Should(BeNil(), 388 "could not get metadata for container %q", helpers.Client) 389 By("client container Docker networking: %q", clientDockerNetworking) 390 391 serverDockerNetworking, err := vm.ContainerInspectNet(helpers.Server) 392 ExpectWithOffset(1, err).Should(BeNil(), 393 "could not get metadata for container %q", helpers.Server) 394 By("server container Docker networking: %q", serverDockerNetworking) 395 396 httpdDockerNetworking, err := vm.ContainerInspectNet(helpers.Httpd1) 397 ExpectWithOffset(1, err).Should(BeNil(), 398 "could not get metadata for container %q", helpers.Httpd1) 399 By("httpd1 container Docker networking: %q", httpdDockerNetworking) 400 401 httpd2DockerNetworking, err := vm.ContainerInspectNet(helpers.Httpd2) 402 ExpectWithOffset(1, err).Should(BeNil(), 403 "could not get metadata for container %q", helpers.Httpd2) 404 By("httpd2 container Docker networking: %q", httpd2DockerNetworking) 405 406 curl1DockerNetworking, err := vm.ContainerInspectNet(curl1ContainerName) 407 ExpectWithOffset(1, err).Should(BeNil(), 408 "could not get metadata for container %q", curl1ContainerName) 409 By("curl1 container Docker networking: %q", curl1DockerNetworking) 410 411 curl2DockerNetworking, err := vm.ContainerInspectNet(curl2ContainerName) 412 ExpectWithOffset(1, err).Should(BeNil(), 413 "could not get metadata for container %q", curl2ContainerName) 414 By("httpd1 container Docker networking: %q", curl2DockerNetworking) 415 416 By("Showing policies imported to Cilium") 417 res := vm.PolicyGetAll() 418 GinkgoPrint(res.CombineOutput().String()) 419 420 testCases := []conntestCases{ 421 { 422 from: curl1ContainerName, 423 to: helpers.CurlFail("http://[%s]:80", httpdDockerNetworking[helpers.IPv6]), 424 destination: helpers.Httpd1, 425 assert: BeTrue, 426 }, 427 { 428 from: curl1ContainerName, 429 to: helpers.CurlFail("http://%s:80", httpdDockerNetworking[helpers.IPv4]), 430 destination: helpers.Httpd1, 431 assert: BeTrue, 432 }, 433 { 434 from: curl2ContainerName, 435 to: helpers.CurlFail("http://[%s]:80", httpdDockerNetworking[helpers.IPv6]), 436 destination: helpers.Httpd1, 437 assert: BeFalse, 438 }, 439 { 440 from: curl2ContainerName, 441 to: helpers.CurlFail("http://%s:80", httpdDockerNetworking[helpers.IPv4]), 442 destination: helpers.Httpd1, 443 assert: BeFalse, 444 }, 445 { 446 from: curl1ContainerName, 447 to: helpers.CurlFail("http://[%s]:80", httpd2DockerNetworking[helpers.IPv6]), 448 destination: helpers.Httpd2, 449 assert: BeFalse, 450 }, 451 { 452 from: curl1ContainerName, 453 to: helpers.CurlFail("http://%s:80", httpd2DockerNetworking[helpers.IPv4]), 454 destination: helpers.Httpd2, 455 assert: BeFalse, 456 }, 457 { 458 from: curl2ContainerName, 459 to: helpers.CurlFail("http://[%s]:80", httpdDockerNetworking[helpers.IPv6]), 460 destination: helpers.Httpd2, 461 assert: BeFalse, 462 }, 463 { 464 from: curl2ContainerName, 465 to: helpers.CurlFail("http://%s:80", httpdDockerNetworking[helpers.IPv4]), 466 destination: helpers.Httpd2, 467 assert: BeFalse, 468 }, 469 { 470 from: helpers.Client, 471 to: helpers.Ping6(serverDockerNetworking[helpers.IPv6]), 472 destination: helpers.Server, 473 assert: BeTrue, 474 }, 475 { 476 from: helpers.Client, 477 to: helpers.Ping(serverDockerNetworking[helpers.IPv4]), 478 destination: helpers.Server, 479 assert: BeTrue, 480 }, 481 { 482 from: helpers.Client, 483 to: helpers.Netcat("%s 777", serverDockerNetworking[helpers.IPv6]), 484 destination: helpers.Server, 485 assert: BeFalse, 486 }, 487 { 488 from: helpers.Client, 489 to: helpers.Netcat("%s 777", serverDockerNetworking[helpers.IPv4]), 490 destination: helpers.Server, 491 assert: BeFalse, 492 }, 493 494 { 495 from: helpers.Client, 496 to: helpers.Netperf(serverDockerNetworking[helpers.IPv6], helpers.TCP_RR), 497 destination: helpers.Server, 498 assert: BeTrue, 499 }, 500 { 501 from: helpers.Client, 502 to: helpers.Netperf(serverDockerNetworking[helpers.IPv4], helpers.TCP_RR), 503 destination: helpers.Server, 504 assert: BeTrue, 505 }, 506 { 507 from: helpers.Client, 508 to: helpers.Netperf(serverDockerNetworking[helpers.IPv6], helpers.UDP_RR), 509 destination: helpers.Server, 510 assert: BeTrue, 511 }, 512 { 513 from: helpers.Client, 514 to: helpers.Netperf(serverDockerNetworking[helpers.IPv4], helpers.UDP_RR), 515 destination: helpers.Server, 516 assert: BeTrue, 517 }, 518 } 519 520 for _, test := range testCases { 521 By("Container %q test connectivity to %q", test.from, test.destination) 522 res = vm.ContainerExec(test.from, test.to) 523 ExpectWithOffset(1, res.WasSuccessful()).To(test.assert(), 524 "The result of %q from container %q to %s does not match", test.to, test.from, test.destination) 525 } 526 527 By("Testing bidirectional connectivity from client to server") 528 529 By("container %s pinging %s IPv6 (should NOT work)", helpers.Server, helpers.Client) 530 res = vm.ContainerExec(helpers.Server, helpers.Ping6(clientDockerNetworking[helpers.IPv6])) 531 ExpectWithOffset(1, res).ShouldNot(helpers.CMDSuccess(), 532 "container %q unexpectedly was able to ping to %q IP:%q", helpers.Server, helpers.Client, clientDockerNetworking[helpers.IPv6]) 533 534 By("container %s pinging %s IPv4 (should NOT work)", helpers.Server, helpers.Client) 535 res = vm.ContainerExec(helpers.Server, helpers.Ping(clientDockerNetworking[helpers.IPv4])) 536 ExpectWithOffset(1, res).ShouldNot(helpers.CMDSuccess(), 537 "%q was unexpectedly able to ping to %q IP:%q", helpers.Server, helpers.Client, clientDockerNetworking[helpers.IPv4]) 538 539 By("============= Finished Connectivity Test ============= ") 540 } 541 542 clientServerL3Connectivity := func() { 543 By("============= Starting Connectivity Test ============= ") 544 545 By("Getting IPs of each spawned container") 546 clientDockerNetworking, err := vm.ContainerInspectNet(helpers.Client) 547 ExpectWithOffset(1, err).Should(BeNil(), 548 "could not get metadata for container %q", helpers.Client) 549 By("client container Docker networking: %s", clientDockerNetworking) 550 551 serverDockerNetworking, err := vm.ContainerInspectNet(helpers.Server) 552 ExpectWithOffset(1, err).Should(BeNil(), 553 "could not get metadata for container %q", helpers.Server) 554 By("server container Docker networking: %s", serverDockerNetworking) 555 556 httpdDockerNetworking, err := vm.ContainerInspectNet(helpers.Httpd1) 557 ExpectWithOffset(1, err).Should(BeNil(), 558 "could not get metadata for container %q", helpers.Httpd1) 559 By("httpd1 container Docker networking: %s", httpdDockerNetworking) 560 561 httpd2DockerNetworking, err := vm.ContainerInspectNet(helpers.Httpd2) 562 ExpectWithOffset(1, err).Should(BeNil(), 563 "could not get metadata for container %q", helpers.Httpd2) 564 By("httpd2 container Docker networking: %s", httpd2DockerNetworking) 565 566 curl1DockerNetworking, err := vm.ContainerInspectNet(curl1ContainerName) 567 ExpectWithOffset(1, err).Should(BeNil(), 568 "could not get metadata for container %q", curl1ContainerName) 569 By("curl1 container Docker networking: %s", curl1DockerNetworking) 570 571 curl2DockerNetworking, err := vm.ContainerInspectNet(curl2ContainerName) 572 ExpectWithOffset(1, err).Should(BeNil(), 573 "could not get metadata for container %q", curl2ContainerName) 574 By("httpd1 container Docker networking: %s", curl2DockerNetworking) 575 576 By("Showing policies imported to Cilium") 577 res := vm.PolicyGetAll() 578 GinkgoPrint(res.CombineOutput().String()) 579 580 testCases := []conntestCases{ 581 { 582 from: curl1ContainerName, 583 to: helpers.CurlFail("http://[%s]:80", httpdDockerNetworking[helpers.IPv6]), 584 destination: helpers.Httpd1, 585 assert: BeTrue, 586 }, 587 { 588 from: curl1ContainerName, 589 to: helpers.CurlFail("http://%s:80", httpdDockerNetworking[helpers.IPv4]), 590 destination: helpers.Httpd1, 591 assert: BeTrue, 592 }, 593 { 594 from: curl2ContainerName, 595 to: helpers.CurlFail("http://[%s]:80", httpdDockerNetworking[helpers.IPv6]), 596 destination: helpers.Httpd1, 597 assert: BeFalse, 598 }, 599 { 600 from: curl2ContainerName, 601 to: helpers.CurlFail("http://%s:80", httpdDockerNetworking[helpers.IPv4]), 602 destination: helpers.Httpd1, 603 assert: BeFalse, 604 }, 605 { 606 from: curl1ContainerName, 607 to: helpers.CurlFail("http://[%s]:80", httpd2DockerNetworking[helpers.IPv6]), 608 destination: helpers.Httpd2, 609 assert: BeFalse, 610 }, 611 { 612 from: curl1ContainerName, 613 to: helpers.CurlFail("http://%s:80", httpd2DockerNetworking[helpers.IPv4]), 614 destination: helpers.Httpd2, 615 assert: BeFalse, 616 }, 617 { 618 from: curl2ContainerName, 619 to: helpers.CurlFail("http://[%s]:80", httpd2DockerNetworking[helpers.IPv6]), 620 destination: helpers.Httpd2, 621 assert: BeFalse, 622 }, 623 { 624 from: curl2ContainerName, 625 to: helpers.CurlFail("http://%s:80", httpd2DockerNetworking[helpers.IPv4]), 626 destination: helpers.Httpd2, 627 assert: BeFalse, 628 }, 629 { 630 from: helpers.Client, 631 to: helpers.Ping6(serverDockerNetworking[helpers.IPv6]), 632 destination: helpers.Server, 633 assert: BeTrue, 634 }, 635 { 636 from: helpers.Client, 637 to: helpers.Ping(serverDockerNetworking[helpers.IPv4]), 638 destination: helpers.Server, 639 assert: BeTrue, 640 }, 641 { 642 from: helpers.Client, 643 to: helpers.Netperf(serverDockerNetworking[helpers.IPv6], helpers.TCP_RR), 644 destination: helpers.Server, 645 assert: BeTrue, 646 }, 647 { 648 from: helpers.Client, 649 to: helpers.Netperf(serverDockerNetworking[helpers.IPv4], helpers.TCP_RR), 650 destination: helpers.Server, 651 assert: BeTrue, 652 }, 653 { 654 from: helpers.Client, 655 to: helpers.Netperf(serverDockerNetworking[helpers.IPv6], helpers.UDP_RR), 656 destination: helpers.Server, 657 assert: BeTrue, 658 }, 659 { 660 from: helpers.Client, 661 to: helpers.Netperf(serverDockerNetworking[helpers.IPv4], helpers.UDP_RR), 662 destination: helpers.Server, 663 assert: BeTrue, 664 }, 665 } 666 667 for _, test := range testCases { 668 By("Container %q test connectivity to %q", test.from, test.destination) 669 res = vm.ContainerExec(test.from, test.to) 670 ExpectWithOffset(1, res.WasSuccessful()).To(test.assert(), 671 "The result of %q from container %q to %s does not match", test.to, test.from, test.destination) 672 } 673 674 By("============= Finished Connectivity Test ============= ") 675 } 676 677 BeforeEach(func() { 678 // TODO: provide map[string]string instead of one string representing KV pair. 679 vm.ContainerCreate(helpers.Client, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.client") 680 vm.ContainerCreate(helpers.Server, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.server") 681 vm.ContainerCreate(helpers.Httpd1, constants.HttpdImage, helpers.CiliumDockerNetwork, "-l id.httpd") 682 vm.ContainerCreate(helpers.Httpd2, constants.HttpdImage, helpers.CiliumDockerNetwork, "-l id.httpd_deny") 683 vm.ContainerCreate(curl1ContainerName, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.curl") 684 vm.ContainerCreate(curl2ContainerName, constants.NetperfImage, helpers.CiliumDockerNetwork, "-l id.curl2") 685 686 vm.PolicyDelAll().ExpectSuccess("cannot delete all policies") 687 688 _, err := vm.PolicyImportAndWait(vm.GetFullPath("ct-test-policy.json"), helpers.HelperTimeout) 689 Expect(err).Should(BeNil()) 690 691 }) 692 693 JustBeforeEach(func() { 694 monitorStop = vm.MonitorStart() 695 }) 696 697 AfterEach(func() { 698 containersToRm := []string{helpers.Client, helpers.Server, helpers.Httpd1, helpers.Httpd2, curl1ContainerName, curl2ContainerName} 699 for _, containerToRm := range containersToRm { 700 vm.ContainerRm(containerToRm) 701 } 702 vm.PolicyDelAll().ExpectSuccess("Policies cannot be deleted") 703 704 ExpectPolicyEnforcementUpdated(vm, helpers.PolicyEnforcementDefault) 705 }) 706 707 JustAfterEach(func() { 708 vm.ValidateNoErrorsInLogs(CurrentGinkgoTestDescription().Duration) 709 Expect(monitorStop()).To(BeNil(), "cannot stop monitor command") 710 }) 711 712 AfterFailed(func() { 713 vm.ReportFailed("cilium policy get") 714 }) 715 716 It("Conntrack-related configuration options for endpoints", func() { 717 By("Getting Endpoint IDs") 718 endpoints, err := vm.GetEndpointsIds() 719 Expect(err).Should(BeNil(), "could not get endpoint IDs") 720 721 // Check that endpoint IDs exist in map. 722 for _, endpointName := range []string{helpers.Server, helpers.Client} { 723 _, exists := endpoints[endpointName] 724 Expect(exists).To(BeTrue(), "unable to retrieve endpoint ID for endpoint %s", endpointName) 725 By("Endpoint ID for %q = %q", endpointName, endpoints[endpointName]) 726 727 } 728 729 endpointsToConfigure := []string{endpoints[helpers.Server], endpoints[helpers.Client]} 730 731 // Iterate through possible values to configure ConntrackLocal option, 732 // apply to both endpoints, verify the option configuration change matches 733 // what was performed, and then run connectivity test with endpoints. 734 conntrackLocalOptionModes := []string{helpers.OptionDisabled, helpers.OptionEnabled} 735 for _, conntrackLocalOptionMode := range conntrackLocalOptionModes { 736 By("Testing with endpoint configuration option: ConntrackLocal=%s", conntrackLocalOptionMode) 737 738 for _, endpointToConfigure := range endpointsToConfigure { 739 err := vm.SetAndWaitForEndpointConfiguration( 740 endpointToConfigure, helpers.OptionConntrackLocal, conntrackLocalOptionMode) 741 Expect(err).To(BeNil(), "Cannot set ConnTrackLocal=%q for endpoint %q", 742 conntrackLocalOptionMode, endpointToConfigure) 743 } 744 areEndpointsReady := vm.WaitEndpointsReady() 745 Expect(areEndpointsReady).Should(BeTrue(), "Endpoints are not ready after timeout") 746 clientServerConnectivity() 747 } 748 749 By("Testing Conntrack endpoint configuration option disabled") 750 751 // Delete all L4 policy so we can disable connection tracking 752 vm.PolicyDelAll().ExpectSuccess("Policies cannot be deleted") 753 754 for _, endpointToConfigure := range endpointsToConfigure { 755 // ConntrackLocal must be disabled as it depends on Conntrack 756 err := vm.SetAndWaitForEndpointConfiguration(endpointToConfigure, helpers.OptionConntrackLocal, helpers.OptionDisabled) 757 Expect(err).To(BeNil(), "Cannot disable ConntrackLocal for the endpoint %q", endpointToConfigure) 758 err = vm.SetAndWaitForEndpointConfiguration(endpointToConfigure, helpers.OptionConntrack, helpers.OptionDisabled) 759 Expect(err).To(BeNil(), "Cannot disable ConnTrack for the endpoint %q", endpointToConfigure) 760 } 761 762 // Need to add policy that allows communication in both directions. 763 _, err = vm.PolicyImportAndWait( 764 vm.GetFullPath(CTPolicyConntrackLocalDisabled), 765 helpers.HelperTimeout) 766 Expect(err).Should(BeNil(), "cannot import %s", CTPolicyConntrackLocalDisabled) 767 768 clientServerL3Connectivity() 769 }) 770 771 } 772 }