diff --git a/orchagent/routeorch.cpp b/orchagent/routeorch.cpp index ef6da962e3..0ea657a60d 100644 --- a/orchagent/routeorch.cpp +++ b/orchagent/routeorch.cpp @@ -2433,13 +2433,21 @@ bool RouteOrch::removeRoute(RouteBulkContext& ctx) size_t creating = gRouteBulker.creating_entries_count(route_entry); if (it_route == it_route_table->second.end() && creating == 0) { - if (it_route_table->second.size() == 0) - { + /* + * Clean up the VRF routing table if + * 1. there is no routing entry in the VRF routing table and + * 2. there is no pending bulk creation routing entry in gRouteBulker + * The ideal way of the 2nd condition is to check pending bulk creation entries of a certain VRF. + * However, we can not do that unless going over all entries in gRouteBulker. + * So, we use above strict conditions here + */ + if (it_route_table->second.size() == 0 && gRouteBulker.creating_entries_count() == 0) + { m_syncdRoutes.erase(vrf_id); m_vrfOrch->decreaseVrfRefCount(vrf_id); - } - SWSS_LOG_INFO("Failed to find route entry, vrf_id 0x%" PRIx64 ", prefix %s\n", vrf_id, - ipPrefix.to_string().c_str()); + } + SWSS_LOG_INFO("Failed to find route entry, vrf_id 0x%" PRIx64 ", prefix %s\n", vrf_id, + ipPrefix.to_string().c_str()); return true; } diff --git a/orchagent/swssnet.h b/orchagent/swssnet.h index 82b5b6f94f..8084b7fb4e 100644 --- a/orchagent/swssnet.h +++ b/orchagent/swssnet.h @@ -21,6 +21,7 @@ inline static sai_ip_address_t& copy(sai_ip_address_t& dst, const IpAddress& src switch(sip.family) { case AF_INET: + memset((void*)&dst.addr, 0, sizeof(dst.addr)); dst.addr_family = SAI_IP_ADDR_FAMILY_IPV4; dst.addr.ip4 = sip.ip_addr.ipv4_addr; break; @@ -41,6 +42,7 @@ inline static sai_ip_prefix_t& copy(sai_ip_prefix_t& dst, const IpPrefix& src) switch(ia.family) { case AF_INET: + memset((void*)&dst, 0, sizeof(dst)); dst.addr_family = SAI_IP_ADDR_FAMILY_IPV4; dst.addr.ip4 = ia.ip_addr.ipv4_addr; dst.mask.ip4 = ma.ip_addr.ipv4_addr; @@ -62,6 +64,7 @@ inline static sai_ip_prefix_t& copy(sai_ip_prefix_t& dst, const IpAddress& src) switch(sip.family) { case AF_INET: + memset((void*)&dst, 0, sizeof(dst)); dst.addr_family = SAI_IP_ADDR_FAMILY_IPV4; dst.addr.ip4 = sip.ip_addr.ipv4_addr; dst.mask.ip4 = 0xFFFFFFFF; diff --git a/tests/mock_tests/routeorch_ut.cpp b/tests/mock_tests/routeorch_ut.cpp index 043b7b6b0a..f66fc9ac38 100644 --- a/tests/mock_tests/routeorch_ut.cpp +++ b/tests/mock_tests/routeorch_ut.cpp @@ -306,6 +306,11 @@ namespace routeorch_test {"mac_addr", "00:00:00:00:00:00" }}); intfTable.set("Ethernet4:11.0.0.1/32", { { "scope", "global" }, { "family", "IPv4" }}); + intfTable.set("Ethernet8", { {"NULL", "NULL" }, + {"vrf_name", "Vrf1"}, + {"mac_addr", "00:00:00:00:00:00" }}); + intfTable.set("Ethernet8:20.0.0.1/24", { { "scope", "global" }, + { "family", "IPv4" }}); gIntfsOrch->addExistingData(&intfTable); static_cast(gIntfsOrch)->doTask(); @@ -552,4 +557,30 @@ namespace routeorch_test ASSERT_EQ(current_create_count, create_route_count); ASSERT_EQ(current_set_count, set_route_count); } + + TEST_F(RouteOrchTest, RouteOrchTestVrfRoute) + { + std::deque entries; + entries.push_back({"Vrf2", "SET", { {"vni", "500200"}}}); + auto vrfConsumer = dynamic_cast(gVrfOrch->getExecutor(APP_VRF_TABLE_NAME)); + vrfConsumer->addToSync(entries); + static_cast(gVrfOrch)->doTask(); + entries.clear(); + entries.push_back({"Ethernet8", "SET", { {"vrf_name", "Vrf2"}}}); + auto intfConsumer = dynamic_cast(gIntfsOrch->getExecutor(APP_INTF_TABLE_NAME)); + intfConsumer->addToSync(entries); + static_cast(gIntfsOrch)->doTask(); + auto routeConsumer = dynamic_cast(gRouteOrch->getExecutor(APP_ROUTE_TABLE_NAME)); + entries.clear(); + entries.push_back({"Vrf2:fe80::/64", "DEL", {}}); + entries.push_back({"Vrf2:20.0.0.0/24", "DEL", {}}); + entries.push_back({"Vrf2:fe80::/64", "SET", { {"protocol", "kernel"}, + {"nexthop", "::"}, + {"ifname", "Ethernet8"}}}); + entries.push_back({"Vrf2:20.0.0.0/24", "SET", { {"protocol", "kernel"}, + {"nexthop", "0.0.0.0"}, + {"ifname", "Ethernet8"}}}); + routeConsumer->addToSync(entries); + static_cast(gRouteOrch)->doTask(); + } }