From 5d3987542106b3049a879bd9a8b2e3d6c6e44fd3 Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Tue, 19 Apr 2016 17:28:22 +0530 Subject: [PATCH] Handle delete marked Vrf during ServiceVlan activation If VRF is marked for delete during ServiceVlan activation, treat it as ServiceVlan deactivation. Add UT for this case. Change-Id: I51fae99ae9a1935991cf370d66078e86dfb81015 Closes-Bug: #1568030 --- src/vnsw/agent/oper/test/test_intf.cc | 74 +++++++++++++++++++++++++++ src/vnsw/agent/oper/vm_interface.cc | 6 ++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/vnsw/agent/oper/test/test_intf.cc b/src/vnsw/agent/oper/test/test_intf.cc index e9c5426cfda..31bb46f1ed1 100644 --- a/src/vnsw/agent/oper/test/test_intf.cc +++ b/src/vnsw/agent/oper/test/test_intf.cc @@ -2007,6 +2007,80 @@ TEST_F(IntfTest, VmPortServiceVlanAdd_3) { EXPECT_FALSE(VrfFind("vrf2")); } +/* Test to verify behavior of ServiceVlan activation when service-vrf is + * delete marked.*/ +TEST_F(IntfTest, VmPortServiceVlanVrfDelete_1) { + struct PortInfo input[] = { + {"vnet1", 1, "1.1.1.10", "00:00:00:01:01:01", 1, 1}, + }; + + client->Reset(); + CreateVmportEnv(input, 1); + client->WaitForIdle(); + EXPECT_TRUE(VmPortActive(input, 0)); + + AddVn("vn2", 2); + AddVrf("vrf2", 2); + AddLink("virtual-network", "vn2", "routing-instance", "vrf2"); + //Add service vlan for vnet1 + client->WaitForIdle(); + AddVmPortVrf("vmvrf1", "2.2.2.100", 10); + AddLink("virtual-machine-interface-routing-instance", "vmvrf1", + "routing-instance", "vrf2"); + AddLink("virtual-machine-interface-routing-instance", "vmvrf1", + "virtual-machine-interface", "vnet1"); + + client->WaitForIdle(); + Ip4Address service_ip = Ip4Address::from_string("2.2.2.100"); + EXPECT_TRUE(RouteFind("vrf2", service_ip, 32)); + EXPECT_TRUE(VmPortServiceVlanCount(1, 1)); + client->WaitForIdle(); + + //Mark service VRF as deleted + VrfEntry *vrf = VrfGet("vrf2", false); + EXPECT_TRUE(vrf != NULL); + vrf->MarkDelete(); + + //Trigger change on VMI (we are doing this by associating secondary IP) + AddInstanceIp("instance2", input[0].vm_id, "3.1.1.10"); + AddLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance2"); + client->WaitForIdle(); + + //Clear the delete flag from service VRF so that it can be deleted + vrf->ClearDelete(); + + //Verify that service vlan count is still 1 and route is still present in + //service VRF + EXPECT_TRUE(VmPortServiceVlanCount(1, 1)); + EXPECT_TRUE(RouteFind("vrf2", service_ip, 32)); + + //Clean-up + DelLink("virtual-machine-interface", input[0].name, + "instance-ip", "instance2"); + DelInstanceIp("instance2"); + //Delete config for vnet1, forcing interface to deactivate + //verify that route and service vlan map gets cleaned up + DelNode("virtual-machine-interface", input[0].name); + client->WaitForIdle(); + EXPECT_FALSE(RouteFind("vrf2", service_ip, 32)); + client->WaitForIdle(); + + DelLink("virtual-machine-interface-routing-instance", "vmvrf1", + "routing-instance", "vrf2"); + DelLink("virtual-machine-interface-routing-instance", "vmvrf1", + "virtual-machine-interface", "vnet1"); + DelVmPortVrf("vmvrf1"); + client->WaitForIdle(); + DelLink("virtual-network", "vn2", "routing-instance", "vrf2"); + DelVrf("vrf2"); + DelVn("vn2"); + DeleteVmportEnv(input, 1, true); + client->WaitForIdle(); + EXPECT_FALSE(VrfFind("vrf1")); + EXPECT_FALSE(VrfFind("vrf2")); +} + //Add and delete static route TEST_F(IntfTest, IntfStaticRoute) { struct PortInfo input[] = { diff --git a/src/vnsw/agent/oper/vm_interface.cc b/src/vnsw/agent/oper/vm_interface.cc index 672790d2179..9cebb5d3d81 100644 --- a/src/vnsw/agent/oper/vm_interface.cc +++ b/src/vnsw/agent/oper/vm_interface.cc @@ -4194,7 +4194,11 @@ void VmInterface::ServiceVlan::Activate(VmInterface *interface, InterfaceTable *table = static_cast(interface->get_table()); VrfEntry *vrf = table->FindVrfRef(vrf_name_); - assert(vrf); + if (!vrf) { + /* If vrf is delete marked VMI will eventually get delete of link which + * will trigger ServiceVlan::DeActivate */ + return; + } if (label_ == MplsTable::kInvalidLabel) { VlanNH::Create(interface->GetUuid(), tag_, vrf_name_, smac_, dmac_);