diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index 87c2206e90..d75375bfc1 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -846,6 +846,19 @@ void IntfsOrch::doTask(Consumer &consumer) m_syncdIntfses[alias] = intfs_entry; m_vrfOrch->increaseVrfRefCount(vrf_id); } + else if (m_syncdIntfses[alias].vrf_id != vrf_id) + { + if (m_syncdIntfses[alias].ip_addresses.size() == 0) + { + m_vrfOrch->decreaseVrfRefCount(m_syncdIntfses[alias].vrf_id); + m_vrfOrch->increaseVrfRefCount(vrf_id); + m_syncdIntfses[alias].vrf_id = vrf_id; + } + else + { + SWSS_LOG_ERROR("Failed to set interface '%s' to VRF ID '%d' because it has IP addresses associated with it.", alias.c_str(), vrf_id); + } + } } else { diff --git a/tests/mock_tests/intfsorch_ut.cpp b/tests/mock_tests/intfsorch_ut.cpp index c2d65362ae..b7c2bc7397 100644 --- a/tests/mock_tests/intfsorch_ut.cpp +++ b/tests/mock_tests/intfsorch_ut.cpp @@ -330,5 +330,63 @@ namespace intfsorch_test static_cast(gIntfsOrch)->doTask(); ASSERT_EQ(current_create_count + 1, create_rif_count); ASSERT_EQ(current_remove_count + 1, remove_rif_count); + }; + + TEST_F(IntfsOrchTest, IntfsOrchVrfUpdate) + { + //create a new vrf + std::deque entries; + entries.push_back({"Vrf-Blue", "SET", { {"NULL", "NULL"}}}); + auto consumer = dynamic_cast(gVrfOrch->getExecutor(APP_VRF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gVrfOrch)->doTask(); + ASSERT_TRUE(gVrfOrch->isVRFexists("Vrf-Blue")); + auto new_vrf_reference_count = gVrfOrch->getVrfRefCount("Vrf-Blue"); + ASSERT_EQ(new_vrf_reference_count, 0); + + // create an interface + entries.clear(); + entries.push_back({"Loopback2", "SET", {}}); + consumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + IntfsTable m_syncdIntfses = gIntfsOrch->getSyncdIntfses(); + ASSERT_EQ(m_syncdIntfses["Loopback2"].vrf_id, gVirtualRouterId); + + // change vrf and check if it worked + entries.clear(); + entries.push_back({"Loopback2", "SET", { {"vrf_name", "Vrf-Blue"}}}); + consumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + auto new_vrf_updated_reference_count = gVrfOrch->getVrfRefCount("Vrf-Blue"); + ASSERT_EQ(new_vrf_reference_count + 1, new_vrf_updated_reference_count); + m_syncdIntfses = gIntfsOrch->getSyncdIntfses(); + ASSERT_EQ(m_syncdIntfses["Loopback2"].vrf_id, gVrfOrch->getVRFid("Vrf-Blue")); + + // create an interface + entries.clear(); + entries.push_back({"Loopback3", "SET", {}}); + consumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + m_syncdIntfses = gIntfsOrch->getSyncdIntfses(); + ASSERT_EQ(m_syncdIntfses["Loopback3"].vrf_id, gVirtualRouterId); + + // Add IP address to the interface + entries.clear(); + entries.push_back({"Loopback3:3.3.3.3/32", "SET", {{"scope", "global"},{"family", "IPv4"}}}); + consumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + + // change vrf and check it doesn't affect the interface due to existing IP + entries.clear(); + entries.push_back({"Loopback3", "SET", { {"vrf_name", "Vrf-Blue"}}}); + consumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + consumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + m_syncdIntfses = gIntfsOrch->getSyncdIntfses(); + ASSERT_EQ(m_syncdIntfses["Loopback3"].vrf_id, gVirtualRouterId); } } \ No newline at end of file