go.ligato.io/vpp-agent/v3@v3.5.0/tests/e2e/050_nat_test.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package e2e 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 "testing" 22 23 . "github.com/onsi/gomega" 24 25 "go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler" 26 linux_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces" 27 linux_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/linux/l3" 28 linux_namespace "go.ligato.io/vpp-agent/v3/proto/ligato/linux/namespace" 29 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 30 vpp_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 31 vpp_nat "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/nat" 32 . "go.ligato.io/vpp-agent/v3/tests/e2e/e2etest" 33 ) 34 35 // Simulate public and private networks using two microservices and test 36 // source-NAT in-between. 37 func TestSourceNAT(t *testing.T) { 38 ctx := Setup(t) 39 defer ctx.Teardown() 40 41 const ( 42 // public network 43 vppTap1Name = "vpp-tap1" 44 vppTap1IP = "80.80.80.20" 45 linuxTap1Name = "linux-tap1" 46 linuxTap1Hostname = "tap" 47 linuxTap1IP = "80.80.80.10" 48 49 // private network 50 vppTap2Name = "vpp-tap2" 51 vppTap2IP = "192.168.1.1" 52 linuxTap2Name = "linux-tap2" 53 linuxTap2Hostname = "tap" 54 linuxTap2IP = "192.168.1.2" 55 56 // nat 57 sNatAddr1 = vppTap1IP 58 sNatAddr2 = "80.80.80.21" 59 sNatAddr3 = "80.80.80.22" 60 61 netMask = "/24" 62 ms1Name = "microservice1" 63 ms2Name = "microservice2" 64 ) 65 66 vppTap1 := &vpp_interfaces.Interface{ 67 Name: vppTap1Name, 68 Type: vpp_interfaces.Interface_TAP, 69 Enabled: true, 70 IpAddresses: []string{vppTap1IP + netMask}, 71 Link: &vpp_interfaces.Interface_Tap{ 72 Tap: &vpp_interfaces.TapLink{ 73 Version: 2, 74 ToMicroservice: MsNamePrefix + ms1Name, 75 }, 76 }, 77 } 78 linuxTap1 := &linux_interfaces.Interface{ 79 Name: linuxTap1Name, 80 Type: linux_interfaces.Interface_TAP_TO_VPP, 81 Enabled: true, 82 IpAddresses: []string{linuxTap1IP + netMask}, 83 HostIfName: linuxTap1Hostname, 84 Link: &linux_interfaces.Interface_Tap{ 85 Tap: &linux_interfaces.TapLink{ 86 VppTapIfName: vppTap1Name, 87 }, 88 }, 89 Namespace: &linux_namespace.NetNamespace{ 90 Type: linux_namespace.NetNamespace_MICROSERVICE, 91 Reference: MsNamePrefix + ms1Name, 92 }, 93 } 94 95 vppTap2 := &vpp_interfaces.Interface{ 96 Name: vppTap2Name, 97 Type: vpp_interfaces.Interface_TAP, 98 Enabled: true, 99 IpAddresses: []string{vppTap2IP + netMask}, 100 Link: &vpp_interfaces.Interface_Tap{ 101 Tap: &vpp_interfaces.TapLink{ 102 Version: 2, 103 ToMicroservice: MsNamePrefix + ms2Name, 104 }, 105 }, 106 } 107 linuxTap2 := &linux_interfaces.Interface{ 108 Name: linuxTap2Name, 109 Type: linux_interfaces.Interface_TAP_TO_VPP, 110 Enabled: true, 111 IpAddresses: []string{linuxTap2IP + netMask}, 112 HostIfName: linuxTap2Hostname, 113 Link: &linux_interfaces.Interface_Tap{ 114 Tap: &linux_interfaces.TapLink{ 115 VppTapIfName: vppTap2Name, 116 }, 117 }, 118 Namespace: &linux_namespace.NetNamespace{ 119 Type: linux_namespace.NetNamespace_MICROSERVICE, 120 Reference: MsNamePrefix + ms2Name, 121 }, 122 } 123 124 ms2DefaultRoute := &linux_l3.Route{ 125 OutgoingInterface: linuxTap2Name, 126 Scope: linux_l3.Route_GLOBAL, 127 DstNetwork: "0.0.0.0/0", 128 GwAddr: vppTap2IP, 129 } 130 131 natGlobal := &vpp_nat.Nat44Global{ 132 Forwarding: true, 133 } 134 natInterface := &vpp_nat.Nat44Interface{ 135 Name: vppTap1Name, 136 OutputFeature: true, 137 } 138 // Looks like VPP versions > 22.02 changed the output feature 139 // (or in newer versions output interface) API so that OutputFeature 140 // and Inside/Outside flags are mutually exclusive 141 if ctx.VppRelease() <= "22.02" { 142 natInterface.NatOutside = true 143 } 144 natPool := &vpp_nat.Nat44AddressPool{ 145 FirstIp: sNatAddr1, 146 LastIp: sNatAddr3, 147 } 148 149 nat44Addresses := func() (string, error) { 150 return ctx.ExecVppctl("show", "nat44", "addresses") 151 } 152 connectTCP := func() error { 153 return ctx.TestConnection(ms2Name, ms1Name, linuxTap1IP, linuxTap1IP, 154 8000, 8000, false, Tapv2InputNode) 155 } 156 connectUDP := func() error { 157 return ctx.TestConnection(ms2Name, ms1Name, linuxTap1IP, linuxTap1IP, 158 8000, 8000, true, Tapv2InputNode) 159 } 160 ping := func() error { 161 return ctx.PingFromMs(ms2Name, linuxTap1IP) 162 } 163 164 ctx.StartMicroservice(ms1Name) 165 ctx.StartMicroservice(ms2Name) 166 ctx.Expect(nat44Addresses()).ShouldNot(SatisfyAny( 167 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 168 req := ctx.GenericClient().ChangeRequest() 169 err := req.Update( 170 vppTap1, 171 linuxTap1, 172 vppTap2, 173 linuxTap2, 174 ms2DefaultRoute, 175 natGlobal, 176 natInterface, 177 natPool, 178 ).Send(context.Background()) 179 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating public and private networks failed") 180 181 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 182 "TAP attached to a newly started microservice1 should be eventually configured") 183 ctx.Eventually(ctx.GetValueStateClb(vppTap2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 184 "TAP attached to a newly started microservice2 should be eventually configured") 185 186 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 187 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 188 ctx.Expect(ping()).Should(Succeed()) 189 ctx.Expect(connectTCP()).Should(Succeed()) 190 ctx.Expect(connectUDP()).Should(Succeed()) 191 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 192 193 // remove S-NAT configuration 194 req = ctx.GenericClient().ChangeRequest() 195 err = req.Delete( 196 natGlobal, 197 natInterface, 198 natPool, 199 ).Send(context.Background()) 200 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction removing S-NAT failed") 201 202 // check configuration 203 ctx.Expect(nat44Addresses()).ShouldNot(SatisfyAny( 204 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 205 ctx.Expect(ping()).ShouldNot(Succeed()) 206 ctx.Expect(connectTCP()).ShouldNot(Succeed()) 207 ctx.Expect(connectUDP()).ShouldNot(Succeed()) 208 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 209 210 // get back the S-NAT configuration 211 req = ctx.GenericClient().ChangeRequest() 212 err = req.Update( 213 natGlobal, 214 natInterface, 215 natPool, 216 ).Send(context.Background()) 217 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating S-NAT failed") 218 219 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 220 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 221 ctx.Expect(ping()).Should(Succeed()) 222 ctx.Expect(connectTCP()).Should(Succeed()) 223 ctx.Expect(connectUDP()).Should(Succeed()) 224 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 225 226 // restart microservice with S-NAT attached 227 ctx.StopMicroservice(ms1Name) 228 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_PENDING), 229 "Without microservice, the associated VPP-TAP should be pending") 230 ctx.StartMicroservice(ms1Name) 231 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 232 "VPP-TAP attached to a re-started microservice1 should be eventually configured") 233 234 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 235 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 236 ctx.Expect(ping()).Should(Succeed()) 237 ctx.Expect(connectTCP()).Should(Succeed()) 238 ctx.Expect(connectUDP()).Should(Succeed()) 239 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 240 } 241 242 // Tests NAT pool CRUD operation and NAT pool resync. 243 func TestNATPools(t *testing.T) { 244 // variable/helper method initialization 245 const addressCount = 7 246 addresses := make([]string, addressCount) 247 for i := 0; i < addressCount; i++ { 248 addresses[i] = fmt.Sprintf("80.80.80.%d", i) 249 } 250 nat44Addresses := func(ctx *TestCtx) func() (string, error) { 251 return func() (string, error) { 252 return ctx.ExecVppctl("show", "nat44", "addresses") 253 } 254 } 255 mustBeInVPP := func(ctx *TestCtx, addrs []string) { 256 for _, addr := range addrs { // Eventually is needed due to VPP-Agent to VPP configuration delay 257 ctx.Eventually(nat44Addresses(ctx)).Should(ContainSubstring(addr)) 258 } 259 } 260 cantBeInVPP := func(ctx *TestCtx, addrs []string) { 261 for _, addr := range addrs { // Eventually is needed due to VPP-Agent to VPP configuration delay 262 ctx.Eventually(nat44Addresses(ctx)).ShouldNot(ContainSubstring(addr)) 263 } 264 } 265 266 // tests 267 tests := []struct { 268 name string 269 createNATPool *vpp_nat.Nat44AddressPool 270 checkAfterCreation func(ctx *TestCtx) 271 updateNATPool *vpp_nat.Nat44AddressPool 272 checkAfterUpdate func(ctx *TestCtx) 273 checkAfterDelete func(ctx *TestCtx) 274 }{ 275 { 276 name: "CRUD for named pool", 277 createNATPool: &vpp_nat.Nat44AddressPool{ 278 Name: "myPool", 279 FirstIp: addresses[0], 280 LastIp: addresses[2], 281 }, 282 checkAfterCreation: func(ctx *TestCtx) { 283 mustBeInVPP(ctx, addresses[0:3]) // initial creation 284 }, 285 updateNATPool: &vpp_nat.Nat44AddressPool{ 286 Name: "myPool", 287 FirstIp: addresses[4], 288 LastIp: addresses[6], 289 }, 290 checkAfterUpdate: func(ctx *TestCtx) { 291 cantBeInVPP(ctx, addresses[0:3]) // old addresses are deleted 292 mustBeInVPP(ctx, addresses[4:7]) // new addresses are created 293 }, 294 checkAfterDelete: func(ctx *TestCtx) { 295 cantBeInVPP(ctx, addresses) // empty pool after deleting only pool 296 }, 297 }, 298 { 299 name: "CRUD for unnamed pool", 300 createNATPool: &vpp_nat.Nat44AddressPool{ 301 FirstIp: addresses[0], 302 LastIp: addresses[2], 303 }, 304 checkAfterCreation: func(ctx *TestCtx) { 305 mustBeInVPP(ctx, addresses[0:3]) // initial creation 306 }, 307 updateNATPool: &vpp_nat.Nat44AddressPool{ 308 FirstIp: addresses[4], 309 LastIp: addresses[6], 310 }, 311 checkAfterUpdate: func(ctx *TestCtx) { 312 // unnamed pools are not tied by name in key 313 // -> update with different ip addresses == create another pool 314 mustBeInVPP(ctx, addresses[0:3]) 315 mustBeInVPP(ctx, addresses[4:7]) 316 }, 317 checkAfterDelete: func(ctx *TestCtx) { 318 mustBeInVPP(ctx, addresses[0:3]) // original create won't get deleted 319 cantBeInVPP(ctx, addresses[4:7]) // the updated is deleted 320 }, 321 }, 322 } 323 324 for _, test := range tests { 325 t.Run(test.name, func(t *testing.T) { 326 ctx := Setup(t) 327 defer ctx.Teardown() 328 329 // check empty pool state 330 cantBeInVPP(ctx, addresses) 331 332 // create NAT pool 333 req := ctx.GenericClient().ChangeRequest() 334 err := req.Update( 335 &vpp_nat.Nat44Global{}, 336 test.createNATPool, 337 ).Send(context.Background()) 338 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating nat pool failed") 339 test.checkAfterCreation(ctx) 340 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") // resync 341 342 // update NAT pool 343 req = ctx.GenericClient().ChangeRequest() 344 err = req.Update( 345 test.updateNATPool, 346 ).Send(context.Background()) 347 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction updating nat pool failed") 348 test.checkAfterUpdate(ctx) 349 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") // resync 350 351 // delete NAT pool 352 req = ctx.GenericClient().ChangeRequest() 353 err = req.Delete( 354 test.updateNATPool, 355 ).Send(context.Background()) 356 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction deleting NAT pool failed") 357 test.checkAfterDelete(ctx) 358 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") // resync 359 }) 360 } 361 } 362 363 // Simulate use-case in which a service located in a private network is published 364 // on a publicly accessible IP address. 365 func TestNATStaticMappings(t *testing.T) { 366 ctx := Setup(t) 367 defer ctx.Teardown() 368 369 const ( 370 // public network 371 vppTap1Name = "vpp-tap1" 372 vppTap1IP = "80.80.80.20" 373 linuxTap1Name = "linux-tap1" 374 linuxTap1Hostname = "tap" 375 linuxTap1IP = "80.80.80.10" 376 377 // private network 378 vppTap2Name = "vpp-tap2" 379 vppTap2IP = "192.168.1.1" 380 linuxTap2Name = "linux-tap2" 381 linuxTap2Hostname = "tap" 382 linuxTap2IP = "192.168.1.2" 383 384 // nat 385 tcpSvcLabel = "tcp-service" 386 tcpSvcExtIP = "80.80.80.30" 387 tcpSvcExtPort = 8888 388 tcpSvcLocalPort = 8000 389 udpSvcLabel = "udp-service" 390 udpSvcExtIP = "80.80.80.50" 391 udpSvcExtPort = 9999 392 udpSvcLocalPort = 9000 393 394 netMask = "/24" 395 ms1Name = "microservice1" 396 ms2Name = "microservice2" 397 ) 398 399 vppTap1 := &vpp_interfaces.Interface{ 400 Name: vppTap1Name, 401 Type: vpp_interfaces.Interface_TAP, 402 Enabled: true, 403 IpAddresses: []string{vppTap1IP + netMask}, 404 Link: &vpp_interfaces.Interface_Tap{ 405 Tap: &vpp_interfaces.TapLink{ 406 Version: 2, 407 ToMicroservice: MsNamePrefix + ms1Name, 408 }, 409 }, 410 } 411 linuxTap1 := &linux_interfaces.Interface{ 412 Name: linuxTap1Name, 413 Type: linux_interfaces.Interface_TAP_TO_VPP, 414 Enabled: true, 415 IpAddresses: []string{linuxTap1IP + netMask}, 416 HostIfName: linuxTap1Hostname, 417 Link: &linux_interfaces.Interface_Tap{ 418 Tap: &linux_interfaces.TapLink{ 419 VppTapIfName: vppTap1Name, 420 }, 421 }, 422 Namespace: &linux_namespace.NetNamespace{ 423 Type: linux_namespace.NetNamespace_MICROSERVICE, 424 Reference: MsNamePrefix + ms1Name, 425 }, 426 } 427 428 vppTap2 := &vpp_interfaces.Interface{ 429 Name: vppTap2Name, 430 Type: vpp_interfaces.Interface_TAP, 431 Enabled: true, 432 IpAddresses: []string{vppTap2IP + netMask}, 433 Link: &vpp_interfaces.Interface_Tap{ 434 Tap: &vpp_interfaces.TapLink{ 435 Version: 2, 436 ToMicroservice: MsNamePrefix + ms2Name, 437 }, 438 }, 439 } 440 linuxTap2 := &linux_interfaces.Interface{ 441 Name: linuxTap2Name, 442 Type: linux_interfaces.Interface_TAP_TO_VPP, 443 Enabled: true, 444 IpAddresses: []string{linuxTap2IP + netMask}, 445 HostIfName: linuxTap2Hostname, 446 Link: &linux_interfaces.Interface_Tap{ 447 Tap: &linux_interfaces.TapLink{ 448 VppTapIfName: vppTap2Name, 449 }, 450 }, 451 Namespace: &linux_namespace.NetNamespace{ 452 Type: linux_namespace.NetNamespace_MICROSERVICE, 453 Reference: MsNamePrefix + ms2Name, 454 }, 455 } 456 457 ms2DefaultRoute := &linux_l3.Route{ 458 OutgoingInterface: linuxTap2Name, 459 Scope: linux_l3.Route_GLOBAL, 460 DstNetwork: "0.0.0.0/0", 461 GwAddr: vppTap2IP, 462 } 463 464 natGlobal := &vpp_nat.Nat44Global{ 465 Forwarding: true, 466 } 467 natInterface1 := &vpp_nat.Nat44Interface{ 468 Name: vppTap1Name, 469 NatOutside: true, 470 } 471 natInterface2 := &vpp_nat.Nat44Interface{ 472 Name: vppTap2Name, 473 NatInside: true, 474 } 475 476 tcpSvc := &vpp_nat.DNat44{ 477 Label: tcpSvcLabel, 478 StMappings: []*vpp_nat.DNat44_StaticMapping{ 479 { 480 ExternalIp: tcpSvcExtIP, 481 ExternalPort: tcpSvcExtPort, 482 Protocol: vpp_nat.DNat44_TCP, 483 LocalIps: []*vpp_nat.DNat44_StaticMapping_LocalIP{ 484 { 485 LocalIp: linuxTap2IP, 486 LocalPort: tcpSvcLocalPort, 487 }, 488 }, 489 }, 490 }, 491 } 492 493 udpSvc := &vpp_nat.DNat44{ 494 Label: udpSvcLabel, 495 StMappings: []*vpp_nat.DNat44_StaticMapping{ 496 { 497 ExternalIp: udpSvcExtIP, 498 ExternalPort: udpSvcExtPort, 499 Protocol: vpp_nat.DNat44_UDP, 500 LocalIps: []*vpp_nat.DNat44_StaticMapping_LocalIP{ 501 { 502 LocalIp: linuxTap2IP, 503 LocalPort: udpSvcLocalPort, 504 }, 505 }, 506 }, 507 }, 508 } 509 510 // without proxy ARP, the client running from microservice1 (public net), 511 // will not get any response for ARP requests concerning service external IPs 512 // from VPP 513 svcExtIPsProxyArp := &vpp_l3.ProxyARP{ 514 Interfaces: []*vpp_l3.ProxyARP_Interface{ 515 { 516 Name: vppTap1Name, 517 }, 518 }, 519 Ranges: []*vpp_l3.ProxyARP_Range{ 520 { 521 FirstIpAddr: tcpSvcExtIP, 522 LastIpAddr: tcpSvcExtIP, 523 }, 524 { 525 FirstIpAddr: udpSvcExtIP, 526 LastIpAddr: udpSvcExtIP, 527 }, 528 }, 529 } 530 531 staticMappings := func() (string, error) { 532 str, err := ctx.ExecVppctl("show", "nat44", "static", "mappings") 533 if err != nil { 534 return "", err 535 } 536 // NOTE: This is a workaround, because case changed in VPP 22.02 (tcp -> TCP) 537 return strings.ToLower(str), nil 538 } 539 containTCP := ContainSubstring( 540 "tcp local %s:%d external %s:%d vrf 0 out2in-only", 541 linuxTap2IP, tcpSvcLocalPort, tcpSvcExtIP, tcpSvcExtPort) 542 543 containUDP := ContainSubstring( 544 "udp local %s:%d external %s:%d vrf 0 out2in-only", 545 linuxTap2IP, udpSvcLocalPort, udpSvcExtIP, udpSvcExtPort) 546 547 connectTCP := func() error { 548 return ctx.TestConnection(ms1Name, ms2Name, tcpSvcExtIP, linuxTap2IP, 549 tcpSvcExtPort, tcpSvcLocalPort, false, Tapv2InputNode) 550 } 551 connectUDP := func() error { 552 return ctx.TestConnection(ms1Name, ms2Name, udpSvcExtIP, linuxTap2IP, 553 udpSvcExtPort, udpSvcLocalPort, true, Tapv2InputNode) 554 } 555 556 ctx.StartMicroservice(ms1Name) 557 ctx.StartMicroservice(ms2Name) 558 ctx.Expect(staticMappings()).ShouldNot(SatisfyAny(containTCP, containUDP)) 559 req := ctx.GenericClient().ChangeRequest() 560 err := req.Update( 561 vppTap1, 562 linuxTap1, 563 vppTap2, 564 linuxTap2, 565 ms2DefaultRoute, 566 svcExtIPsProxyArp, 567 natGlobal, 568 natInterface1, 569 natInterface2, 570 tcpSvc, udpSvc, 571 ).Send(context.Background()) 572 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating public and private networks failed") 573 574 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 575 "TAP attached to a newly started microservice1 should be eventually configured") 576 ctx.Eventually(ctx.GetValueStateClb(vppTap2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 577 "TAP attached to a newly started microservice2 should be eventually configured") 578 579 ctx.Expect(staticMappings()).Should(SatisfyAll(containTCP, containUDP)) 580 ctx.Expect(connectTCP()).Should(Succeed()) 581 ctx.Expect(connectUDP()).Should(Succeed()) 582 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 583 584 // remove static mappings 585 req = ctx.GenericClient().ChangeRequest() 586 err = req.Delete( 587 tcpSvc, udpSvc, 588 ).Send(context.Background()) 589 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction removing NAT static mappings failed") 590 591 ctx.Expect(staticMappings()).ShouldNot(SatisfyAny(containTCP, containUDP)) 592 ctx.Expect(connectTCP()).ShouldNot(Succeed()) 593 ctx.Expect(connectUDP()).ShouldNot(Succeed()) 594 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 595 596 // get back the NAT configuration 597 req = ctx.GenericClient().ChangeRequest() 598 err = req.Update( 599 tcpSvc, udpSvc, 600 ).Send(context.Background()) 601 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating NAT static mappings failed") 602 603 ctx.Expect(staticMappings()).Should(SatisfyAll(containTCP, containUDP)) 604 ctx.Expect(connectTCP()).Should(Succeed()) 605 ctx.Expect(connectUDP()).Should(Succeed()) 606 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 607 608 // restart both microservices 609 ctx.StopMicroservice(ms1Name) 610 ctx.StopMicroservice(ms2Name) 611 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_PENDING), 612 "Without microservice, the associated VPP-TAP should be pending") 613 ctx.Eventually(ctx.GetValueStateClb(vppTap2)).Should(Equal(kvscheduler.ValueState_PENDING), 614 "Without microservice, the associated VPP-TAP should be pending") 615 ctx.StartMicroservice(ms1Name) 616 ctx.StartMicroservice(ms2Name) 617 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 618 "VPP-TAP attached to a re-started microservice1 should be eventually configured") 619 ctx.Eventually(ctx.GetValueStateClb(vppTap2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 620 "VPP-TAP attached to a re-started microservice1 should be eventually configured") 621 622 ctx.Expect(staticMappings()).Should(SatisfyAll(containTCP, containUDP)) 623 ctx.Expect(connectTCP()).Should(Succeed()) 624 ctx.Expect(connectUDP()).Should(Succeed()) 625 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 626 } 627 628 // Simulate public and private networks using two microservices and test 629 // source-NAT in-between. Uses deprecated API for NatInterfaces and AddressPool in Nat44Global. 630 func TestSourceNATDeprecatedAPI(t *testing.T) { 631 ctx := Setup(t) 632 defer ctx.Teardown() 633 634 if ctx.VppRelease() >= "22.02" { 635 t.Skipf("SKIP testing of deprecated NAT API for VPP>=22.02") 636 } 637 638 const ( 639 // public network 640 vppTap1Name = "vpp-tap1" 641 vppTap1IP = "80.80.80.20" 642 linuxTap1Name = "linux-tap1" 643 linuxTap1Hostname = "tap" 644 linuxTap1IP = "80.80.80.10" 645 646 // private network 647 vppTap2Name = "vpp-tap2" 648 vppTap2IP = "192.168.1.1" 649 linuxTap2Name = "linux-tap2" 650 linuxTap2Hostname = "tap" 651 linuxTap2IP = "192.168.1.2" 652 653 // nat 654 sNatAddr1 = vppTap1IP 655 sNatAddr2 = "80.80.80.30" 656 sNatAddr3 = "80.80.80.40" 657 658 netMask = "/24" 659 ms1Name = "microservice1" 660 ms2Name = "microservice2" 661 ) 662 663 vppTap1 := &vpp_interfaces.Interface{ 664 Name: vppTap1Name, 665 Type: vpp_interfaces.Interface_TAP, 666 Enabled: true, 667 IpAddresses: []string{vppTap1IP + netMask}, 668 Link: &vpp_interfaces.Interface_Tap{ 669 Tap: &vpp_interfaces.TapLink{ 670 Version: 2, 671 ToMicroservice: MsNamePrefix + ms1Name, 672 }, 673 }, 674 } 675 linuxTap1 := &linux_interfaces.Interface{ 676 Name: linuxTap1Name, 677 Type: linux_interfaces.Interface_TAP_TO_VPP, 678 Enabled: true, 679 IpAddresses: []string{linuxTap1IP + netMask}, 680 HostIfName: linuxTap1Hostname, 681 Link: &linux_interfaces.Interface_Tap{ 682 Tap: &linux_interfaces.TapLink{ 683 VppTapIfName: vppTap1Name, 684 }, 685 }, 686 Namespace: &linux_namespace.NetNamespace{ 687 Type: linux_namespace.NetNamespace_MICROSERVICE, 688 Reference: MsNamePrefix + ms1Name, 689 }, 690 } 691 692 vppTap2 := &vpp_interfaces.Interface{ 693 Name: vppTap2Name, 694 Type: vpp_interfaces.Interface_TAP, 695 Enabled: true, 696 IpAddresses: []string{vppTap2IP + netMask}, 697 Link: &vpp_interfaces.Interface_Tap{ 698 Tap: &vpp_interfaces.TapLink{ 699 Version: 2, 700 ToMicroservice: MsNamePrefix + ms2Name, 701 }, 702 }, 703 } 704 linuxTap2 := &linux_interfaces.Interface{ 705 Name: linuxTap2Name, 706 Type: linux_interfaces.Interface_TAP_TO_VPP, 707 Enabled: true, 708 IpAddresses: []string{linuxTap2IP + netMask}, 709 HostIfName: linuxTap2Hostname, 710 Link: &linux_interfaces.Interface_Tap{ 711 Tap: &linux_interfaces.TapLink{ 712 VppTapIfName: vppTap2Name, 713 }, 714 }, 715 Namespace: &linux_namespace.NetNamespace{ 716 Type: linux_namespace.NetNamespace_MICROSERVICE, 717 Reference: MsNamePrefix + ms2Name, 718 }, 719 } 720 721 ms2DefaultRoute := &linux_l3.Route{ 722 OutgoingInterface: linuxTap2Name, 723 Scope: linux_l3.Route_GLOBAL, 724 DstNetwork: "0.0.0.0/0", 725 GwAddr: vppTap2IP, 726 } 727 728 sourceNat := &vpp_nat.Nat44Global{ 729 Forwarding: true, 730 NatInterfaces: []*vpp_nat.Nat44Global_Interface{ 731 { 732 Name: vppTap1Name, 733 IsInside: false, 734 OutputFeature: true, 735 }, 736 }, 737 AddressPool: []*vpp_nat.Nat44Global_Address{ 738 { 739 Address: sNatAddr1, 740 }, 741 { 742 Address: sNatAddr2, 743 }, 744 { 745 Address: sNatAddr3, 746 }, 747 }, 748 } 749 750 nat44Addresses := func() (string, error) { 751 return ctx.ExecVppctl("show", "nat44", "addresses") 752 } 753 connectTCP := func() error { 754 return ctx.TestConnection(ms2Name, ms1Name, linuxTap1IP, linuxTap1IP, 755 8000, 8000, false, Tapv2InputNode) 756 } 757 connectUDP := func() error { 758 return ctx.TestConnection(ms2Name, ms1Name, linuxTap1IP, linuxTap1IP, 759 8000, 8000, true, Tapv2InputNode) 760 } 761 ping := func() error { 762 return ctx.PingFromMs(ms2Name, linuxTap1IP) 763 } 764 765 ctx.StartMicroservice(ms1Name) 766 ctx.StartMicroservice(ms2Name) 767 ctx.Expect(nat44Addresses()).ShouldNot(SatisfyAny( 768 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 769 req := ctx.GenericClient().ChangeRequest() 770 err := req.Update( 771 vppTap1, 772 linuxTap1, 773 vppTap2, 774 linuxTap2, 775 ms2DefaultRoute, 776 sourceNat, 777 ).Send(context.Background()) 778 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating public and private networks failed") 779 780 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 781 "TAP attached to a newly started microservice1 should be eventually configured") 782 ctx.Eventually(ctx.GetValueStateClb(vppTap2)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 783 "TAP attached to a newly started microservice2 should be eventually configured") 784 785 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 786 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 787 ctx.Expect(ping()).Should(Succeed()) 788 ctx.Expect(connectTCP()).Should(Succeed()) 789 ctx.Expect(connectUDP()).Should(Succeed()) 790 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 791 792 // remove S-NAT configuration 793 req = ctx.GenericClient().ChangeRequest() 794 err = req.Delete( 795 sourceNat, 796 ).Send(context.Background()) 797 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction removing S-NAT failed") 798 799 // check configuration 800 ctx.Expect(nat44Addresses()).ShouldNot(SatisfyAny( 801 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 802 ctx.Expect(ping()).ShouldNot(Succeed()) 803 ctx.Expect(connectTCP()).ShouldNot(Succeed()) 804 ctx.Expect(connectUDP()).ShouldNot(Succeed()) 805 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 806 807 // get back the S-NAT configuration 808 req = ctx.GenericClient().ChangeRequest() 809 err = req.Update( 810 sourceNat, 811 ).Send(context.Background()) 812 ctx.Expect(err).ToNot(HaveOccurred(), "Transaction creating S-NAT failed") 813 814 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 815 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 816 ctx.Expect(ping()).Should(Succeed()) 817 ctx.Expect(connectTCP()).Should(Succeed()) 818 ctx.Expect(connectUDP()).Should(Succeed()) 819 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 820 821 // restart microservice with S-NAT attached 822 ctx.StopMicroservice(ms1Name) 823 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_PENDING), 824 "Without microservice, the associated VPP-TAP should be pending") 825 ctx.StartMicroservice(ms1Name) 826 ctx.Eventually(ctx.GetValueStateClb(vppTap1)).Should(Equal(kvscheduler.ValueState_CONFIGURED), 827 "VPP-TAP attached to a re-started microservice1 should be eventually configured") 828 829 ctx.Expect(nat44Addresses()).Should(SatisfyAll( 830 ContainSubstring(sNatAddr1), ContainSubstring(sNatAddr2), ContainSubstring(sNatAddr3))) 831 ctx.Expect(ping()).Should(Succeed()) 832 ctx.Expect(connectTCP()).Should(Succeed()) 833 ctx.Expect(connectUDP()).Should(Succeed()) 834 ctx.Expect(ctx.AgentInSync()).To(BeTrue(), "Agent is not in-sync") 835 }