go.ligato.io/vpp-agent/v3@v3.5.0/tests/e2e/080_vrf_test.go (about) 1 // Copyright (c) 2020 Pantheon.tech 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 "testing" 20 "time" 21 22 . "github.com/onsi/gomega" 23 24 kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api" 25 vrf "go.ligato.io/vpp-agent/v3/plugins/linux/ifplugin/descriptor" 26 "go.ligato.io/vpp-agent/v3/plugins/netalloc/utils" 27 "go.ligato.io/vpp-agent/v3/proto/ligato/kvscheduler" 28 linux_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/linux/interfaces" 29 linux_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/linux/l3" 30 linux_namespace "go.ligato.io/vpp-agent/v3/proto/ligato/linux/namespace" 31 netalloc_api "go.ligato.io/vpp-agent/v3/proto/ligato/netalloc" 32 vpp_interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 33 vpp_l3 "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/l3" 34 . "go.ligato.io/vpp-agent/v3/tests/e2e/e2etest" 35 ) 36 37 // +----------------------------------------------------------------------+ 38 // | VPP | 39 // | +-------------------------------+ +-------------------------------+ | 40 // | | VRF 1 | | VRF 2 | | 41 // | | +-------------------+ | | +-------------------+ | | 42 // | | | 192.168.1.1/24 | | | | 192.168.1.1./24 | | | 43 // | | +---------+---------+ | | +----------+--------+ | | 44 // | +------------------|------------+ +-------------------|-----------+ | 45 // +--------------------|-----------------------------------|-------------+ 46 // Linux | (TAP) | (TAP) 47 // +--------------------|-----------+ +--------------------|-----------+ 48 // | VRF_1 | | | VRF_2 | | 49 // | +---------+---------+ | | +---------+--------+ | 50 // | | 192.168.1.2/24 | | | | 192.168.1.2/24 | | 51 // | +-------------------+ | | +------------------+ | 52 // +--------------------------------+ +--------------------------------+ 53 func TestVRFsWithSameSubnets(t *testing.T) { 54 if !SupportsLinuxVRF() { 55 t.Skip("Linux VRFs are not supported") 56 } 57 58 ctx := Setup(t) 59 defer ctx.Teardown() 60 61 const ( 62 vrf1ID = 1 63 vrf1Mtu uint32 = 1500 64 vrf2ID = 2 65 vrf1Label = "vrf-1" 66 vrf2Label = "vrf-2" 67 vrfVppIP = "192.168.1.1" 68 vrfLinuxIP = "192.168.1.2" 69 vrfSubnetMask = "/24" 70 tapNameSuffix = "-tap" 71 msName = "microservice1" 72 ) 73 74 // TAP interfaces 75 vrf1VppTap := &vpp_interfaces.Interface{ 76 Name: vrf1Label + tapNameSuffix, 77 Type: vpp_interfaces.Interface_TAP, 78 Enabled: true, 79 Vrf: vrf1ID, 80 IpAddresses: []string{vrfVppIP + vrfSubnetMask}, 81 Link: &vpp_interfaces.Interface_Tap{ 82 Tap: &vpp_interfaces.TapLink{ 83 Version: 2, 84 ToMicroservice: MsNamePrefix + msName, 85 }, 86 }, 87 } 88 vrf1LinuxTap := &linux_interfaces.Interface{ 89 Name: vrf1Label + tapNameSuffix, 90 Type: linux_interfaces.Interface_TAP_TO_VPP, 91 Enabled: true, 92 VrfMasterInterface: vrf1Label, 93 IpAddresses: []string{vrfLinuxIP + vrfSubnetMask}, 94 Link: &linux_interfaces.Interface_Tap{ 95 Tap: &linux_interfaces.TapLink{ 96 VppTapIfName: vrf1Label + tapNameSuffix, 97 }, 98 }, 99 Namespace: &linux_namespace.NetNamespace{ 100 Type: linux_namespace.NetNamespace_MICROSERVICE, 101 Reference: MsNamePrefix + msName, 102 }, 103 } 104 vrf2VppTap := &vpp_interfaces.Interface{ 105 Name: vrf2Label + tapNameSuffix, 106 Type: vpp_interfaces.Interface_TAP, 107 Enabled: true, 108 Vrf: vrf2ID, 109 IpAddresses: []string{vrfVppIP + vrfSubnetMask}, 110 Link: &vpp_interfaces.Interface_Tap{ 111 Tap: &vpp_interfaces.TapLink{ 112 Version: 2, 113 ToMicroservice: MsNamePrefix + msName, 114 }, 115 }, 116 } 117 vrf2LinuxTap := &linux_interfaces.Interface{ 118 Name: vrf2Label + tapNameSuffix, 119 Type: linux_interfaces.Interface_TAP_TO_VPP, 120 VrfMasterInterface: vrf2Label, 121 Enabled: true, 122 IpAddresses: []string{vrfLinuxIP + vrfSubnetMask}, 123 Link: &linux_interfaces.Interface_Tap{ 124 Tap: &linux_interfaces.TapLink{ 125 VppTapIfName: vrf2Label + tapNameSuffix, 126 }, 127 }, 128 Namespace: &linux_namespace.NetNamespace{ 129 Type: linux_namespace.NetNamespace_MICROSERVICE, 130 Reference: MsNamePrefix + msName, 131 }, 132 } 133 134 // VRFs 135 vppVrf1 := &vpp_l3.VrfTable{ 136 Id: vrf1ID, 137 Label: vrf1Label, 138 Protocol: vpp_l3.VrfTable_IPV4, 139 } 140 vppVrf2 := &vpp_l3.VrfTable{ 141 Id: vrf2ID, 142 Label: vrf2Label, 143 Protocol: vpp_l3.VrfTable_IPV4, 144 } 145 linuxVrf1 := &linux_interfaces.Interface{ 146 Name: vrf1Label, 147 Type: linux_interfaces.Interface_VRF_DEVICE, 148 Enabled: true, 149 Link: &linux_interfaces.Interface_VrfDev{ 150 VrfDev: &linux_interfaces.VrfDevLink{ 151 RoutingTable: vrf1ID, 152 }, 153 }, 154 Namespace: &linux_namespace.NetNamespace{ 155 Type: linux_namespace.NetNamespace_MICROSERVICE, 156 Reference: MsNamePrefix + msName, 157 }, 158 } 159 linuxVrf1Updated := &linux_interfaces.Interface{ 160 Name: vrf1Label, 161 Type: linux_interfaces.Interface_VRF_DEVICE, 162 Enabled: true, 163 Link: &linux_interfaces.Interface_VrfDev{ 164 VrfDev: &linux_interfaces.VrfDevLink{ 165 RoutingTable: vrf1ID, 166 }, 167 }, 168 Mtu: vrf1Mtu, 169 Namespace: &linux_namespace.NetNamespace{ 170 Type: linux_namespace.NetNamespace_MICROSERVICE, 171 Reference: MsNamePrefix + msName, 172 }, 173 } 174 linuxVrf2 := &linux_interfaces.Interface{ 175 Name: vrf2Label, 176 Type: linux_interfaces.Interface_VRF_DEVICE, 177 Enabled: true, 178 Link: &linux_interfaces.Interface_VrfDev{ 179 VrfDev: &linux_interfaces.VrfDevLink{ 180 RoutingTable: vrf2ID, 181 }, 182 }, 183 Namespace: &linux_namespace.NetNamespace{ 184 Type: linux_namespace.NetNamespace_MICROSERVICE, 185 Reference: MsNamePrefix + msName, 186 }, 187 } 188 189 ctx.StartMicroservice(msName) 190 191 // configure everything in one resync 192 err := ctx.GenericClient().ResyncConfig( 193 vppVrf1, vppVrf2, 194 linuxVrf1, linuxVrf2, 195 vrf1VppTap, vrf1LinuxTap, 196 vrf2VppTap, vrf2LinuxTap, 197 ) 198 ctx.Expect(err).ToNot(HaveOccurred()) 199 200 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 201 ctx.Expect(ctx.GetValueState(vrf1VppTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 202 ctx.Expect(ctx.GetValueState(vrf2LinuxTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 203 ctx.Expect(ctx.GetValueState(vrf2VppTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 204 ctx.Expect(ctx.GetValueState(linuxVrf1)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 205 ctx.Expect(ctx.GetValueState(linuxVrf2)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 206 ctx.Expect(ctx.GetValueState(vppVrf1)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 207 ctx.Expect(ctx.GetValueState(vppVrf2)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 208 209 // vrf mtu check 210 linuxVrf1Msg := ctx.GetValue(linuxVrf1, kvs.SBView).ProtoReflect() 211 linuxVrf1Desc := linuxVrf1Msg.Descriptor().Fields().ByTextName("mtu") 212 linuxVrf1Mtu := linuxVrf1Msg.Get(linuxVrf1Desc).Uint() 213 ctx.Expect(int(linuxVrf1Mtu)).To(SatisfyAny(Equal(vrf.DefaultVrfDevMTU), Equal(vrf.DefaultVrfDevLegacyMTU))) 214 linuxVrf2Msg := ctx.GetValue(linuxVrf2, kvs.SBView).ProtoReflect() 215 linuxVrf2Desc := linuxVrf2Msg.Descriptor().Fields().ByTextName("mtu") 216 linuxVrf2Mtu := linuxVrf2Msg.Get(linuxVrf2Desc).Uint() 217 ctx.Expect(int(linuxVrf2Mtu)).To(SatisfyAny(Equal(vrf.DefaultVrfDevMTU), Equal(vrf.DefaultVrfDevLegacyMTU))) 218 219 // try to ping in both VRFs 220 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).To(Succeed()) 221 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 222 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 223 224 // restart microservice 225 ctx.StopMicroservice(msName) 226 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_PENDING)) 227 ctx.Eventually(ctx.GetValueStateClb(vrf2LinuxTap)).Should(Equal(kvscheduler.ValueState_PENDING)) 228 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 229 230 ctx.StartMicroservice(msName) 231 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 232 ctx.Eventually(ctx.GetValueStateClb(vrf2LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 233 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).To(Succeed()) 234 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 235 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 236 237 // re-create Linux VRF1 238 err = ctx.GenericClient().ChangeRequest(). 239 Delete(linuxVrf1).Send(context.Background()) 240 ctx.Expect(err).ToNot(HaveOccurred()) 241 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).ToNot(Succeed()) 242 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 243 244 err = ctx.GenericClient().ChangeRequest().Update( 245 linuxVrf1Updated, 246 ).Send(context.Background()) 247 ctx.Expect(err).ToNot(HaveOccurred()) 248 249 // vrf 1 mtu re-check 250 linuxVrf1Msg = ctx.GetValue(linuxVrf1, kvs.SBView).ProtoReflect() 251 linuxVrf1Desc = linuxVrf1Msg.Descriptor().Fields().ByTextName("mtu") 252 linuxVrf1Mtu = linuxVrf1Msg.Get(linuxVrf1Desc).Uint() 253 ctx.Expect(uint32(linuxVrf1Mtu)).To(Equal(vrf1Mtu)) 254 255 ctx.Eventually(ctx.PingFromMsClb(msName, vrfVppIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).Should(Succeed()) 256 ctx.Expect(ctx.PingFromMs(msName, vrfVppIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 257 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 258 } 259 260 // +--------------------------------------------------------------------------------+ 261 // | VPP inter-VRF RT: | 262 // | +-------------------------------+ .2.0/24 +-------------------------------+ | 263 // | | VRF 1 | ---------> | VRF 2 | | 264 // | | +-------------------+ | | +-------------------+ | | 265 // | | | 192.168.1.1/24 | | .1.0/24 | | 192.168.2.1./24 | | | 266 // | | +---------+---------+ | <--------- | +----------+--------+ | | 267 // | +------------------|------------+ +-------------------|-----------+ | 268 // +--------------------|---------------------------------------------|-------------+ 269 // Linux | (TAP) | (TAP) 270 // +--------------------|----------+ +---------------------|---------+ 271 // | VRF_1 | | | VRF_2 | | 272 // | +-----------+-------+ | | +-----------+------+ | 273 // | | 192.168.1.2/24 | | | | 192.168.2.2/24 | | 274 // | +-------------------+ | | +------------------+ | 275 // | ^ | | ^ | 276 // | | | | | | 277 // | RT: 192.168.2.0/24 --+ | | RT: 192.168.1.0/24 --+ | 278 // +-------------------------------+ +-------------------------------+ 279 func TestVRFRoutes(t *testing.T) { 280 if !SupportsLinuxVRF() { 281 t.Skip("Linux VRFs are not supported") 282 } 283 284 ctx := Setup(t) 285 defer ctx.Teardown() 286 287 const ( 288 vrf1ID = 1 289 vrf2ID = 2 290 vrf1Label = "vrf-1" 291 vrf2Label = "vrf-2" 292 vrfSubnetMask = "/24" 293 vrf1Subnet = "192.168.1.0" + vrfSubnetMask 294 vrf1VppIP = "192.168.1.1" 295 vrf1LinuxIP = "192.168.1.2" 296 vrf2Subnet = "192.168.2.0" + vrfSubnetMask 297 vrf2VppIP = "192.168.2.1" 298 vrf2LinuxIP = "192.168.2.2" 299 tapNameSuffix = "-tap" 300 msName = "microservice1" 301 ) 302 303 // TAP interfaces 304 vrf1VppTap := &vpp_interfaces.Interface{ 305 Name: vrf1Label + tapNameSuffix, 306 Type: vpp_interfaces.Interface_TAP, 307 Enabled: true, 308 Vrf: vrf1ID, 309 IpAddresses: []string{vrf1VppIP + vrfSubnetMask}, 310 Link: &vpp_interfaces.Interface_Tap{ 311 Tap: &vpp_interfaces.TapLink{ 312 Version: 2, 313 ToMicroservice: MsNamePrefix + msName, 314 }, 315 }, 316 } 317 vrf1LinuxTap := &linux_interfaces.Interface{ 318 Name: vrf1Label + tapNameSuffix, 319 Type: linux_interfaces.Interface_TAP_TO_VPP, 320 Enabled: true, 321 VrfMasterInterface: vrf1Label, 322 IpAddresses: []string{vrf1LinuxIP + vrfSubnetMask}, 323 Link: &linux_interfaces.Interface_Tap{ 324 Tap: &linux_interfaces.TapLink{ 325 VppTapIfName: vrf1Label + tapNameSuffix, 326 }, 327 }, 328 Namespace: &linux_namespace.NetNamespace{ 329 Type: linux_namespace.NetNamespace_MICROSERVICE, 330 Reference: MsNamePrefix + msName, 331 }, 332 } 333 vrf2VppTap := &vpp_interfaces.Interface{ 334 Name: vrf2Label + tapNameSuffix, 335 Type: vpp_interfaces.Interface_TAP, 336 Enabled: true, 337 Vrf: vrf2ID, 338 IpAddresses: []string{vrf2VppIP + vrfSubnetMask}, 339 Link: &vpp_interfaces.Interface_Tap{ 340 Tap: &vpp_interfaces.TapLink{ 341 Version: 2, 342 ToMicroservice: MsNamePrefix + msName, 343 }, 344 }, 345 } 346 vrf2LinuxTap := &linux_interfaces.Interface{ 347 Name: vrf2Label + tapNameSuffix, 348 Type: linux_interfaces.Interface_TAP_TO_VPP, 349 VrfMasterInterface: vrf2Label, 350 Enabled: true, 351 IpAddresses: []string{vrf2LinuxIP + vrfSubnetMask}, 352 Link: &linux_interfaces.Interface_Tap{ 353 Tap: &linux_interfaces.TapLink{ 354 VppTapIfName: vrf2Label + tapNameSuffix, 355 }, 356 }, 357 Namespace: &linux_namespace.NetNamespace{ 358 Type: linux_namespace.NetNamespace_MICROSERVICE, 359 Reference: MsNamePrefix + msName, 360 }, 361 } 362 363 // VRFs 364 vppVrf1 := &vpp_l3.VrfTable{ 365 Id: vrf1ID, 366 Label: vrf1Label, 367 Protocol: vpp_l3.VrfTable_IPV4, 368 } 369 vppVrf2 := &vpp_l3.VrfTable{ 370 Id: vrf2ID, 371 Label: vrf2Label, 372 Protocol: vpp_l3.VrfTable_IPV4, 373 } 374 linuxVrf1 := &linux_interfaces.Interface{ 375 Name: vrf1Label, 376 Type: linux_interfaces.Interface_VRF_DEVICE, 377 Enabled: true, 378 Link: &linux_interfaces.Interface_VrfDev{ 379 VrfDev: &linux_interfaces.VrfDevLink{ 380 RoutingTable: vrf1ID, 381 }, 382 }, 383 Namespace: &linux_namespace.NetNamespace{ 384 Type: linux_namespace.NetNamespace_MICROSERVICE, 385 Reference: MsNamePrefix + msName, 386 }, 387 } 388 linuxVrf2 := &linux_interfaces.Interface{ 389 Name: vrf2Label, 390 Type: linux_interfaces.Interface_VRF_DEVICE, 391 Enabled: true, 392 Link: &linux_interfaces.Interface_VrfDev{ 393 VrfDev: &linux_interfaces.VrfDevLink{ 394 RoutingTable: vrf2ID, 395 }, 396 }, 397 Namespace: &linux_namespace.NetNamespace{ 398 Type: linux_namespace.NetNamespace_MICROSERVICE, 399 Reference: MsNamePrefix + msName, 400 }, 401 } 402 403 // Routes 404 vrf1VppRoute := &vpp_l3.Route{ 405 Type: vpp_l3.Route_INTER_VRF, 406 VrfId: vrf1ID, 407 DstNetwork: vrf2Subnet, 408 NextHopAddr: vrf2LinuxIP, 409 ViaVrfId: vrf2ID, 410 } 411 vrf2VppRoute := &vpp_l3.Route{ 412 Type: vpp_l3.Route_INTER_VRF, 413 VrfId: vrf2ID, 414 DstNetwork: vrf1Subnet, 415 NextHopAddr: vrf1LinuxIP, 416 ViaVrfId: vrf1ID, 417 } 418 vrf1LinuxRoute := &linux_l3.Route{ 419 OutgoingInterface: vrf1Label + tapNameSuffix, 420 Scope: linux_l3.Route_GLOBAL, 421 DstNetwork: vrf2Subnet, 422 GwAddr: vrf1VppIP, 423 } 424 vrf2LinuxRoute := &linux_l3.Route{ 425 OutgoingInterface: vrf2Label + tapNameSuffix, 426 Scope: linux_l3.Route_GLOBAL, 427 DstNetwork: vrf1Subnet, 428 GwAddr: vrf2VppIP, 429 } 430 431 ctx.StartMicroservice(msName) 432 433 // configure everything in one resync 434 err := ctx.GenericClient().ResyncConfig( 435 vppVrf1, vppVrf2, 436 linuxVrf1, linuxVrf2, 437 vrf1VppTap, vrf1LinuxTap, 438 vrf2VppTap, vrf2LinuxTap, 439 vrf1VppRoute, vrf2VppRoute, 440 vrf1LinuxRoute, vrf2LinuxRoute, 441 ) 442 ctx.Expect(err).ToNot(HaveOccurred()) 443 444 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 445 ctx.Expect(ctx.GetValueState(vrf1VppTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 446 ctx.Expect(ctx.GetValueState(vrf2LinuxTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 447 ctx.Expect(ctx.GetValueState(vrf2VppTap)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 448 ctx.Expect(ctx.GetValueState(vrf1VppRoute)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 449 ctx.Expect(ctx.GetValueState(vrf2VppRoute)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 450 ctx.Expect(ctx.GetValueState(vrf1LinuxRoute)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 451 ctx.Expect(ctx.GetValueState(vrf2LinuxRoute)).To(Equal(kvscheduler.ValueState_CONFIGURED)) 452 453 // try to ping across VRFs 454 ctx.Expect(ctx.PingFromMs(msName, vrf2LinuxIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).To(Succeed()) 455 ctx.Expect(ctx.PingFromMs(msName, vrf1LinuxIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 456 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 457 458 // restart microservice 459 ctx.StopMicroservice(msName) 460 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_PENDING)) 461 ctx.Eventually(ctx.GetValueStateClb(vrf2LinuxTap)).Should(Equal(kvscheduler.ValueState_PENDING)) 462 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 463 464 ctx.StartMicroservice(msName) 465 ctx.Eventually(ctx.GetValueStateClb(vrf1LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 466 ctx.Eventually(ctx.GetValueStateClb(vrf2LinuxTap)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 467 ctx.Expect(ctx.PingFromMs(msName, vrf2LinuxIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).To(Succeed()) 468 ctx.Expect(ctx.PingFromMs(msName, vrf1LinuxIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 469 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 470 471 // re-create Linux VRF1 472 err = ctx.GenericClient().ChangeRequest(). 473 Delete(linuxVrf1).Send(context.Background()) 474 ctx.Expect(err).ToNot(HaveOccurred()) 475 ctx.Expect(ctx.PingFromMs(msName, vrf2LinuxIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).ToNot(Succeed()) 476 ctx.Expect(ctx.PingFromMs(msName, vrf1LinuxIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).ToNot(Succeed()) 477 478 err = ctx.GenericClient().ChangeRequest().Update( 479 linuxVrf1, 480 ).Send(context.Background()) 481 ctx.Expect(err).ToNot(HaveOccurred()) 482 ctx.Eventually(ctx.PingFromMsClb(msName, vrf2LinuxIP, PingWithSourceInterface(vrf1Label+tapNameSuffix))).Should(Succeed()) 483 ctx.Expect(ctx.PingFromMs(msName, vrf1LinuxIP, PingWithSourceInterface(vrf2Label+tapNameSuffix))).To(Succeed()) 484 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 485 } 486 487 // Test VRF created externally (i.e. not by the agent). 488 func TestExistingLinuxVRF(t *testing.T) { 489 if !SupportsLinuxVRF() { 490 t.Skip("Linux VRFs are not supported") 491 } 492 493 ctx := Setup(t) 494 defer ctx.Teardown() 495 496 SetDefaultConsistentlyDuration(3 * time.Second) 497 SetDefaultConsistentlyPollingInterval(time.Second) 498 499 const ( 500 vrfName = "existing-vrf" 501 vrfHostName = "vrf" 502 vrfRT = 10 503 vrfIface1Name = "existing-dummy1" 504 vrfIface1HostName = "dummy1" 505 vrfIface2Name = "dummy2" 506 ipAddr1 = "192.168.7.7" 507 ipAddr2 = "10.7.7.7" 508 ipAddr3 = "172.16.7.7" 509 netMask = "/24" 510 ) 511 512 existingVrf := &linux_interfaces.Interface{ 513 Name: vrfName, 514 Type: linux_interfaces.Interface_EXISTING, 515 Enabled: true, 516 HostIfName: vrfHostName, 517 LinkOnly: true, 518 } 519 520 existingIface1 := &linux_interfaces.Interface{ 521 Name: vrfIface1Name, 522 Type: linux_interfaces.Interface_EXISTING, 523 Enabled: true, 524 LinkOnly: true, // wait for IP addresses, do not configure them 525 IpAddresses: []string{ipAddr1 + netMask, ipAddr2 + netMask}, 526 HostIfName: vrfIface1HostName, 527 VrfMasterInterface: vrfName, 528 } 529 530 iface2 := &linux_interfaces.Interface{ 531 Name: vrfIface2Name, 532 Type: linux_interfaces.Interface_DUMMY, 533 Enabled: true, 534 IpAddresses: []string{ipAddr3 + netMask}, 535 VrfMasterInterface: vrfName, 536 } 537 538 ipAddr1Key := linux_interfaces.InterfaceAddressKey( 539 vrfIface1Name, ipAddr1+netMask, netalloc_api.IPAddressSource_EXISTING) 540 ipAddr2Key := linux_interfaces.InterfaceAddressKey( 541 vrfIface1Name, ipAddr2+netMask, netalloc_api.IPAddressSource_EXISTING) 542 ipAddr3Key := linux_interfaces.InterfaceAddressKey( 543 vrfIface2Name, ipAddr3+netMask, netalloc_api.IPAddressSource_STATIC) 544 iface1InVrfKey := linux_interfaces.InterfaceVrfKey(vrfIface1Name, vrfName) 545 iface2InVrfKey := linux_interfaces.InterfaceVrfKey(vrfIface2Name, vrfName) 546 547 // configure everything in one resync 548 err := ctx.GenericClient().ResyncConfig( 549 existingVrf, 550 existingIface1, 551 iface2, 552 ) 553 ctx.Expect(err).ToNot(HaveOccurred()) 554 555 // the referenced VRF with interface does not exist yet 556 ctx.Expect(ctx.GetValueState(existingVrf)).To(Equal(kvscheduler.ValueState_PENDING)) 557 ctx.Expect(ctx.GetValueState(existingIface1)).To(Equal(kvscheduler.ValueState_PENDING)) 558 ctx.Expect(ctx.GetValueState(iface2)).To(Equal(kvscheduler.ValueState_CONFIGURED)) // created but not in VRF yet 559 ctx.Expect(ctx.GetDerivedValueState(iface2, iface2InVrfKey)).To(Equal(kvscheduler.ValueState_PENDING)) 560 561 ifHandler := ctx.Agent.LinuxInterfaceHandler() 562 563 // create referenced VRF using netlink (without the interface inside it for now) 564 err = ifHandler.AddVRFDevice(vrfHostName, vrfRT) 565 ctx.Expect(err).To(BeNil()) 566 err = ifHandler.SetInterfaceUp(vrfHostName) 567 ctx.Expect(err).To(BeNil()) 568 569 ctx.Eventually(ctx.GetValueStateClb(existingVrf)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 570 ctx.Expect(ctx.GetValueMetadata(existingVrf, kvs.CachedView)).To( 571 HaveKeyWithValue(BeEquivalentTo("VrfDevRT"), BeEquivalentTo(vrfRT))) 572 ctx.Eventually(ctx.GetDerivedValueStateClb(iface2, iface2InVrfKey)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 573 ctx.Expect(ctx.GetValueMetadata(iface2, kvs.CachedView)).To( 574 HaveKeyWithValue(BeEquivalentTo("VrfMasterIf"), BeEquivalentTo(vrfName))) 575 ctx.Eventually(ctx.GetDerivedValueStateClb(iface2, ipAddr3Key)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 576 ctx.Consistently(ctx.GetValueStateClb(existingIface1)).Should(Equal(kvscheduler.ValueState_PENDING)) 577 578 // re-check metadata after resync 579 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 580 ctx.Expect(ctx.GetValueMetadata(existingVrf, kvs.CachedView)).To( 581 HaveKeyWithValue(BeEquivalentTo("VrfDevRT"), BeEquivalentTo(vrfRT))) 582 ctx.Expect(ctx.GetValueMetadata(iface2, kvs.CachedView)).To( 583 HaveKeyWithValue(BeEquivalentTo("VrfMasterIf"), BeEquivalentTo(vrfName))) 584 585 // create vrfIface1 but do not put it into VRF yet 586 err = ifHandler.AddDummyInterface(vrfIface1HostName) 587 ctx.Expect(err).To(BeNil()) 588 err = ifHandler.SetInterfaceUp(vrfIface1HostName) 589 ctx.Expect(err).To(BeNil()) 590 591 ctx.Eventually(ctx.GetValueStateClb(existingIface1)).Should(Equal(kvscheduler.ValueState_CONFIGURED)) 592 ctx.Expect(ctx.GetValueMetadata(existingIface1, kvs.CachedView)).To( 593 HaveKeyWithValue(BeEquivalentTo("VrfMasterIf"), BeEquivalentTo(vrfName))) 594 ctx.Expect(ctx.GetDerivedValueState(existingIface1, iface1InVrfKey)).To(Equal(kvscheduler.ValueState_PENDING)) 595 596 // put interface into VRF (without IPs for now) 597 err = ifHandler.PutInterfaceIntoVRF(vrfIface1HostName, vrfHostName) 598 ctx.Expect(err).To(BeNil()) 599 600 ctx.Eventually(ctx.GetDerivedValueStateClb(existingIface1, iface1InVrfKey)). 601 Should(Equal(kvscheduler.ValueState_CONFIGURED)) 602 ctx.Consistently(ctx.GetDerivedValueStateClb(existingIface1, ipAddr1Key)). 603 Should(Equal(kvscheduler.ValueState_PENDING)) 604 ctx.Consistently(ctx.GetDerivedValueStateClb(existingIface1, ipAddr2Key)). 605 Should(Equal(kvscheduler.ValueState_PENDING)) 606 607 // re-check metadata after resync 608 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 609 ctx.Expect(ctx.GetValueMetadata(existingVrf, kvs.CachedView)).To( 610 HaveKeyWithValue(BeEquivalentTo("VrfDevRT"), BeEquivalentTo(vrfRT))) 611 ctx.Expect(ctx.GetValueMetadata(existingIface1, kvs.CachedView)).To( 612 HaveKeyWithValue(BeEquivalentTo("VrfMasterIf"), BeEquivalentTo(vrfName))) 613 ctx.Expect(ctx.GetValueMetadata(iface2, kvs.CachedView)).To( 614 HaveKeyWithValue(BeEquivalentTo("VrfMasterIf"), BeEquivalentTo(vrfName))) 615 616 // add ipAddr1 617 ipAddr, _, err := utils.ParseIPAddr(ipAddr1+netMask, nil) 618 ctx.Expect(err).ToNot(HaveOccurred()) 619 err = ifHandler.AddInterfaceIP(vrfIface1HostName, ipAddr) 620 ctx.Expect(err).ToNot(HaveOccurred()) 621 622 ctx.Eventually(ctx.GetDerivedValueStateClb(existingIface1, ipAddr1Key)). 623 Should(Equal(kvscheduler.ValueState_CONFIGURED)) 624 ctx.Consistently(ctx.GetDerivedValueStateClb(existingIface1, ipAddr2Key)). 625 Should(Equal(kvscheduler.ValueState_PENDING)) 626 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 627 628 // add ipAddr2 629 ipAddr, _, err = utils.ParseIPAddr(ipAddr2+netMask, nil) 630 ctx.Expect(err).ToNot(HaveOccurred()) 631 err = ifHandler.AddInterfaceIP(vrfIface1HostName, ipAddr) 632 ctx.Expect(err).ToNot(HaveOccurred()) 633 634 ctx.Eventually(ctx.GetDerivedValueStateClb(existingIface1, ipAddr1Key)). 635 Should(Equal(kvscheduler.ValueState_CONFIGURED)) 636 ctx.Eventually(ctx.GetDerivedValueStateClb(existingIface1, ipAddr2Key)). 637 Should(Equal(kvscheduler.ValueState_CONFIGURED)) 638 ctx.Expect(ctx.AgentInSync()).To(BeTrue()) 639 640 // cleanup 641 req := ctx.GenericClient().ChangeRequest() 642 err = req.Delete( 643 existingVrf, 644 existingIface1, 645 iface2, 646 ).Send(context.Background()) 647 ctx.Expect(err).ToNot(HaveOccurred()) 648 err = ifHandler.DeleteInterface(vrfIface1HostName) 649 ctx.Expect(err).ToNot(HaveOccurred()) 650 err = ifHandler.DeleteInterface(vrfHostName) 651 ctx.Expect(err).ToNot(HaveOccurred()) 652 }